To describe the key features of trajectories work, we’ll use the following example:
A trajectory can be thought of as a script that is being compiled and run behind the scenes. It uses a namespace to store variable names and values. There are two types of variables: custom variables and device node variables.
A custom variable is only used within the context of a trajectory (e.g., for a calculation), so its name and value are simply stored in the namespace. A device node variable not only has its name-value pair stored in the namespace, but the device node corresponding to the variable name also gets set to the variable’s value.
Users need to be careful when referencing device nodes in trajectories because potentially a single device node can be represented four different ways. For example primary node for sampleTheta device can be referenced by:
All these names are legal names for referencing sampleTheta in the trajectory, however they will be treated as different variables by the trajectory engine. If A3 is set in the init section of the trajectory, and later referenced as sampleTheta in another expression, the trajectory will not recognize it as such. This will cause unpredictable results.
Also avoid referencing nodes by just it's device name or alias, if later on you decide to move another node of the same device. For example, let's say you would like to move sampleTheta to an initial value and and also set its tolerance.
A3 = 10
A3.softTolerance = 0.01
instead, you should use the full node names for all references in the trajectory:
This will garantee that trajectory will create a proper object with two properties, otherwise, again the results will be unpredictable.
Note: If the device node belongs to an add-removable device and the device has not been added, then the trajectory’s variable defaults to being a custom variable.
The Properties block has variables that cannot be changed once the scan begins. These variables define the file writing/naming (see File Rule) and data-of-interest conventions (see Data-of-Interest) for a trajectory.
The easiest way to specify the name of your output data file is to set the filePrefix expression.
If we set it to myFile, then the output filenames will be use this prefix. For example, if NEXUS file writing is turned on, then you would get the following file: myFile.nxs.phd
Writers determine the types of files that are written. You can have multiple writers turned on (ICP, TEXT-COLUMN, NEXUS, etc.) simultaneously. Each writer follows its own file-naming conventions – more on that later.
If you run the same trajectory again, NICE will increment the index at the end.
The Init section defines an initial state for the trajectory. (See Initialization in the Reference for a full explanation of how the Init section can be used). We can define our counting criteria in the Init section as it is fixed throughout our trajectory. In this example, we count for 10 seconds at each point.
The measurement states of an experiment are generated using loops. Loops are defined using lists, ranges, and expressions.
In our example, a range and an expression are used (see the Reference for more on Lists) in a loop to define the measurement states that the experiment will have.
A range is a compact way to specify a series of measurement states from a set of parameters.
In our example, the range will cause motorA to visit positions: 1.0, 2.0, 3.0, 4.0, and 5.0.
An expression is a list of values for the trajectory to visit that is generated by a formula relying on lists, ranges, and other expressions.
In our example, the expression will cause motorB to visit positions: 2.0, 4.0, 6.0, 8.0, and 10.0. This is because motorA visits positions 1.0, 2.0, 3.0, 4.0, and 5.0 and motorB visits every position of motorA multiplied by two.
Note: Expressions should not be the only thing within a loop, because they depend on other values. However, they can reference variables in outer loops - more on this later.
You can preview how the trajectory will run by hitting the Dryrun usa-button at the bottom of the panel. This will open a new window with the expected results.
The dryrun output matches the range and expression we created for motorA and motorB, respectively.
The positions for motorA correspond to the list we get from the range in our loop. The positions for motorB correspond to the list we get from the expression in our loop. The 10.0 seconds spent counting at each measurement state corresponds to the time preset we gave our counter in the Init section.
The above is an example of a point. Its measurement state is having motorA at position 1.0 and motorB at position 2.0 – and it counts at this measurement state for a duration of 10.0 seconds. However, because this is just a “mock” run, no data is written to disc or broadcast to listeners.
Once you’re ready to run a trajectory, hit the Run usa-button at the bottom of the panel.
You can see the trajectory running in the console queue – in the above example, the trajectory is at its third point, counting for the measurement state of motorA at position 3.0 and of motorB at position 6.0.
The console will print the estimated trajectory time and the location/name of the file(s) that was/were written. Multiple writers can be used to write multiple files in different formats. The lsWriters command displays a table of the available and active writers on the system. The table also contains short descriptions of each writer’s function, the data formats it uses, if/where data may be displayed, etc. The writer command starts and stops writers.
Note: Files are written to /usr/local/nice/server_data/experiments/nonims()/data by default.