The addition of an ifftshift call makes sense to me. However, putting it in to my code seems to add an angular offset to the noise, along with a visible mesh-like pattern.
Turns out this was due to a bug in my fftshift implementation. After fixing the bug, adding the inverse fftshift, and taking only the real-valued output of the inverse FFT (instead of taking the absolute value of the full, complex result), I get reasonable-looking output. Sorry about that!
However, the new output doesn’t look qualitatively different than the old output (no iffshift, abs), so it’s hard to say whether I’ve fixed the issue (whatever it was). Are there particular values of theta_0/sigma_theta where the difference should be obvious?
Thanks,
Chris
Your approach sounds fine.
Mark
Re:ifftshift and real():
Sounds great- sounds like your bug was similar to our bug.
If I remember correctly, your first plugin (as our code did) showed odd
images w/ too much high-freq content, only for values of theta0 near pi -
try stepping theta0 around the circle. Paul or Anna may be able to give us
more detail as Anna did the pilot testing of your plugin and I believe Paul
found the odd behavior.
Mark
Hey Chris,
This issue popped up when we had a theta0 value greater than pi/2. I’ve attached an example from the old plugin with theta0 at 2.35 (135deg) and sigma theta 0.3.
Hi Anna,
Thanks. The issue is very apparent with those parameter values, and I can see that it’s now fixed.
Chris
Hi all,
I’ve attached an updated version of the plugin (in source and compiled form) that includes the following changes:
- theta_0 and sigma_theta are now specified in degrees
- missing inverse FFT shift has been added, and bogus absolute value has been removed
- bug in my FFT shift has been fixed
- added
rand_seed
parameter for explicit seeding of dynamically-generated base noise
- added support for getting base noise from a directory of images
To use the new version, you’ll need the latest MWorks nightly build, which includes some new helper routines that the plugin requires.
I’ve attached a new example that demonstrates the use of image files for the base noise. In short, you specify the directory containing the images via the directory_path
parameter. The specified directory should contain only noise images. The images can be in any format understood by the operating system, and they can be named in any way you want. The only restrictions are
- the width and height of each image must be a power of two (but width needn’t equal height), and
- all images must have the same dimensions.
Also, to ensure that the noise values get interpreted correctly, the images should include an appropriate color profile. The example experiment includes a copy of Apple’s “Linear Gray” profile, and the script gen_noise.py
(which I used to generate the example’s noise images) demonstrates how to use it when creating TIFF files.
At present, the plugin runs through the noise images in lexical sort order (by filename). When it reaches the last image, it goes back to the first, thereby making the noise a fixed-length, repeating loop. If you want to use a different ordering scheme, please let me know. In any case, the filename and SHA-1 hash of the current noise file are included in stimulus announcements for the oriented noise stimulus, so the event file contains all the info you need to reproduce the state of the stimulus during any frame.
Cheers,
Chris
Hi all,
Have you had a chance to test the updated oriented noise stimulus? If so, does it seem to be working correctly now?
If things look OK, can I add the plugin to the main MWorks source repository and nightly build, or do you want it to remain private?
Thanks,
Chris
Hi Chris,
Sorry for the delay, there have been lots of things going on. I tested the new plugin and it seems to work perfectly. Thanks for your help on this.
We’re fine with the plugin being public.
Anna
Hi Chris and Anna,
Thanks for testing.
Actually, can we hold off on publicizing the plugin until I’ve had a chance to test it a bit more?
Thanks,
Mark
Hi Mark & Anna,
I tested the new plugin and it seems to work perfectly.
Great! Thanks for letting me know.
Actually, can we hold off on publicizing the plugin until I’ve had a chance to test it a bit more?
Sure, no problem.
Chris
Hi Mark,
Actually, can we hold off on publicizing the plugin until I’ve had a chance to test it a bit more?
Just a heads up: If you want the oriented noise stimulus to be in the next MWorks release, I’ll need to know soon (like in the next few weeks).
Cheers,
Chris
Happy to hold off on this release, OK? I’m actually going to test myself
in the next few weeks. Thanks! Mark
Hi Chris,
This stimulus plugin is looking great.
Two questions/issues after some testing:
- It looks like f0 (and f_theta?) are specified relative to the size of the stimulus. Ideally, since this is a spatial frequency this would change with stimulus size so that the stim features (the black/white regions) are constant size even as the stimulus is resized. Is that a change you could make and would you need us to help?
- It would be helpful to have a parameter to randomize the order of the noise frames used, and log in MWorks the noise frame # that was used in a given refresh. Is that something you can add?
No rush on this, next few weeks is fine.
Also, I REALLY like working in the new MWEL. It’s very very much better than writing and editing the XML code - much easier to wrap your head and understand what is going on.
thanks!
Mark
Hi Mark,
It looks like f0 (and f_theta?) are specified relative to the size of the stimulus. Ideally, since this is a spatial frequency this would change with stimulus size so that the stim features (the black/white regions) are constant size even as the stimulus is resized. Is that a change you could make and would you need us to help?
Sure, I can make that change. However, it’s not obvious to me exactly how f0 and sigma_f relate to feature size, or what a “natural” size would be for a given combination of those parameters. Maybe you could provide some guidance?
It would be helpful to have a parameter to randomize the order of the noise frames used, and log in MWorks the noise frame # that was used in a given refresh. Is that something you can add?
Sure. How should the stimulus handle repeats of the noise frames? Should it set the random order once and just keep looping over it, or should it re-randomize every time it hits the end of the sequence?
Also, I REALLY like working in the new MWEL. It’s very very much better than writing and editing the XML code - much easier to wrap your head and understand what is going on.
Glad to hear it! That’s certainly how I feel, so it’s nice to know at least one other person shares my point of view
Chris
Hi Chris,
Sure, I can make that change. However, it’s not obvious to me exactly how f0 and sigma_f relate to feature size, or what a “natural” size would be for a given combination of those parameters. Maybe you could provide some guidance?
f0 and sigma_f are both spatial frequencies. (f0: center frequency. sigma_f: standard deviation around f0). Both have the same units (inverse of length, times a scale factor). I’m not sure what the scale factor is off the top of my head (2pisize/2?). This is an angular spatial frequency, so it assumes the stimulus itself has equal x_size and y_size (though the mask may have different x_size and y_size).
Does that get you far enough? Ideally both would be expressed in cycles per degree, so a 10x10 stimulus, with sigma_f = 1e-6 and f0 = 0.2 would have approximately 5 cycles across the stimulus.
Sure. How should the stimulus handle repeats of the noise frames? Should it set the random order once and just keep looping over it, or should it re-randomize every time it hits the end of the sequence?
Re-randomize every time it hits the end. A randomize parameter, with values “random_w/out_replacement”, “sequential_ascending”, “random_with_replacement” as with the other random choice objects in MWorks, might be a good idea?
thanks,
Mark
Hi Mark,
It looks like f0 (and f_theta?) are specified relative to the size of the stimulus. Ideally, since this is a spatial frequency this would change with stimulus size so that the stim features (the black/white regions) are constant size even as the stimulus is resized.
I discovered that this was actually due to an issue in how we compute the FFT mask. Following your example code, I was letting f_x and f_y run over [-cols/2, cols/2] and [-rows/2, rows/2], respectively. However, the bounds really need to be [-f_c, f_c], where f_c is the Nyquist frequency for the given dimension. Since the Nyquist frequency depends on the spatial sampling rate, making this change results in f_0 and sigma_f being treated correctly as spatial frequencies.
Ideally both would be expressed in cycles per degree, so a 10x10 stimulus, with sigma_f = 1e-6 and f0 = 0.2 would have approximately 5 cycles across the stimulus.
Shouldn’t that be 2 cycles (0.2 cycles/degree * 10 degrees)? That’s what I see now, after making the change described above.
A randomize parameter, with values “random_w/out_replacement”, “sequential_ascending”, “random_with_replacement” as with the other random choice objects in MWorks, might be a good idea?
Is the intent here to be able to repeat the same sequence of noise frames (i.e. the oriented noise “movie”) multiple times? If yes, then I think the experiment needs to be explicit about the default order of the noise frames.
Maybe, instead of using all the images in a given directory, the stimulus should have a “noise_images” parameter that takes a list of filenames. The default order for the noise frames would be their order in the list, but you could alter the order with a “selection” or “randomize” parameter like you describe. (It would still be easy to pull all the images from a directory, without having to name them individually, using MWorks’ filenames function.)
What do you think?
Chris
Hi Chris,
I discovered that this was actually due to an issue in how we compute the FFT mask. Following your example code, I was letting f_x and f_y run over [-cols/2, cols/2] and [-rows/2, rows/2], respectively. However, the bounds really need to be [-f_c, f_c], where f_c is the Nyquist frequency for the given dimension. Since the Nyquist frequency depends on the spatial sampling rate, making this change results in f_0 and sigma_f being treated correctly as spatial frequencies.
Great.
Shouldn’t that be 2 cycles (0.2 cycles/degree * 10 degrees)? That’s what I see now, after making the change described above.
Yes, that’s correct.
A randomize parameter, with values “random_w/out_replacement”, “sequential_ascending”, “random_with_replacement” as with the other random choice objects in MWorks, might be a good idea?
Is the intent here to be able to repeat the same sequence of noise frames (i.e. the oriented noise “movie”) multiple times? If yes, then I think the experiment needs to be explicit about the default order of the noise frames.
Yes and no. Actually, we have two main intentions: (1) we just need to KNOW the order of the noise frames for later analysis, and (2) sometimes we want the sequence to be re-randomized from one repeat to another. (Repeating the same, or a chosen, sequence is sometimes fine; this isn’t a priority but probably worth adding now in case we ever need it.).
Maybe, instead of using all the images in a given directory, the stimulus should have a “noise_images” parameter that takes a list of filenames. The default order for the noise frames would be their order in the list, but you could alter the order with a “selection” or “randomize” parameter like you describe. (It would still be easy to pull all the images from a directory, without having to name them individually, using MWorks’ filenames function.)
What do you think?
Chris
That sounds like a fine way to achieve what we want, if I understand you correctly. Would you like to send an example MWEL too when you make this change?
thanks,
Mark