Skip to content

Choosing a Language

William Wood edited this page Feb 22, 2024 · 14 revisions

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

Language Overview

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.

Java

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

Kotlin

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

Python

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

MATLAB

Attribute Pros Cons
It's MATLAB You're not using it It's possible to use it
Clone this wiki locally