Today I called Python from QML

I always use QML with Qt Quick for GUI programming. It’s incredible both for prototyping and larger applications. I find it easy to express myself in QML, because it is so flexible. It’s declarative. You can bind a button’s position to the value of a slider in just one line. Not that you’d ever want to do that, but it shows how easy it is to connect objects together. I really wish the web was written in QML and not HTML.

Typically, I’m working with both QML and C++. I write high performance and visualization code in C++ and define GUI elements in QML. But today I wanted to use QML and Python together because I’m working on an experiment browser for our lab. Not an experimental browser, but an application that lists all experiments and makes it easy to export data for further analysis.

We have decided to organize the experiments as HDF5 files. To read these files I want to use the Python HDF5 package. I could use the C++ HDF5 library, but using Python should hopefully make the application more easily maintainable in the future, also for non-C++ coders in our lab. To do this, I figured there were two possibilities: PyQt and PyOtherSide.

In brief (and a bit simplified), PyQt calls Qt code from Python, while PyOtherSide calls Python code from QML. The difference isn’t really that big, so it just boils down to where the business logic resides. I figured that PyOtherSide would be the better option for us, because it allows everyone to help out with the Python code without learning anything about Qt. PyQt would on the other hand require everyone to have at least some understanding of the Qt framework to make changes in the code. More of the business logic will have to take place in QML, though.

PyOtherSide is really simple in use. You just define a Python object in QML and this loads modules and files from the Qt resource file (qrc). Once loaded, Python functions can be called from QML and their results are automatically converted from Python types to Qt types:

import io.thp.pyotherside 1.3

Python {
    property bool ready: false
    
    function loadData() {
        if(!ready) {
            return
        }
        call("hdf5_loader.read_experiments", [], parseData)
    }

    function parseData(result) {
        for(var i in result) {
            var element = result[i]
            tableModel.append(element)
        }
    }
    
    Component.onCompleted: {
        addImportPath(Qt.resolvedUrl("."))
        importModule("hdf5_loader", function() {
            ready = true
        })
    }
}

As you can see, all Python calls are asynchronous. You can also make synchronous Python calls, but this is not recommended because it could cause the QML GUI to stall while waiting for the results.

The Python code in this case is just a simple function that returns a dictionary:

def read_experiments():
    return {{"experimenter": "test", 
             "date": "2015-10-26"}, 
            {"experimenter": "test2", 
             "date": "2015-10-25"}}

Now I just need to make this code read and parse real HDF5 files.

Straight from the source: NEURON’s incredible backwards compatibility

NEURON is a neural simulator, but it’s not just another neural network application. NEURON has been around much longer than your fancy deep learning software. It was first released in 1994, although some of it’s early code and concepts seem to stem from the 70’s and 80’s. In fact, NEURON is not a machine learning library at all. It simulates real neurons. It uses real morphologies and ion channel densities to reproduce experiments. Some labs even use machine learning algorithms to fit the parameters of their NEURON models. NEURON is one of the workhorses of the computational branch of the Human Brain Project and the core engine in the Blue Brain Project.

But the age of NEURON is starting to show in its source code. Because some things are a bit awkward when working with this simulator I decided to peek at its sources. Just to see what this old engine looks like on the inside. And it turned out to be an interesting journey. Deep inside NEURON’s plotting library, I found this:

#if VT125
case VT:
vtplot(mode, x, y);
break;
#endif

Now, I didn’t know what VT125 was when I first saw this, but a quick search on the web reminded me that I’m still a young software developer. I present to you, the VT100:

VT100 terminal
I couldn’t find a good picture of the VT125. I apologize if it looks way more modern than its older cousin.

Now that’s what I call backwards compatibility!

Some of you may want to lecture me about how modern terminals actually emulate VT100s and that this code might be in there to allow some fancy plotting inside xterm or its siblings. But I would argue that there are other parts of this code that give away its impressive attempt at supporting older platforms. Such as the rest of the above switch statement:

		switch (graphdev)
		{
		case SSUN:
#if SUNCORE
			hoc_sunplot(&text, mode, x, y);
			break;
#else
#if NRNOC_X11
			hoc_x11plot(mode,x,y);
			break;
#else
#if NeXTstep
			break;
		case NX:
			hoc_NeXTplot(mode,x,y);
			break;
#endif
#endif
#endif
#if TEK
		case ADM:
		case SEL:
		case TEK4014:
			tplot(mode, x, y);
			break;
#endif
#if VT125
		case VT:
			vtplot(mode, x, y);
			break;
#endif
		}
#endif

Now, we all love nested preprocessor if-statements inside switch blocks, but let’s look aside from that and at what’s supported here.

There’s the NRNOC_X11, which I believe introduces the only part of this block that might actually be executed nowadays. In addition we have SUNCORE, which might be Solaris, but I’d bet this supports something that existed long before Oracle acquired Sun back in 2010. There’s TEK, which may refer to something like the Tektronix 4010:

Tektronix_4014
This baby was made in 1972, but it still runs NEURON’s plotting functions. Just download the 5 MB zip-file of NEURON’s source code and … oh, wait.

And then there’s NeXTstep, which Apple acquired in 1997 and used to replace its own Mac OS with Mac OS X. Considering that NeXTstep made its last official release in 1995, I think its fair to say that this piece of code was written in the previous century. It could, of course, just be that no one has deared to search-replace NeXTstep with OS X, but I doubt it.

I should finish this with a final caveat: It could be that this code isn’t at all in use by NEURON anymore. After all, I found all of the above in the plot.c file in the src/oc folder of NEURON’s source code. The above could be remainders of NEURON’s interpreter language, hoc, which was originally made as a demonstration of how to use the parser generator Yacc in the The Unix Programming Environment book. As far as I know, NEURON is the only software out there that’s still using hoc, but that’s a story for another day.

Image Credits: Wikipedia User:ClickRick, Wikipedia User:Rees11.

Nerveceller med toon-shader

Da var det på tide med et nytt Blender-prosjekt igjen. Etter å ha lest om mulighetene til å lage tegneserieaktige materialer bestemte jeg meg for å teste dette ut på en 3D-figur av en nervecelle:

neuronity4

Jeg har for øyeblikket ingen anelse om hva det kan brukes til, men det er alltid gøy å teste ut ulike effekter i Blender. Kanskje dukker den opp på en fremtidig poster.

Last ned Blender prosjektet her.