# Noise stimulus

**URL:** <https://mworks.discourse.group/t/noise-stimulus/770>\
**Category:** Support\
**Created:** [October 5, 2018, 1:42pm UTC](https://mworks.discourse.group/t/noise-stimulus/770 "2018-10-05T13:42:33Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [October 5, 2018, 1:42pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/1 "2018-10-05T13:42:33Z")

</div>

Hi Chris,

I’m attaching the code to generate the noise stimulus we want. There’s an example notebook with what the masks and the resulting stimulus frames look like. The python code should fairly precisely specify what we want.

I think we decided we wanted to be able to point the stimulus at a directory of unfiltered noise frames and an array with noise frame ordering, so that we could recover exactly the stimulus that was presented on each frame for later analysis.

Let us know what other questions you have as you implement this.

Thanks,  
Mark

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [October 5, 2018, 1:42pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/2 "2018-10-05T13:42:33Z")

</div>

Attachment: [for-chris-181002.zip](https://mworks.discourse.group/uploads/short-url/97VR45sdLARlmEXv04QXJycIdq.zip) (1.77 MB)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [October 5, 2018, 1:48pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/3 "2018-10-05T13:48:23Z")

</div>

Hi Mark,

Thanks. It looks like I have everything I need. What’s the timeframe for when you want to have this in MWorks?

(FYI, I sent this to your Gmail address, because the support site [seems to lose](https://mworks.tenderapp.com/discussions/questions/746#comment_43126376) messages from NIH addresses. Sorry for the inconvenience!)

Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [October 5, 2018, 2:40pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/4 "2018-10-05T14:40:19Z")

</div>

Great. There is not a huge rush - next 4 weeks possible to get us something to test? Can we test in a separate build before it goes into MWorks, perhaps as a histedlab plugin?

I also wish NIH email worked better.

Mark

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 8, 2018, 4:59pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/5 "2018-11-08T16:59:40Z")

</div>

Hi Mark,

I’ve attached a first pass at the “oriented noise” stimulus. I’ve included the source code, the compiled plugin (usable with the current MWorks nightly build), and a demo experiment.

At present, the stimulus generates the “base” noise itself, instead of reading it from files. I’m sharing it now because I’d like you to verify that the implementation of the stimulus is otherwise correct and what you want. (The math replicates your Python code, and the output qualitatively looks like your examples. Still, it’s hard for me to be sure I’ve gotten it exactly right.)

Also, the stimulus doesn’t include an integrated Gaussian mask. Instead, you need to put it in a [layer](https://mworks.github.io/documentation/latest/components/layer_stimulus.html) underneath an appropriate [mask stimulus](https://mworks.github.io/documentation/latest/components/mask_stimulus.html). The example experiment demonstrates this.

Cheers,  
Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 8, 2018, 4:59pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/6 "2018-11-08T16:59:40Z")

</div>

Attachments:

- [OrientedNoise.zip](https://mworks.discourse.group/uploads/short-url/m9p7Q0yqiepdjW8qAofZIotqcBG.zip) (13.9 KB)
- [OrientedNoise.bundle.zip](https://mworks.discourse.group/uploads/short-url/3MjzHOtNJehM7VOqg1rNoxOpOXm.zip) (44.6 KB)
- [oriented\_noise\_demo.mwel.zip](https://mworks.discourse.group/uploads/short-url/1ZMneQ2byz5nIzK8i7V1JbpPt9N.zip) (422 Bytes)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 13, 2018, 7:32pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/7 "2018-11-13T19:32:26Z")

</div>

Hi all,

Anna and Paul are now included in this discussion.

Also, I failed to be explicit about how to install the compiled plugin: Unzip `OrientedNoise.bundle.zip`, and then move the `.bundle` to the directory `/Library/Application Support/MWorks/Plugins/Core`. After that, you’ll need to restart MWServer.

Cheers,  
Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 16, 2018, 11:08pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/8 "2018-11-16T23:08:53Z")

</div>

Hello Chris,

Thank you for providing the stimulus. We have looked at you’ve provided and we have a few comments:

1. We noticed that we provided you with an earlier version of our stimulus code that has a bug. I’ve attached the code that should be implemented instead - it’s only a few differences and should be simpler to implement (I’ve also attached a screenshot of the diff between codes for convenience).

2. We also noticed a potential issue with the contrast. I’ve attached images, but it appears that the mean pixel value across the stimulus is less than that of the background layer. I’ve attached two images where we decrement contrast by adjusting the alpha value. With alpha at 1.0, the stimulus looks correct compared to the background. When alpha is at 0.5, the stimulus appears darker than the background. Would you have any insight into what could be causing this?

3. Just a small edit for ease of use - can we have the stimulus orientation parameter input changed from radians to degrees?

4. Last, and slightly unrelated, do you have a status update on converting our current hold-and-detect experiment to .mwel?

Please let me know if you have any questions or would like any other information. Thank you!

-PKL

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 16, 2018, 11:08pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/9 "2018-11-16T23:08:53Z")

</div>

Attachments:

- [dynamic\_stim\_diff\_screencap.png](https://mworks.discourse.group/uploads/short-url/3LHCgDYQiFzG1qxDWuEcJ90mOu1.png) (478 KB)
- [dynamic\_stim.py](https://mworks.discourse.group/uploads/short-url/ZOt7dp0yqonTTBwDQet0kmADX8.py) (4.92 KB)
- [alpha0.5.png](https://mworks.discourse.group/uploads/short-url/gY52ZXmwFxlNSK9R52zvf6Gbzb4.png) (25.5 KB)
- [alpha1.png](https://mworks.discourse.group/uploads/short-url/ecF6ikx2ybTacjEDNSrEiPmMe0L.png) (54.7 KB)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 19, 2018, 3:12pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/10 "2018-11-19T15:12:53Z")

</div>

Hi Paul,

> We noticed that we provided you with an earlier version of our stimulus code that has a bug. I’ve attached the code that should be implemented instead

The code that Mark gave me (in `for-chris-181002.zip`) is identical to what you attached, so this is already what I’ve implemented.

> We also noticed a potential issue with the contrast.

Yes, I see what you mean. The issue is that the `alpha_multiplier` parameter of MWorks’ stimuli only behaves like a contrast setting when the stimulus is drawn directly on top of a 50% gray background. When the stimulus is part of a _layer_ that’s drawn on top of a 50% gray background, the blending works out differently. (Specifically, the stimulus is first blended with the layer’s background, whose red, green, blue, and alpha color components are all zero. Then, the layer is blended with the content under it.)

Luckily, there’s a simple fix: In the noise’s layer, draw a 50% gray rectangle directly beneath the noise. I’ve attached a demo experiment that shows two oriented noise stimuli, both with an alpha of 0.5. The one on the right has a 50% gray rectangle under it, while the one on the left does not. When run, the left stimulus looks like the alpha 0.5 image you sent (i.e. too dark), while the right one looks like it maintains the correct mean luminance.

> Just a small edit for ease of use - can we have the stimulus orientation parameter input changed from radians to degrees?

Sure. You mean `theta_0`, right? Do you also want `sigma_theta` to be in degrees, or should that stay in radians?

> Last, and slightly unrelated, do you have a status update on converting our current hold-and-detect experiment to .mwel?

Sorry, but I failed to grab a copy before Mark removed my access to the repository. If you can add me again, I’ll clone a copy for myself. Or, if you want to email me a tarball of the source, that’d be fine.

Cheers,  
Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 19, 2018, 3:12pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/11 "2018-11-19T15:12:53Z")

</div>

Attachment: [oriented\_noise\_bg\_rect.mwel.zip](https://mworks.discourse.group/uploads/short-url/hrf52pBVK46eol2sPIlBq2QcsRL.zip) (462 Bytes)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 20, 2018, 4:57pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/12 "2018-11-20T16:57:08Z")

</div>

Hello Chris,

1. We have taken another look at the stimulus code and have fixed the bug. I’ve attached below the new stimulus code and a screenshot of the new diff (two lines to change).

2. We will take a look at your demo for handling the contrast and let you know if we have trouble.

3. Yes, we would like degrees for both theta\_0 and sigma\_theta.

Thank you for your help!

-PKL

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 20, 2018, 4:57pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/13 "2018-11-20T16:57:08Z")

</div>

Attachments:

- [dynamic\_stim.py](https://mworks.discourse.group/uploads/short-url/9Qoi7ZwqFWOWRJiPnbOmtkD7CfY.py) (5 KB)
- [dynamic\_stim\_stim\_screencap.png](https://mworks.discourse.group/uploads/short-url/qdIgNe9OghZhMXBK2KBaB18Z9hr.png) (76.1 KB)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 26, 2018, 4:31pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/14 "2018-11-26T16:31:18Z")

</div>

Hi Paul,

I don’t understand the math in the new code:

```
noisefr = np.fft.ifft2(np.fft.ifftshift(ftimagep)).real
noisefr = noisefr - noisefr.mean()
maxamp = np.max(np.abs(noisefr))
minamp = np.min(np.abs(noisefr))
noisefr = (noisefr-minamp) / (maxamp-minamp)

```

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. (See attached image.) I had tried adding it before, and I assumed that these effects were the reason it was omitted.

Also, I don’t understand the normalization code. The last line makes it look like you’re trying to map the range of values in noisefr on to [0,1], which makes sense (and is ultimately what I have to do to display the noise with OpenGL). However, you’re using the minimum and maximum amplitude, as opposed to the signed min and max. Since you’ve translated noisefr to have mean zero, won’t minamp always be zero, in which case you’re just dividing by maxamp as before?

Thanks,  
Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 26, 2018, 4:31pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/15 "2018-11-26T16:31:18Z")

</div>

Attachment: [with\_ifftshift.jpg](https://mworks.discourse.group/uploads/short-url/3mxxys6uk2aAYDGyQtrFKeJy8x5.jpeg) (194 KB)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 26, 2018, 4:51pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/16 "2018-11-26T16:51:11Z")

</div>

Hi Chris,

I can comment as I looked at this too, and Paul can chime in.

I think there were two problems that are fixed here:

- inverse shift (prev. omitted)
- work with real part of inverse transform (prev: abs())

1. the new code appears to work in our hands, perhaps Paul can attach figure output as we vary orientation. (I think the problem previously was that abs() was hiding the problems due to failture to shift, though you can see problems emerge if you take the stimulus you sent and vary orientation around the whole circle.)

2. Normalization: What we see is that ifft2() produces pixel values in roughly range [-1, 1]. So we subtract the mean, and find the min (around -1) and max (around +1). Then we find  
(noise-minamp)/(maxamp-minamp)  
which becomes  
(noise+1)/2  
and thus maps onto [0,1].

Mark

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 26, 2018, 5:35pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/17 "2018-11-26T17:35:22Z")

</div>

Hi Mark,

> Normalization: What we see is that ifft2() produces pixel values in roughly range [-1, 1]. So we subtract the mean, and find the min (around -1) and max (around +1). Then we find (noise-minamp)/(maxamp-minamp) which becomes (noise+1)/2 and thus maps onto [0,1]

That makes sense, but that isn’t what your code does. The key part:

```
maxamp = np.max(np.abs(noisefr))
minamp = np.min(np.abs(noisefr))

```

You’re taking the min and max of the _absolute value_ of the noise. Hence, maxamp will be around 1, minamp will be around zero, and you get (noise-0)/1. Is that an error, or am I missing something?

Chris

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 26, 2018, 6:02pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/18 "2018-11-26T18:02:48Z")

</div>

Hi Chris,

Yes, you’re right. That was a bug in my description.

That code should actually return values from [-1,1] (which is what was going on), not [0,1]. Then that frame should be put on a neutral gray screen where zero == gray, as with DriftingGrating.

I fixed that (patch snapshot attached) and regenrated the patches as I vary all the parameters, also attached. This looks correct.  
Anything else to resolve?

Thanks,  
Mark

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 26, 2018, 6:02pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/19 "2018-11-26T18:02:48Z")

</div>

Attachments:

- [download\_(3).png](https://mworks.discourse.group/uploads/short-url/q9Sf7T3P1jb3Gg2yUPNRob52tWj.png) (61.1 KB)
- [download\_(2).png](https://mworks.discourse.group/uploads/short-url/vc819nd5aDlfDqKLLi6HAIQoIoH.png) (66.3 KB)
- [download\_(1).png](https://mworks.discourse.group/uploads/short-url/bvkfnWg71dcfuk0jna8KHlT97vG.png) (66.7 KB)
- [PastedGraphic-3.png](https://mworks.discourse.group/uploads/short-url/1zQADf9gtb5HbxGxX6YLjr4vDhx.png) (62.1 KB)
- [download\_(4).png](https://mworks.discourse.group/uploads/short-url/o01e4HW9D2z9OKPqveXuCrY13Fs.png) (72.2 KB)

---

<div class="post-metadata">

**Author:** ![cstawarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/mworks.discourse.group/cstawarz/32/3_2.png) [@cstawarz](https://mworks.discourse.group/u/cstawarz)\
**Post date:** [November 26, 2018, 7:53pm UTC](https://mworks.discourse.group/t/noise-stimulus/770/20 "2018-11-26T19:53:35Z")

</div>

Hi Mark,

> That code should actually return values from [-1,1] (which is what was going on), not [0,1]. Then that frame should be put on a neutral gray screen where zero == gray, as with DriftingGrating.

Is this different than mapping the values into [0,1], with neutral gray equal to 0.5? I’ve been doing the latter, because the OpenGL color buffer takes values between 0 and 1. If it’s not equivalent, then I don’t understand what you want.

Chris

[Next page](https://mworks.discourse.group/t/noise-stimulus/770.md?page=2)
