Display Frequency

Hi Chris,

I have a quick question. I’m probably missing this somewhere in the documentation, but if I have a frame list stimulus, how can I control the temporal frequency with which it updates? Currently the code I have (attached, I think it’s more or less the same code as the last version you sent me) updates each frame with a new white noise image, but how would I be able to - for example - make the noise update at specifically 30Hz?

It would be ideal if this were able to be changed from trial to trial, too, as we want a portion of our experiment to have some randomly decided change in temporal frequency of noise presentation that varies each trial.

Thank you,
Yvonne

And a second question - is there any way to change the size that the images in a frame list will be displayed on the screen? We also want to play with the spatial frequency, and being able to use the display size of an image to our advantage might be easier than changing the way MatLab generates the code. Though, if you disagree, let me know. I’ve been looking and can’t seem to find how I would change the spatial frequency (or how big each generated same-color “pixel” is) in the MatLab code from trial to trial.

Thanks,
Yvonne

Hi Yvonne,

I’m probably missing this somewhere in the documentation, but if I have a frame list stimulus, how can I control the temporal frequency with which it updates?

You aren’t missing anything. The frame list is always locked to the refresh rate of the display, and there’s no way to change it.

The closely-related movie stimulus does let you select an arbitrary frame rate. However, you have to give up frame-locked timing, meaning that some frames may be displayed more than once, while others may be skipped entirely.

If you want to retain frame-exact timing while updating the display at a fraction of its refresh rate, you need to “pad” the frame list’s stimulus group with multiple copies of each frame. For example, in your experiment, if you wanted to update the noise at 30Hz for one second on a display running at 60Hz, then the value of the dynamic_white_noise_filenames variable would look like

['img1.png', 'img1.png', 'img2.png', 'img2.png', ... 'img30.png', 'img30.png']

is there any way to change the size that the images in a frame list will be displayed on the screen?

Yes, just remove the fullscreen parameter and add x_size and/or y_size. But:

We also want to play with the spatial frequency, and being able to use the display size of an image to our advantage might be easier than changing the way MatLab generates the code. Though, if you disagree, let me know.

Actually, I think it does make more sense to change the image-generation code. Specifically, change dynamic_white_noise_frame_width and dynamic_white_noise_frame_height to get “pixels” of the desired size. Then, continue to use fullscreen=true in the image stimulus definition.

Cheers,
Chris

Hi Chris,

Thanks so much for your quick reply. I’ll look into whether we want to use
the movie stimulus or the frame list with “padding”. That information is
very helpful, thank you.

As for the spatial frequency issue, thank you for explaining how I would
change that - it definitely looks like changing the width and height is a
better idea. I think I was misunderstanding the way the code was written
and missed that that was possible. That’s perfect.

Thank you!
Yvonne

Hi Chris,

I tried changing the variables dynamic_white_noise_frame_width and
dynamic_white_noise_frame_height while running the experiment, and it
doesn’t change the appearance of the noise displayed.

I see that the python bridge gets those variables from MWorks and Matlab
uses those - if I change the variables in the base code before loading the
experiment, it will change the appearance of the noise. However, if I
attempt to change these without reloading the experiment (so attempt to
change them through the variables window), it doesn’t change the noise. Is
python getting these variables at load and not refreshing every time the
bridge is called? How can I make sure python reacquires the variables at
each noise generation step?

Thank you,
Yvonne

Hi Yvonne,

Is python getting these variables at load and not refreshing every time the bridge is called?

Yes.

How can I make sure python reacquires the variables at each noise generation step?

You can acquire them inside the generate_whitenoise_images function.

However, after trying this, I realized that it isn’t really what you want. If the dimensions of the noise image are smaller than those of the display, the noise “pixels” get smeared (i.e. interpolated linearly) when the image is drawn. To get crisp squares, you need to create an image with the same dimensions as the display, with each noise grain consisting of multiple pixels. I’ve attached a new version of the experiment that does this. The variable dynamic_white_noise_grain_size sets the noise grain size in pixels.

The new version also includes two other changes:

  1. The noise images are saved in uncompressed TIFF format (instead of BMP). This makes the files both slightly smaller and a bit faster to generate.
  2. The noise images have an embedded ICC profile, so that their linear color space is interpreted correctly when MWorks’ color correction is enabled (the default in MWorks 0.8).

If you have any questions, please let me know.

Chris

Hi Chris,

In theory, this definitely sounds like a better idea, though we may be able
to take advantage of the linear interpolation later on, so it’s actually
good to know we can do both. I tested the code you sent me and I get the
attached error. I did remember to change the image path this time - it
looks like this is saying something is wrong in the subprocess used in the
python script? I’m totally unfamiliar with subprocesses, so I wasn’t sure
where to begin on troubleshooting. Any help would be appreciated.

Thank you!
Yvonne

Attachment: Screen_Shot_2018-06-14_at_2.46.58_PM.png (44.7 KB)

The Python script tries to launch MATLAB R2018a (the latest). You probably need to change it to the version you have installed.

Chris

Hi Chris,

Thanks, that’s all it was. I changed it and the program works now.

However, the white noise images it creates now seem to have way too much
white content. The static white noise before a trial looks a lot darker
than the generated noise, when before, assuming the grain size matched,
there was no visual difference between the static frame and the dynamic
frames. This inbalance happens regardless of grain size. I’m not sure what
might be causing this. Might it have to do with the new ICC profile or the
change in file format? I’m not sure what else might be different to cause
this.

Thanks,
Yvonne

For reference - the attached are example images generated from the old code
(the .bmp file) and the new code (.tiff). I was only just now able to get
them off of the lab computer since I was running a monkey earlier. Hope it
helps!

Thanks,
Yvonne

Attachments:

I’m actually looking at them now (on the non-lab computer where I am
writing this email), and they look the same. I’m not sure why they would
appear so different on the lab computer. I’ll have to look into this more.
Sorry about the confusion. I’ll get back to you on whether or not there
actually seems to be an issue.

Hi Yvonne,

The static white noise before a trial looks a lot darker than the generated noise, when before, assuming the grain size matched, there was no visual difference between the static frame and the dynamic frames. This inbalance happens regardless of grain size. I’m not sure what might be causing this. Might it have to do with the new ICC profile or the change in file format?

It does relate to the ICC profile. If the static noise looks darker than the dynamic noise, then either you’re running MWorks 0.8 with color management disabled, or you’re using an older version of MWorks that doesn’t support color management at all. If the former, you should enable color management (MWServer → Preferences → Display → Use color management). Otherwise, you can omit the ICC profile by commenting out the following line in the MATLAB script:

tags.ICCProfile = icc_profile_data;

FYI, assuming the ICC profile of your display is reasonably accurate, the brighter image is correct (i.e. its pixels are uniformly distributed between the minimum and maximum luminance of the display, whereas those of the darker image are closer to the minimum on average).

I’m actually looking at them now (on the non-lab computer where I am writing this email), and they look the same.

You mean they look the same in your email client? That suggests the email client isn’t performing color management. I’m guessing the non-lab computer isn’t a Mac?

Chris

The non lab computer is actually a Mac! It must not be color corrected.

As for the actual noise on the lab computer, looking at the values through
Matlab (loading in the images as matrices after generation), they seem to
be identical (in terms of min/max values and distribution of values) except
for a “colormap” that came with the image from the old code when loaded in
by clicking on the file and not through imread. Does this sound as
expected? This seems weird, since they look so visually different as images.

I’m using a version of MWorks that is “0.8dev-20171120”, so it doesn’t have
the color correction of the full 0.8 release. I’ll have to update that.
Commenting out that line in the Matlab code does work though, and makes it
look like the mworks-generated static white noise.

A further question, however, that Arash wanted to know: how does MWorks
color correct? Does it assume the monitor is calibrated?

Thank you,
Yvonne

Hi Yvonne,

As for the actual noise on the lab computer, looking at the values through Matlab (loading in the images as matrices after generation), they seem to be identical (in terms of min/max values and distribution of values) except for a “colormap” that came with the image from the old code when loaded in by clicking on the file and not through imread. Does this sound as expected? This seems weird, since they look so visually different as images.

Yes, it makes sense that the pixel values in both images have the same min/max and distribution. The difference is in the interpretation of those values, and that’s where the colorspace is crucial. If you want to know more, Apple has a reasonably-understandable overview of how color management works. (FYI, I am in no way an expert on this topic!)

Also, BMP (unlike TIFF) uses indexed color. The “colormap” is probably the color index of the image.

how does MWorks color correct? Does it assume the monitor is calibrated?

No, it doesn’t assume any particular calibration of the display.

When color management is enabled, stimuli are rendered in a “linearized” sRGB color space (i.e. a color space with the same gamut as sRGB but a linear gamma). The RGB values in a stimulus’ color parameter are interpreted as belonging to this color space, and image files are color matched to this color space. Before being presented, each output frame is converted to the target display’s color space, which is defined by the ICC profile assigned to the display (System Preferences → Displays → Color).

This is the same color-management process that is used throughout macOS. As I alluded to previously, the accuracy of the process depends on the accuracy of the display’s profile. The default profile is probably fine, but if you’re worried about it, you can profile your displays yourself using, e.g., an i1Display Pro or equivalent.

As for why we’d bother with all this, the main benefit in MWorks is that you get linear luminance response, so that, e.g., a stimulus with color 0.5,0.5,0.5 has a luminance half way between the minimum and maximum of the display. It probably seems strange to think this would ever not be the case. However, when color management is disabled, colors are interpreted as belonging to the color space of the display (and not “linearized” sRGB), and that color space is almost certainly not linear. For example, on one of the displays I’m using, the color 0.5,0.5,0.5 matches 0.22,0.22,0.22 in linear sRGB. This is why MWorks’ default “50%” gray background looks noticeably darker when color management is off.

(As a side note, it’s also possible to get linear luminance by “linearizing” your display. Basically, this means applying a gamma correction to the display that is the inverse of the display’s native gamma, thereby canceling out the nonlinearity. This does work, and in fact, at the request of some users, the current MWorks nightly build even supports this directly. However, this method is inferior to proper color correction. In addition to making the display look bonkers for any non-MWorks content, it also completely mangles MWorks’ presentation of images with non-linear colorspaces, meaning pretty much any image that hasn’t been created expressly for display on such a “linearized” monitor. As you may have guessed, I don’t recommend this approach!)

Anyway, sorry to drag you in to the color management weeds. My previous recommendation still stands: either upgrade to 0.8 and enable color management, or don’t assign an ICC profile to the noise images.

Chris

Hi Chris,

Thanks so much for the explanations! In this case, it’s important to us
since we’re working in V1 so I’m glad I’m getting dragged into the weeds of
color management. I ended up looking up some stuff about it on my own over
the weekend as well. Making sure our display’s profile reflects the actual
luminance is very important to us, so we’ll be profiling it ourselves and
using that profile. Thank you for the link to something that allows us to
do that! The color management in MWorks is definitely a boon to us, so I’ll
update to 0.8 so we can use it to our advantage.

Best,
Yvonne