add support for vpixx pixel mode#571
Conversation
|
|
||
| Parameters | ||
| ---------- | ||
| bits: array-like of int |
There was a problem hiding this comment.
As written, this approach seems to preclude setting all the pixel bits to low. A simple fix would be to allow an empty bits array. In practice though, I-LABs will for now only be monitoring one of the digital output pins, so just setting one of the other bits to high is sufficient to get the bit of interest to be low.
| @@ -39,8 +39,6 @@ | |||
| from expyfun import ExperimentController, building_doc | |||
There was a problem hiding this comment.
It might be nice if this and the other sync utility has VPIXX be a user-set option, defined at the top of the script. (Since our lab and others may not always have this hardware online during an AV test.) And consider defining the Vpixx color bit specification(s) at the top as well, for users to customize the test around their physical Vpixx connections.
There was a problem hiding this comment.
So the general way of working in expyfun is to set everything that needs to be set, then let the sys config JSON make sure that things (triggering modes, response modes, etc.) get to and from the correct places / devices. As implemented, this code deviates from this pattern by protecting some setting from happening based on a conditional at the top of the file.
What I think would be better would be this set_vpixx_color command not to be protected by an if conditional. Then somewhere else, the vpixx-display-ness is controlled more globally based on whether or not a vpixx projector is connected.
The "expyfun-standard" way to do this I think would be
with ExperimentController(..., vpixx=None):
which means "decide whether or not to display vpixx pixel codes based on system expyfun.json". And end users can set ExperimentController(..., vpixx=True) on their systems to see this pixel appear even if they don't have vpixx.
Then at the end of the day the only thing that changes in this specific test is a single line addition of ec.set_vpixx_color("red"), and we make both ExperimentController and start_stimulus smarter in terms of how they handle vpixx-ness. So concretely the API would be:
- Add
SCREEN_VPIXX=False(or similar name) default toexpyfun.json, which can be set to True on systems with vpixx - Add
ExperimentController(..., vpixx=None), which usesSCREEN_VPIXXwhen None - Add
start_stimulus(..., vpixx=None), which usesSCREEN_VPIXXwhen None
| from expyfun.visual import Circle, Rectangle | ||
|
|
||
| USE_VPIXX = False | ||
| VPIXX_COLOR = [0, 1, 2, 3, 4, 5, 6, 7] # full red |
There was a problem hiding this comment.
Typically in expyfun we try to abstract complexity like this (I would have no idea how to switch to blue for example!). Ideally here the API would just allow for set_vpixx_color("r") or set_vpixx_color("red").
If vpixx supports full-spectrum (0-255, 0-255, 0-255) colors, then we should just use matplotlib to convert to int8, then convert this to vpixx internal coding.
If vpixx only supports a subset of colors, I'd prefer:
- Add aliases for the most common ones (probably red, green, blue, black, white)?
- Allow passing this list-of-int8-of-length-8 (?) to have more granular control
There was a problem hiding this comment.
The VPixx DataPixx video and Pixel Mode digital output use the RGB color scheme. 8-bits for each of the Red, Blue, Green. I agree with Dan (below) about abstracting the colors for Expyfun scripts, because in practice our lab would ever use only a subset of the digital output pins and we want exact control over those pins because they will be tied to digital inputs of the Megin or other acquisition system.
| @@ -39,8 +39,6 @@ | |||
| from expyfun import ExperimentController, building_doc | |||
There was a problem hiding this comment.
So the general way of working in expyfun is to set everything that needs to be set, then let the sys config JSON make sure that things (triggering modes, response modes, etc.) get to and from the correct places / devices. As implemented, this code deviates from this pattern by protecting some setting from happening based on a conditional at the top of the file.
What I think would be better would be this set_vpixx_color command not to be protected by an if conditional. Then somewhere else, the vpixx-display-ness is controlled more globally based on whether or not a vpixx projector is connected.
The "expyfun-standard" way to do this I think would be
with ExperimentController(..., vpixx=None):
which means "decide whether or not to display vpixx pixel codes based on system expyfun.json". And end users can set ExperimentController(..., vpixx=True) on their systems to see this pixel appear even if they don't have vpixx.
Then at the end of the day the only thing that changes in this specific test is a single line addition of ec.set_vpixx_color("red"), and we make both ExperimentController and start_stimulus smarter in terms of how they handle vpixx-ness. So concretely the API would be:
- Add
SCREEN_VPIXX=False(or similar name) default toexpyfun.json, which can be set to True on systems with vpixx - Add
ExperimentController(..., vpixx=None), which usesSCREEN_VPIXXwhen None - Add
start_stimulus(..., vpixx=None), which usesSCREEN_VPIXXwhen None
|
... and if we do switch to this new API, I think the default behavior should be for |
|
All good points @larsoner.
Strictly speaking the conditional is unnecessary, it's just that setting the color has no effect if I hesitated to do machine-config JSON for vpixx because I thought it would likely be experiment-specific (auditory paradigms might not want/care about super-precise flip times), which isn't usually the case for things like screen size, audio controller, etc. But I don't have a strong objection to it, so if you think it makes sense I can add a config.
Since the point of vpixx is (ab)using pixel color to send binary triggers, I'm assuming YAGNI on letting users specify colors as e.g. |
In what I'm imagining, the experiment-specific part I think is whether
Oh okay I think I get it now... the experimenter shouldn't care about the color but rather the bits encoded. In your In that case I wouldn't call it ... thinking about this use case actually I wonder if instead this should "just" be a part of |
|
... in other words, make the behavior more closely mirror |
I think I agree with this; at least with the idea that this should be exposed in the API as an ID and not a color. My hesitation is that the vpixx ID is inextricably tied to a flip event, and trial:flip_event is not 1-to-1:
So I think the correct analogy is only to
I'm actually leaning now toward eliminating the
if we do that, then yeah, that should be settable as |
I think this is the crux of how we see this differently. I'm not convinced about the first part -- you can want to stamp additional TTL triggers at arbitrary times with I expect the most common anticipated use case of vpixx is that the user will want to use it to 1) identify a trial start of a paradigm that starts with a visual flip, and they might have a secondary goal of 2) "stamping" something later using vpixx. So I don't see the best analogy being with just
Yeah this is true. While I think it's going to be pretty rare for visual paradigms that use vpixx, in my API proposal: accidentally calling In the Which is okay and workable, but (to me) slightly less clean conceptually consistent because now trial identification is done in two places instead of one. I can live with it if you're not convinced by the conceptual argument, though! A hybrid option would be to allow both modes, essentially. Allow passing a Either way, for non-stimulus-start ID vpixx-ids, I think |
|
I can live with this: with ExperimentController(..., use_vpixx=None) as ec:
# None falls back to machine config ↑↑↑↑
...
ec.identify_trial(..., vpixx_id=(R,G,B))
# ↑ silently does nothing if use_vpixx resolves to False
...
ec.start_stimulus()
# ↑ raises error if flip=False and vpixx_id isn't None
# (unless use_vpixx resolves to False? or even then?)
...
ec.flip(vpixx_id=(R,G,B))
# ↑ silently does nothing if use_vpixx resolves to False
ec.trial_ok()WDYT about the |
|
In this case: we want development on non-vpixx machines and vpixx machines to mirror one another as much as possible. If it raises an error on one it should on the other if possible, so it should raise an if you One could argue that the vpixx pixel should always be drawn if you set In any case, if we do keep machine config stuff, I think |
This occurred to me as I was programming the dMEG protocol to use the Vpixx feature. Apologies for being lab-specific here in the pull request section. But in practice, I don't see a use case for our lab using this feature outside of wanting to strictly know the exact timing of a particular image flip (or really in most cases every image flip). If there are a lot of different types of images, then the VPixx has the additional advantage of inherently "stamping" them up to 24 bits. But for Expyfun scripts, I think we'd still be using our own stamping via the TDT or parallel port outputs, regardless of what the VPixx is doing. In the dMEG experiment, for example, the stamping is still done using STI001 - 003. To capture the visual timing, I define a VON = [0] and VOFF = [1] state for the vpixx pixels (with [0] the single bit we are physically connected to that gets sent to STI004). Before the
Absolutely true. In fact, if you don't pull the monitored pixel back to some background state, the pixels could just remain at their set color for the entire experiment after the first flip. Even worse, if something else overdraws that pixel, like a new background color, the pixel will be at the mercy of the new final image. Thus the on/off states I defined for dMEG. So, basically if the VPixx is being used, there should be an expectation that every So that's not to say that every
That sounds right to me. If you're not physically pulling out the digital info from the DataPixx port anyway, nothing is lost or gained by continuing to manipulate the upper-left pixel. |
No description provided.