def make_vague(impulse=False): import os import numpy as np import MotionClouds as mc mc.N_X, mc.N_Y, mc.N_frame = 50, 2, 2048 fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) theta, B_theta = 0., np.pi / 8. alpha, sf_0, B_sf, B_V = 1., .02, .1, .1 seed = 1234565 V_X, V_Y = .1, 0. mc_wave = mc.envelope_gabor(fx, fy, ft, V_X=V_X, V_Y=V_Y, B_V=B_V, theta=theta, B_theta=B_theta, sf_0=sf_0, B_sf=B_sf, alpha=alpha) wave = mc.random_cloud(mc_wave, seed=seed, impulse=impulse) wave -= wave.mean() wave /= np.abs(wave).max() return wave
def MotionCloudNoise(sf_0=0.125, B_sf=3., figure_type='', save=False): mc.N_X, mc.N_Y, mc.N_frame = 128, 128, 1 fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) name = 'static' env = mc.envelope_gabor(fx, fy, ft, sf_0=sf_0, B_sf=B_sf, B_theta=np.inf, V_X=0., V_Y=0., B_V=0, alpha=.5) z = mc.rectif(mc.random_cloud(env)) z = z.reshape((mc.N_X, mc.N_Y)) if figure_type == 'cmap': fig, ax = plt.subplots(figsize=(13, 10.725)) cmap = ax.pcolor(np.arange(-mc.N_X / 2, mc.N_X / 2), np.arange(-mc.N_X / 2, mc.N_X / 2), MotionCloudNoise(), cmap='Greys_r') fig.colorbar(cmap) if save: plt.savefig('motioncloud_noise.pdf') return fig, ax else: return z
def creation_stimulus(info, screen, param, name_database='blackwhite'): import MotionClouds as mc from MotionClouds.display import rectif # from libpy import lena if (param.condition == 1): stimulus = (np.random.rand(info[NS_X]/2, info[NS_Y]/2) > .5) # stimulus = (np.random.rand(64, 64) > .5) elif (param.condition == 2): im = Image(ParameterSet({'N_X' : info[NS_X], 'N_Y' : info[NS_Y], 'figpath':'.', 'matpath':'.', 'datapath':'database/', 'do_mask':False, 'seed':None})) stimulus, filename, croparea = im.patch(name_database) # stimulus = lena() stimulus = np.rot90(np.fliplr(stimulus)) stimulus = rectif(stimulus, contrast=1.) else: fx, fy, ft = mc.get_grids(info[NS_X], info[NS_Y], 1) if (param.condition == 3): t, b, B_sf, sf_0 = 0, np.pi/32, 0.1, 0.15 if (param.condition == 4): t, b, B_sf, sf_0= 0, np.pi/8, 0.1, 0.15 if (param.condition == 5): t, b, B_sf, sf_0= 0, np.pi/2, 0.1, 0.15 if (param.condition == 6): t, b, B_sf, sf_0= 0, np.pi/32, 0.1, 0.03 if (param.condition == 7): t, b, B_sf, sf_0= 0, np.pi/32, 0.1, 0.075 if (param.condition == 8): t, b, B_sf, sf_0= 0, np.pi/32, 0.25, 0.15 if (param.condition == 9): t, b, B_sf, sf_0= 0, np.pi/32, 0.5, 0.15 fx, fy, ft = mc.get_grids(info[NS_X], info[NS_Y], 1) cloud = mc.random_cloud(mc.envelope_gabor(fx, fy, ft, sf_0=sf_0, B_sf=B_sf, theta=t, B_theta=b, B_V=1000.)) cloud = rectif(cloud, contrast=1.) stimulus = cloud[:, :, 0] return (stimulus)
def generate_random_cloud(theta, B_theta, downscale=1): fx, fy, ft = mc.get_grids(mc.N_X / downscale, mc.N_Y / downscale, 1) mc_i = mc.envelope_gabor(fx, fy, ft, V_X=0., V_Y=0., B_V=0, theta=theta, B_theta=B_theta) im = mc.random_cloud(mc_i) im = (mc.rectif(im) * 255).astype('uint8') fname = 'tmp/%s_%s.png' % (theta, B_theta) imageio.imwrite(fname, im[:, :, 0]) return fname
def generate_cloud(theta, b_theta, sf_0, N_X, N_Y, seed, contrast=1): fx, fy, ft = mc.get_grids(N_X, N_Y, 1) mc_i = mc.envelope_gabor(fx, fy, ft, V_X=0., V_Y=0., B_V=0., sf_0=sf_0, B_sf=sf_0, theta=theta, B_theta=b_theta) im_ = mc.rectif(mc.random_cloud(mc_i, seed=seed), contrast=contrast) return im_[:, :, 0]
def make_vague(impulse=False): name = 'waves' import os import numpy as np import MotionClouds as mc mc.N_X, mc.N_Y, mc.N_frame = 128, 32, 512 fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) theta, B_theta, B_wave = 0., np.pi/8., .1 alpha, sf_0, B_sf, B_V = 2., .25, .3, 2. alpha, sf_0, B_sf, B_V = 1., .1, .3, 2. seed = 1234565 V_X, V_Y, g = .5, 0., .1 V_X, V_Y, g = .5, 0., 2 loggabor=True B_v = .025 def envelope_gravity(fx, fy, ft, B_wave, g=.1): """ Gravitational envelope: selects the plane corresponding to the speed (V_X, V_Y) with some thickness B_V """ k = fx*V_X+fy*V_Y env = np.exp(-.5*(((ft/.5)**2-g*np.sqrt(((k/.5)**2)))**2/(B_wave*mc.frequency_radius(fx, fy, ft, ft_0=np.inf))**2)) env *= (ft*k) < 0 return env def envelope_gabor_wave(fx, fy, ft, B_wave, V_X=mc.V_X, V_Y=mc.V_Y, B_V=mc.B_V, B_v=1., sf_0=mc.sf_0, B_sf=mc.B_sf, loggabor=mc.loggabor, theta=mc.theta, B_theta=mc.B_theta, alpha=mc.alpha): """ Returns the Motion Cloud kernel """ envelope = mc.envelope_gabor(fx, fy, ft, V_X=V_X, V_Y=V_Y, B_V=B_V, sf_0=sf_0, B_sf=B_sf, loggabor=loggabor, theta=theta, B_theta=B_theta, alpha=alpha) envelope *= envelope_gravity(fx, fy, ft, B_wave=B_wave) return envelope B_v_low, B_v_high = .025, .1 mc_vague = envelope_gabor_wave(fx, fy, ft, V_X=1., V_Y=0., B_wave=B_v_low, B_V=B_V, theta=theta, B_theta=B_theta, sf_0=sf_0, B_sf=B_sf, alpha=alpha) return mc.rectif(mc.random_cloud(mc_vague, seed=seed, impulse=impulse))
def create_stimulus(info, return_env=False): control(info) import numpy as np fx, fy, ft = mc.get_grids(info[height], info[width], info[frame]) env_color = 1 env_orientation = 1 env_radial = 1 env_speed = 1 if (info[color] == True): if (info[ft_0] == True): ft_0_color = np.inf else: ft_0_color = 1 env_color = mc.envelope_color(fx, fy, ft, alpha=info[alpha], ft_0=ft_0_color) if (info[orientation] == True): env_orientation = mc.envelope_orientation(fx, fy, ft, theta=info[theta], B_theta=info[B_theta]) if (info[radial] == True): if (info[ft_0b] == True): ft_0_radial = np.inf else: ft_0_radial = 1 env_radial = mc.envelope_radial(fx, fy, ft, sf_0=info[sf_0], B_sf=info[B_sf], ft_0=ft_0_radial, loggabor=info[loggabor]) if (info[speed] == True): env_speed = mc.envelope_speed(fx, fy, ft, V_X=info[V_X], V_Y=info[V_Y], B_V=info[B_V]) env = env_color * env_orientation * env_radial * env_speed if (info[random_cloud] == True): if (info[seed] == 'None'): seed_t = None else: seed_t = int(info[seed]) env = mc.random_cloud(env, seed=seed_t, impulse=info[impulse], do_amp=info[do_amp]) env = mc.rectif(env, contrast=1.) env = env * 255 if (return_env == True): return (env) stimulus = np.zeros([info[height], info[width], info[frame], 3]).astype(int) if (info[isoluminance] == True): stimulus[:, :, :, 0] = env stimulus[:, :, :, 1] = 255 - env stimulus[:, :, :, 2] = 127 else: for i in range(3): stimulus[:, :, :, i] = env[:, :, :] return(stimulus)
def make_vague(impulse=False): import os import numpy as np import MotionClouds as mc mc.N_X, mc.N_Y, mc.N_frame = 50, 2, 2048 fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) theta, B_theta = 0., np.pi/8. alpha, sf_0, B_sf, B_V = 1., .02, .1, .1 seed = 1234565 V_X, V_Y = .1, 0. mc_wave = mc.envelope_gabor(fx, fy, ft, V_X=V_X, V_Y=V_Y, B_V=B_V, theta=theta, B_theta=B_theta, sf_0=sf_0, B_sf=B_sf, alpha=alpha) wave = mc.random_cloud(mc_wave, seed=seed, impulse=impulse) wave -= wave.mean() wave /= np.abs(wave).max() return wave
def wave(self): filename = f'{self.cachepath}/{self.opt.tag}_wave.npy' if self.opt.cache and os.path.isfile(filename): z = np.load(filename) else: # A simplistic model of a wave using https://github.com/NeuralEnsemble/MotionClouds import MotionClouds as mc fx, fy, ft = mc.get_grids(self.opt.nx, self.opt.ny, self.opt.nframe) env = mc.envelope_gabor(fx, fy, ft, V_X=self.opt.V_Y, V_Y=self.opt.V_X, B_V=self.opt.B_V, sf_0=self.opt.sf_0, B_sf=self.opt.B_sf, theta=self.opt.theta, B_theta=self.opt.B_theta) z = mc.rectif(mc.random_cloud(env, seed=self.opt.seed)) if self.opt.cache: np.save(filename, z) return z
print('Could not load gui... running with defaut parameters') print(info) info['timeStr'] = time.strftime("%b_%d_%H%M", time.localtime()) fileName = 'data/discriminating_v2_' + info['observer'] + '_' + info['timeStr'] + '.pickle' #save to a file for future use (ie storing as defaults) if dlg.OK: misc.toFile(fileName, info) else: print('Interrupted gui... quitting') core.quit() #user cancelled. quit print('generating data') alphas = [-1., -.5, 0., 0.5, 1., 1.5, 2.] fx, fy, ft = mc.get_grids(info['N_X'], info['N_Y'], info['N_frame_total']) colors = [mc.envelope_color(fx, fy, ft, alpha=alpha) for alpha in alphas] slows = [2*mc.rectif(mc.random_cloud(color * mc.envelope_gabor(fx, fy, ft, V_Y=0., V_X = 1.1, B_sf = 10.))) - 1 for color in colors] fasts = [2*mc.rectif(mc.random_cloud(color * mc.envelope_gabor(fx, fy, ft, V_Y=0., V_X = 0.9, B_sf = 10.))) - 1 for color in colors] print('go! ') win = visual.Window([info['screen_width'], info['screen_height']], fullscr=True) stimLeft = visual.GratingStim(win, size=(info['screen_width']/2, info['screen_width']/2), pos=(-info['screen_width']/4, 0), units='pix', interpolate=True, mask = 'gauss', autoLog=False)#this stim changes too much for autologging to be useful
#!/usr/bin/env python # -*- coding: utf-8 -*- """ Demonstration of doing plaids using MotionClouds. Used to generate page: http://invibe.net/LaurentPerrinet/SciBlog/2011-07-12 (c) Laurent Perrinet - INT/CNRS """ import numpy as np import MotionClouds as mc fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) name = 'MotionPlaid' vext = '.gif' # show example table = """ #acl LaurentPerrinet,LaurentPerrinetGroup:read,write,delete,revert All: #format wiki ----- = MotionPaids : from MotionClouds components to a plaid-like stimulus = """ theta1, theta2, B_theta = np.pi/4., -np.pi/4., np.pi/32 diag1 = mc.envelope_gabor(fx, fy, ft, theta=theta1, V_X=np.cos(theta1), V_Y=np.sin(theta1), B_theta=B_theta)
import itertools # size = 2**4 # size = 2**5 size = 2**6 # size = 2**7 space = 1.5 * size # space between 2 cubes N = 5 idx = np.arange(N) pos = idx * space Bf = np.logspace(-2., 0.1, N) Bv = [0.01, 0.1, 0.5, 1.0, 10.0] sigma_div = [2, 3, 5, 8, 13] # I love the golden number :-) Bo = np.pi/np.array(sigma_div) fx, fy, ft = mc.get_grids(size, size, size) # x-axis = B_f # y-axis = B_V # z_axis = B_o downscale = 1 # downscale =2 # downscale = 1./2 mlab.figure(1, bgcolor=(.6, .6, .6), fgcolor=(0, 0, 0), size=(1600/downscale,1200/downscale)) mlab.clf() do_grid, do_splatter, do_MCs = False, True, False do_grid, do_splatter, do_MCs = True, True, True ################################################################################ ## Generate the cubical graph structure to connect each individual cube ##
""" import os import scipy import MotionClouds as mc import numpy as np # uncomment to preview movies # vext, display = None, True #------------------------- Zipped grating ------------------------------- # name = 'zipped_grating' #initialize - fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) sf_0 = 0.2 B_sf = sf_0 / 4. alpha = 1.0 V_X = 0.5 B_V = V_X / 10. name_ = mc.figpath + name for seed in range(424242, 424242+8): name_ = mc.figpath + name + '-seed-' + str(seed) mc.figures_MC(fx, fy, ft, name_, B_V=B_V, sf_0=sf_0, B_sf=B_sf, V_X=V_X, theta=np.pi/4., alpha=alpha, seed=seed, vext='.zip') #-------------------- Narrowband vs Braodband experiment ---------------- # vext = '.mpg' #vext = '.mat' #vext = '.zip'
# Setting up the conditions: condList = data.importConditions(conditionsFilePath) grtList = [] for thisCondition in condList: # grating name: grtSz = thisCondition['szL'] thisSf = thisCondition['sfL'] thisBsf = thisCondition['BsfL'] if thisCondition['dirL'] < 0: # this means clockwise or CCW motion thisV = 0 else: # translational motion thisV = thisCondition['vL'] thisBv = thisCondition['BvL'] grtName = precompiledDir + os.sep + 'mc_' + str(thisV) + '_sf' + str(thisSf) + \ '_bsf' + str(thisBsf) + '_bv' + str(thisBv) + '_sz' + str(grtSz) if grtName not in grtList: grtList.append(grtName) # compiling the gratings: szX = grtSz szY = szX fx, fy, ft = mc.get_grids(szX, szY, nFrames) grtCol = mc.envelope_color(fx, fy, ft) z = mc.envelope_gabor(fx, fy, ft, sf_0=thisSf, B_sf=thisBsf, V_X=thisV, B_V=thisBv, B_theta=np.inf) zcl = mc.random_cloud(grtCol * z) grtL = 2*mc.rectif(zcl) - 1 # saving the gratings: np.save(grtName, grtL) # mc.figures(grtL, grtName, vext='.mkv') print 'precompiled ' + grtName
sat = thisTrial['colStart'] # alpha value colStep = thisTrial['colStep'] # alpha step print 'sat=' + str(sat) + '; colStep=' + str(colStep) colOdd = [150,1,1] # green colEven = [330,sat,1] # red is adjusted and is assigned to gratings in even frames # initiating the gratings if precompileMode: grtL = np.load(precompiledDir + os.sep + 'mc_' + '{0:.1f}'.format(vL) + '_sf' + str(sfL) + '_bsf' + str(BsfL) + '_bv' + str(BvL) + '_sz' + str(szL) + '.npy') grtR = np.load(precompiledDir + os.sep + 'mc_' + '{0:.1f}'.format(vR) + '_sf' + str(sfR) + '_bsf' + str(BsfR) + '_bv' + str(BvR) + '_sz' + str(szR) + '.npy') else: fx, fy, ft = mc.get_grids(szL, szL, nFrames) grtCol = mc.envelope_color(fx, fy, ft) grtL = 2*mc.rectif(mc.random_cloud(grtCol * mc.envelope_gabor(fx, fy, ft, sf_0=sfL, B_sf=BsfL, B_V=BvL, V_X=vL, B_theta=np.inf))) - 1 fx, fy, ft = mc.get_grids(szR, szR, nFrames) grtCol = mc.envelope_color(fx, fy, ft) grtR = 2*mc.rectif(mc.random_cloud(grtCol * mc.envelope_gabor(fx, fy, ft, sf_0=sfR, B_sf=BsfR, B_V=BvR, V_X=vR, B_theta=np.inf))) - 1 # Creating a mask, which is fixed for a given trial: curMask = combinedMask(fovGap, fovFade, periGap, periFade) # Using the mask to assign both the greyscale values and the mask for our color masks: colMaskL.tex = (curMask + 1)/2
import libpy as lb import numpy as np import sys, os import MotionClouds as mc h = 400 w = 200 f = 64 fx, fy, ft = mc.get_grids(h, w, f) color = mc.envelope_color(fx, fy, ft) env = color * mc.envelope_speed(fx, fy, ft) env = mc.envelope_gabor(fx, fy, ft) env = mc.random_cloud(env) env = mc.rectif(env, contrast=1.) tomat = env env = env * 255 stimulus = np.zeros([h, w, f, 3]).astype(int) i = 0 while (i != f): if (i % 2 == 0): stimulus[:, :, i, 0] = env[:, :, i] stimulus[:, :, i, 1] = 0 # 128 #env[:, :, i] stimulus[:, :, i, 2] = 0 # 255 - env[:, :, i] else: #stimulus[:, :, i, 0] = 255 - env[:, :, i] stimulus[:, :, i, 1] = 255 - env[:, :, i] stimulus[:, :, i, 0] = 0 #128 #env[:, :, i] stimulus[:, :, i, 2] = 0 #env[:, :, i] # stimulus[:, :, i, :] = 255 - env[:, :, i, np.newaxis]
def create_stimulus(info, return_env=False): control(info) import numpy as np fx, fy, ft = mc.get_grids(info[height], info[width], info[frame]) env_color = 1 env_orientation = 1 env_radial = 1 env_speed = 1 if (info[color] == True): if (info[ft_0] == True): ft_0_color = np.inf else: ft_0_color = 1 env_color = mc.envelope_color(fx, fy, ft, alpha=info[alpha], ft_0=ft_0_color) if (info[orientation] == True): env_orientation = mc.envelope_orientation(fx, fy, ft, theta=info[theta], B_theta=info[B_theta]) if (info[radial] == True): if (info[ft_0b] == True): ft_0_radial = np.inf else: ft_0_radial = 1 env_radial = mc.envelope_radial(fx, fy, ft, sf_0=info[sf_0], B_sf=info[B_sf], ft_0=ft_0_radial, loggabor=info[loggabor]) if (info[speed] == True): env_speed = mc.envelope_speed(fx, fy, ft, V_X=info[V_X], V_Y=info[V_Y], B_V=info[B_V]) env = env_color * env_orientation * env_radial * env_speed if (info[random_cloud] == True): if (info[seed] == 'None'): seed_t = None else: seed_t = int(info[seed]) env = mc.random_cloud(env, seed=seed_t, impulse=info[impulse], do_amp=info[do_amp]) env = mc.rectif(env, contrast=1.) env = env * 255 if (return_env == True): return (env) stimulus = np.zeros([info[height], info[width], info[frame], 3]).astype(int) if (info[isoluminance] == True): stimulus[:, :, :, 0] = env stimulus[:, :, :, 1] = 255 - env stimulus[:, :, :, 2] = 127 else: for i in range(3): stimulus[:, :, :, i] = env[:, :, :] return (stimulus)
loops = 2 # %% Motion clouds # V_X and V_Y determine the speed in x and y direction # (V_X, V_Y) = (0,1) is downward and (V_X, V_Y) = (1, 0) is rightward # A speed of V_X=1 corresponds to an average displacement of 1/N_X per frame # B_V determines the bandwidth fo the speed # theta determines the mean orientation (in radians, von-Mises distribution) # B_theta is the bandwidth of the orientation (in radians) # (standard deviation of the Gaussian envelope; HWHH = 2*B_theta_**2*np.log(2)) # sf_0 determines the preferred spatial frequency # B_sf determines the bandwidth of spatial frequency fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) seed = 1234 size = 5 N_X, N_Y, N_frame = 2**size, 2**size, mc.N_frame fx, fy, ft = mc.get_grids(N_X, N_Y, N_frame) N_orient = 9 # %% x, y = np.meshgrid( np.arange(-N_orient / 2., N_orient / 2.) + 0.5, np.arange(-N_orient / 2., N_orient / 2.) + 0.5) def cart2pol(x, y):
# Les imports classiques # In[1]: import numpy as np import MotionClouds as mc import imageio import matplotlib.pyplot as plt # Les paramètres de sauvegarde # On défini la résolution en x-y (pixels) et t (ms) # In[2]: fx, fy, ft = mc.get_grids(512, 512, 128) # L'envelope gabor du stimulus est généré, avec les paramètres : # * theta l'angle du stimulus # * b_theta l'ouverture des gabors (donc le niveau de bruit) # * sf_0 et b_sf les fréquences spatiales # In[3]: envelope = mc.envelope_gabor(fx, fy, ft, V_X=1., V_Y=0., B_V=.1, sf_0=.15,
(c) Laurent Perrinet - INT/CNRS """ # width and height of your screen w, h = 1920, 1200 w, h = 2560, 1440 # width and height of the stimulus w_stim, h_stim = 1024, 1024 loops = 1 import MotionClouds as mc print 'started get_grids' fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) print 'started color' color = mc.envelope_color(fx, fy, ft) print 'started enveope' env = color *(mc.envelope_gabor(fx, fy, ft, V_X=1.) + mc.envelope_gabor(fx, fy, ft, V_X=-1.)) print 'started rectif' z = 2*mc.rectif(mc.random_cloud(env), contrast=.5) -1. print 'ended motion clouds' #from pyglet.gl import gl_info from psychopy import visual, core, event, logging logging.console.setLevel(logging.DEBUG) print 'started stim' win = visual.Window([w, h], fullscr=True) stim = visual.GratingStim(win,
def make_vague(impulse=False): name = "waves" import os import numpy as np import MotionClouds as mc mc.N_X, mc.N_Y, mc.N_frame = 128, 32, 512 fx, fy, ft = mc.get_grids(mc.N_X, mc.N_Y, mc.N_frame) theta, B_theta, B_wave = 0.0, np.pi / 8.0, 0.1 alpha, sf_0, B_sf, B_V = 2.0, 0.25, 0.3, 2.0 alpha, sf_0, B_sf, B_V = 1.0, 0.1, 0.3, 2.0 seed = 1234565 V_X, V_Y, g = 0.5, 0.0, 0.1 V_X, V_Y, g = 0.5, 0.0, 2 loggabor = True B_v = 0.025 def envelope_gravity(fx, fy, ft, B_wave, g=0.1): """ Gravitational envelope: selects the plane corresponding to the speed (V_X, V_Y) with some thickness B_V """ k = fx * V_X + fy * V_Y env = np.exp( -0.5 * ( ((ft / 0.5) ** 2 - g * np.sqrt(((k / 0.5) ** 2))) ** 2 / (B_wave * mc.frequency_radius(fx, fy, ft, ft_0=np.inf)) ** 2 ) ) env *= (ft * k) < 0 return env def envelope_gabor_wave( fx, fy, ft, B_wave, V_X=mc.V_X, V_Y=mc.V_Y, B_V=mc.B_V, B_v=1.0, sf_0=mc.sf_0, B_sf=mc.B_sf, loggabor=mc.loggabor, theta=mc.theta, B_theta=mc.B_theta, alpha=mc.alpha, ): """ Returns the Motion Cloud kernel """ envelope = mc.envelope_gabor( fx, fy, ft, V_X=V_X, V_Y=V_Y, B_V=B_V, sf_0=sf_0, B_sf=B_sf, loggabor=loggabor, theta=theta, B_theta=B_theta, alpha=alpha, ) envelope *= envelope_gravity(fx, fy, ft, B_wave=B_wave) return envelope B_v_low, B_v_high = 0.025, 0.1 mc_vague = envelope_gabor_wave( fx, fy, ft, V_X=1.0, V_Y=0.0, B_wave=B_v_low, B_V=B_V, theta=theta, B_theta=B_theta, sf_0=sf_0, B_sf=B_sf, alpha=alpha, ) return mc.rectif(mc.random_cloud(mc_vague, seed=seed, impulse=impulse))