Thinking ahead: Re-thinking some of OpenSesame's design principles
Update: A rough list of all the areas of improvement that have been suggested:
- GUI: A better loop table
- GUI: Better drag-and-drop
- GUI: A better sketchpad
- Runtime: More sensible variable management
- Runtime: Consistent coordinates (i.e. always 0,0 as the display center)
- Runtime: A way to do things in parallel
- Runtime: Arithmetic in OpenSesame script
- Runtime: Fully integrate Gstreamer back-end
Hi fellow developers and interested users,
I'm quite happy with how the 2.8 series of OpenSesame is turning out, and how we're gradually working towards a bug-free utopia. Thank you to everyone who contributed, in whatever way! (The increased stability of OpenSesame is to a large part also due to improvements in Expyriment and PsychoPy, so credit to these guys as well.)
Nevertheless, OpenSesame has a number of suboptimal design choices that I would like to see improved in the future, potentially for the 2.9 series, or perhaps even later. Many of these design choices are deeply ingrained in the source code and workflow, and will require considerable changes and potentially introduce backwards incompatibility. That's why they haven't been addressed so far.
With this post I would like to pick your brain about what you currently consider to be problematic, and how you would like to see this fixed. (We're talking about fundamental changes here, so please keep minor bug-reports and inconveniences elsewhere, such as in this discussion.)
I'll start with what I think should be improved, and some thoughts on how. Feel free to comment on these points, suggest alternatives, and also raise new points. I'll update this discussion as necessary.
Managing experimental variables
Currently, as you know, you need to set experimental variables like so ...
... and get them like so ...
my_value = self.get('my_var')
This works, but it feels clumsy. Also, from a technical point of view, these variables are either stored as properties of the
experiment object (for experiment-wide variables) or properties of the
item object (for item-specific) variables. This often leads to conflicts, because, for example, a variable cannot have the same name as a function of the
So how could this be improved? I'm thinking (but this is just a sketch in my mind) about something like the following. There is a
var object that you can use to get and set experimental variables in a transparent way, like so:
var.my_var = 'my_value' # Like exp.set('my_var', 'my_value') my_value = var.my_var # Like my_value = self.get('my_var')
This offers a transparent API that is easy to understand, and usually works as you would expect. However, this basic API ignores the fact that variables can live in the
experiment object, or in an
item object. The following API could offer a more flexible (but rarely used) way to get and set experiment variables:
# Set experiment variable var.my_var = 'my_value' var.experiment.my_var = 'my_value' # Set variable to current item (usally an inline_script) var.item.my_var = 'my_value' # Set variable to item named 'my_sketchpad' var.my_sketchpad.my_var = 'my_value' # Get variable. First look in current item, fall back to experiment. my_value = var.my_var my_value = var.item.my_var # Get experiment variable. my_value = var.experiment.my_var # Get variable. First look in item named my_sketchpad, fall back to experiment. my_value = var.my_sketchpad.my_var
We also need to rethink how variable types are dealt with. Right now, variables are saved as
unicode, depending on which type fits best. Things such as
lists are converted to their
unicode representation. This can be confusing. My suggestion would be to simplify this to the following logic:
- Numeric values are saved as
unicodevalues are saved as
unicode, assuming utf-8 encoding for
- All other types trigger an
osexception. So they are not silently converted to
Finally, how can we implement (something like) the API above in a way that doesn't break backwards compatibility, and assures that current plug-ins continue working?
Top-left vs center-based coordinates
sketchpad objects (and elsewhere in the GUI) use 0,0 to indicate the center, whereas mouse coordinates and coordinates specified in
inline_scripts use 0,0 to indicate the top-left. This is clearly inconsistent, and is a result of the way that OpenSesame gradually evolved. In principle, this can be changed relatively easily, but the obvious problem is that doing so will break a lot of existing experiments. I was thinking something like the following:
We add a new experimental variable, say
unified_coordinates, that can be
no. When set to
no, coordinates should interpreted as they do now (inconsistently), when set to
yes all coordinates are interpreted relative to a 0,0 center (consistently). Then we change the templates such that they set
yes. The result will be that old experiments continue to work, but new experiments all use a sensible and consistent coordinate system.
After some time, we can remove this hack (thus keeping the code clean) and only support center-based coordinates.
Easily doing things in parallel
Currently, it's difficult to do things in parallel in OpenSesame. The typical problem that users run into is that they want to collect responses while at the same time implementing some sequence of
sketchpads. This requires scripting and is unnecessarily difficult, given that it's pretty basic functionality.
I had hoped that the
parallel plug-in would solve this issue, but it turns out that using threads to do things in parallel is tricky and prone to crashes. So my question is pretty open: What would be a user-friendly way to do things in parallel? Could this be done by a plug-in, possible by improving/ fixing the current
parallel plug-in? Technicalities aside, what would this functionality ideally look like?
There's much bigger issues in the world, I know. But I first have to take care of the world I know.