-
Notifications
You must be signed in to change notification settings - Fork 9
Choosing a Language
Since JISA
can be used in a multitude of different languages, it can be quite hard to pick which one to use!
This page will hopefully serve to help you decide out of the three main "target" languages:
- Java
- Kotlin
- Python
Out of the three target languages, we can classify them into two camps. Python and Kotlin are what I'd call "modern" whereas Java I would call "traditional" (as in similar in style to C/C++). What this boils down to is the "intelligence" of the compiler/interpreter in each case. Modern languages tend to be able to infer and/or assume things that older-style purposefully don't in order to make you explicitly state everything.
The result is that Kotlin and Python are more concise, allowing you to write your code quicker. However, the obvious drawback to this is that it's harder for someone else to come along and understand what you've done (unless you extensively comment your code of course). Java, on the other hand, requires you to explicitly state E V E R Y T H I N G
. The main drawback being the added effort needed to write the code, but the plus side being that your code will make it painfully obvious what everything is doing, to the extent that commenting is much less of a priority.
The difference between Python and Kotlin then comes down to syntax. They both employ a simple syntax compared to Java but Kotlin stays closer to "tradition" in style than Python. The two most notable examples of this are variable declarations and code-blocks.
When first using a variable in Kotlin you use either the val
or var
(depending on whether it should be constant or not) keyword to indicate that you have declared a new variable and not overwriting the value of an already existing variable. In Python you do not use any keyword to indicate this, you just state the name as if the variable already exists. Some people prefer this, and some don't. Either you argue that not having it is a simplification or you argue that having it adds a nice safe-guard against accidentally assigning a value to a new variable as well as being an indicator of where a variable first begins its life. [There's also some technical issues with not having a declaration keyword in terms of scoping which ends up causing Python to resort to using a global
keyword which is generally considered to be a moral defeat by most programmers (almost as much as branching statements). However, this may be a bit niche many simple applications.]
For code blocks, Kotlin retains the use of curly braces { }
to define where a block begins and ends as well as regular brackets for code-block arguments. This is a common trope across many languages and thus will be familiar to many people. Python, on the other-hand, uses its edge-lord bracketless indentation-only approach. Some people, like myself, absolutely loathe this (saying it makes it hard to tell when blocks begin and end as well as stifling the possibility of introducing more complex structures), others think it's a nice simplification. Really it's a matter of style, and we each have our own in the end.
To get a good feel of this let's take a look at the same program written in each language. When run, each of these programs will produce the same output:
and after running the sweep by pressing the "Run Sweep" button:
Java
// Import JISA classes
import jisa.Util;
import jisa.maths.Range;
import jisa.addresses.GPIBAddress;
import jisa.devices.smu.K2450;
import jisa.devices.interfaces.SMU;
import jisa.results.Column;
import jisa.results.ResultList;
import jisa.gui.*;
public class Main {
// Define results structure
public static Column<Double> VOLTAGE = Column.ofDoubles("Voltage", "V");
public static Column<Double> CURRENT = Column.ofDoubles("Current", "A");
public static ResultList results = new ResultList(VOLTAGE, CURRENT);
public static void main(String[] args) {
// Create user interface elements
Table table = new Table("Table of Results", results);
Plot plot = new Plot("Plot of Results", results);
Grid mainWindow = new Grid("Voltage Sweep", table, plot);
// Add button to toolbar to call run() method when clicked
mainWindow.addToolbarButton("Run Sweep", Main::run);
// We want the program to terminate if the window is closed
mainWindow.setExitOnClose(true);
mainWindow.show();
}
public static void run() {
SMU smu = GUI.connectTo(K2450.class, new GPIBAddress(25));
if (smu == null) {
return;
}
try {
// Clear out old results and turn on the SMU
results.clear();
smu.turnOn();
for (double v : Range.linear(0, 60)) {
smu.setVoltage(v);
Util.sleep(500);
// Take measurements and record to results as new row
results.addRow(row -> {
row.set(VOLTAGE, smu.getVoltage());
row.set(CURRENT, smu.getCurrent());
});
}
} catch (Exception e) {
// If anything goes wrong, show error message
GUI.showException(e);
} finally {
// Turn SMU off and disconnect, regardless of success
smu.turnOff();
smu.close();
}
}
}
Kotlin
import jisa.Util
import jisa.maths.Range
import jisa.addresses.GPIBAddress
import jisa.devices.smu.K2450
import jisa.devices.interfaces.SMU
import jisa.results.Column
import jisa.results.ResultList
import jisa.gui.*
val VOLTAGE = Column.ofDoubles("Voltage", "V")
val CURRENT = Column.ofDoubles("Current", "A")
val results = ResultList(VOLTAGE, CURRENT)
fun main() {
val table = Table("Table of Results", results)
val plot = Plot("Plot of Results", results)
val mainWindow = Grid("Voltage Sweep", table, plot)
mainWindow.addToolbarButton("Run Sweep", ::run)
mainWindow.setExitOnClose(true)
mainWindow.show()
}
fun run() {
val smu: SMU
try {
smu = K2450(GPIBAddress(25))
} catch (e: Exception) {
GUI.showException(e)
return
}
try {
results.clear()
smu.turnOn()
for (v in Range.linear(0, 60)) {
smu.voltage = v
Util.sleep(500)
results.addRow {
it[VOLTAGE] = smu.voltage
it[CURRENT] = smu.current
}
}
} catch (e: Exception) {
GUI.showException(e)
} finally {
smu.turnOff()
smu.close()
}
}
Python
# Import and startup PyJISA
import pyjisa; pyjisa.load();
# Import JISA classes
from jisa import Util
from jisa.maths import Range
from jisa.addresses import GPIBAddress
from jisa.devices.smu import K2450
from jisa.results import ResultList, Column
from jisa.gui import GUI, Table, Plot, Grid
from java.lang import Exception
# Define results structure
VOLTAGE = Column.ofDoubles("Voltage", "V")
CURRENT = Column.ofDoubles("Current", "A")
results = ResultList(VOLTAGE, CURRENT)
def main():
# Create GUI elements
table = Table("Table of Results", results)
plot = Plot("Plot of Results", results)
mainWindow = Grid("Voltage Sweep", table, plot)
# Add button to toolbar to call run() when clicked
mainWindow.addToolbarButton("Run Sweep", run)
# We want the program to end when the window is closed
mainWindow.setExitOnClose(True)
mainWindow.show()
# Tell python to wait until exit() is called
GUI.waitForExit()
def run():
# Attempt to connect to SMU
try:
smu = K2450(GPIBAddress(25))
except Exception as e:
GUI.showException(e)
return
# Run the measurement routine
try:
results.clear()
smu.turnOn()
for v in Range.linear(0, 60):
smu.setVoltage(v)
Util.sleep(500)
results.mapRow({
VOLTAGE: smu.getVoltage(),
CURRENT: smu.getCurrent()
})
except Exception as e:
GUI.showException(e)
finally:
smu.turnOff()
smu.close()
main()
As a general overview:
- If you are used to traditional languages like C/C++, then you will want to use Java (it's also a very employable skill...).
- If you are looking to extend the
JISA
library itself you MUST use Java (for my sanity if nothing else). - If you are used to more modern-style languages (like Python), you probably want Kotlin.
- You probably only want Python if you're already very used to it since it's more of a pain to set-up for using
JISA
than Kotlin (and comes with a raft of draw-backs compared to Kotlin despite being very similar). - Performance hits will become quite noticeable in Python if you intend to do anything with large amounts of data.
- If I catch you writing a
JISA
program in MATLAB I will get you arrested for high treason.
Attribute | Pros | Cons |
---|---|---|
Verbose | Makes it easier to follow the logic of a program | Makes your code longer to write |
Statically Typed | Makes it easy to spot where a variable is first declared and what type it is, also faster to run | Extra words to write and think about, generics can be confusing |
Traditional Syntax | Tried and tested, very standard and similar to other languages, robust | Can look scary since it looks like C++ |
Input/Output Streams | Gives more precise control over terminal input and output | Slightly more complex to use |
Strong Object Orientation | Forces you into good practices, leads to well organised code | Can seem a bit much for simpler programs |
Compiled | Runs fast and can be compiled into a single executable .jar file |
Code needs to be compiled when changed |
Attribute | Pros | Cons |
---|---|---|
Concise | Makes it quicker to write programs | Can make it harder to follow the logic of your code |
Static Inferred Typing | Fast to run, still easy to spot declarations but removes need to remember type names | Harder to tell which variable is of what type |
Simplified Traditional Syntax | Very standard and similar to other tried and tested languages but more human readable than most | None really, unless you are conditioned to expect Python syntax |
Input/Output Methods + Streams | Far simpler to use terminal input/output than in Java but you can also use streams like in Java if you wish | None, best of both worlds really. |
Fair Object Orientation | Forces you into good practices, leads to well organised code but doesn't require your main method to be inside a class | None really |
Compiled or Interpreted | Your choice, you can compile to run fast or write Kotlin scripts that run in an interpreter | None, you can choose whatever best suits your needs |
Attribute | Pros | Cons |
---|---|---|
Concise | Makes it quicker to write programs | Can make it harder to follow the logic of your code |
Dynamically Typed | No need to explicitly declare variables | Hard to see where variables are first declared, what type they are and gives rise to scoping issues |
Reinvented Syntax | Designed to be human readable, commonly used in scientific community | Completely different from almost all other languages, sacrifices functionality, can become messy easily |
Input/Output Methods | Far simpler to use terminal input/output than in Java | Less control and precision |
Weak Object Orientation | Lets you do it your way(tm) | Missing some very useful OO features, often leads to huge messes of code without proper discipline |
Interpreted | No compilation needed, allows straight-forward interactive shell usage | Slow and memory-hungry execution, up to roughly 30x slower than the likes of Java/Kotlin |
Attribute | Pros | Cons |
---|---|---|
It's MATLAB | You're not using it | It's possible to use it |
- Getting Started
- Object Orientation
- Choosing a Language
- Using JISA in Java
- Using JISA in Python
- Using JISA in Kotlin
- Exceptions
- Functions as Objects
- Instrument Basics
- SMUs
- Thermometers (and old TCs)
- PID and Temperature Controllers
- Lock-Ins
- Power Supplies
- Pre-Amplifiers
- Writing New Drivers