-
Notifications
You must be signed in to change notification settings - Fork 4
Interprocess Socket Interface
This section describes the interface between the Nutmeg client and server. This is written from the point of view of somebody wishing to write a Nutmeg client.
The messaging interface between Nutmeg clients and the server is pretty straightforward. The messages are strings in JSON format.
There are two types of sockets that a Nutmeg client should keep track of:
- The one and only Nutmeg server's core socket
- Parameter update request sockets (one for each figure created by the client)
The server is constantly listening to this port and deals with requests from Nutmeg clients. The port bound to by the server can changed based on availability or user preference, so the client should allow the user to define it when plotting.
The message format is simply:
["command", "handle", args...]
Where handle is the unique identifier of the item in which the client is interested. The following sections describe the commands accepted by the server.
The server will send a reply back to the client giving details on the status of the request in the form of a list. The first element will be the error number, zero meaning success. If the command was not valid the client will receive the following reply:
[1, "Unrecognized command"]
Request: ["createFigure", figureHandle, qmlString]
qmlString is a QML string declaring the layout of the figure. See more in [Figure API](Figure API).
Replies
Success: [0, figureHandle, parameterUpdatePort, msg]
QML Failure: [2, {"lineNumber": l, "columnNumber": c, "message": m}]
Request: ["createGui", figureHandle, qmlString]
qmlString is a QML string declaring the layout of the parameter controls. The values of these parameters are sent back to the client and can be used to update the data in the plots. See more in [Controls API](Controls API).
Replies
Success: [0, msg, parameters]
Bad Figure Handle: [3, msg]
QML Failure: [4, {"lineNumber": l, "columnNumber": c, "message": m}]
Request: ["sendData", plotHandle, dataDict, parameter (optional)]
Sets the data or properties of plotHandle according the values stored in dataDict. Multiple objects can be referenced using Python-style pretty indexing (see below).
plotHandle is the hierarchical handle to the plot of interest (e.g. myFigure.axis[0].experiment1Data)
Typically, dataDict should set one or both of x and y data for a 2D plot (e.g. {"x": [0,1,2], "y": [2,4,1]})
For a set of data, the plot data should be a 1D list. For a multiple sets of data destined for multiple axes or plots, the plot data should be a 2D list, regardless of the number of data points. Where the first dimension contains a list for each dataset. In the following example, a figure has an axis group of 3 (so they have the same handle). Each axis contains a line plot with the handle "myData":
[ "sendData", "myFigure.axes[0:3].myData", {"x": [0,1,2], "y": [ [2,4,1], [9,1,0], [1,2,3] ]} ]
The parameter argument is an optional argument which informs the server which changing parameter that this update is in response to. See below for further details.
Replies
Success: [0, msg]
For each figure created, the Nutmeg server creates a socket specifically for pushing parameter updates to a client. On the client side, this socket is a ZMQ Request socket and works in the following way:
-
Client sends
createFigurecommand to Nutmeg server. -
Figure is created and a parameter update socket is opened.
-
The port number is sent back to the client in the reply message.
-
The client connects to the socket, sending the string message,
"ready". -
The server responds when the user updates any parameters. The message has the following format:
["updateParam", figureHandle, parameter, value]
Where `figureHandle` specifies the figure being updated, `parameter` is the handle of the parameter updated, and `value` is its new value.
6. When the client is ready to receive further parameter update notifications, it sends `"ready"` back to the socket. The server will not push any further updates for this parameter until it receives a `"sendData"` command tagged with that parameter. This means the update has been completed.
7. If the client needs to update any plot data, it should be sent to the Nutmeg server via the server's core socket.
### Synchronous vs. Asynchronous
The client can choose to be either asynchronous or synchronous. Asynchronicity is preferred, since it allows the Nutmeg server to push updates for multiple _different_ parameters before waiting to receive new data for the first parameter. It also means it is less likely to interfere with any computation the user may be performing on the client side.
**Synchronous**
The simplest option. For step 5 and 6 above, the client receives the parameter's new value, computes the new data, sends that to the server (with `"sendData"` to the core socket), and then send `"ready"` back up the parameter socket.
**Asynchronous**
For an example of implementation, the Python Nutmeg client module shows how this can be exposed to the user. For steps 5 and 6 above, the client receives the parameter's new value, spawns a new process which computes the new data, then sends `"ready"` back up the parameter socket. When the spawned process finishes calculating the new data, it sends to the server (with `"sendData"` to the core socket).