# triggering signal will be required at the beginning! class FlashProtocol(Protocol): name = "flash protocol" def __init__(self): super().__init__() self.pause_duration = 1. self.flash_duration = 2. def get_stim_sequence(self): stimuli = [ TriggerStimulus(), Pause(duration=self.pause_duration), FullFieldVisualStimulus(duration=self.flash_duration, color=(0, 255, 0)), Pause(duration=self.pause_duration), TriggerStimulus(), Pause(duration=self.pause_duration), FullFieldVisualStimulus(duration=self.flash_duration, color=(255, 0, 0)), Pause(duration=self.pause_duration), ] return stimuli if __name__ == "__main__": trigger = ZmqTrigger(port="5555") st = Stytra(protocol=FlashProtocol(), scope_triggering=trigger)
from stytra import Stytra if __name__ == "__main__": from stytra.examples.gratings_exp import GratingsProtocol # We make a new instance of Stytra with this protocol as the only option: s = Stytra(protocol=GratingsProtocol(), stim_plot=True)
for i in range(self.n_looms): # The radius is only specified at the beginning and at the # end of expansion. More elaborate functional relationships # than linear can be implemented by specifying a more # detailed interpolation table radius_df = pd.DataFrame( dict( t=[0, np.random.rand() * self.max_loom_duration], radius=[0, np.random.rand() * self.max_loom_size], )) # We construct looming stimuli with the radius change specification # and a random point of origin within the projection area # (specified in fractions from 0 to 1 for each dimension) stimuli.append( LoomingStimulus( background_color=(255, 255, 255), circle_color=(0, 0, 0), df_param=radius_df, origin=(self.x_pos_pix, self.y_pos_pix), )) return stimuli if __name__ == "__main__": # We make a new instance of Stytra with this protocol as the only option: s = Stytra(protocol=LoomingProtocol())
# Abituation phase: for _ in range(self.abituation_trials_n): stimuli.append( ClosedLoop1DGratings( df_param=df, grating_angle=np.pi / 2, wave_shape="sine", grating_period=1 / self.baseline_grating_freq, grating_col_1=(255,) * 3, ) ) freq_list = self.grating_freq_list * self.trials_n shuffle(freq_list) # Actual acuity testing: for freq in freq_list: stimuli.append( ClosedLoop1DGratings( df_param=df, grating_angle=np.pi / 2, wave_shape="sine", grating_period=1 / freq, ) ) return stimuli if __name__ == "__main__": s = Stytra(protocol=ClosedLoop1DProt())
from pathlib import Path from stytra import Stytra from stytra.examples.gratings_exp import GratingsProtocol REQUIRES_EXTERNAL_HARDWARE = False class TrackingGratingsProtocol(GratingsProtocol): name = "gratings_tail_tracking" # To add tracking to a protocol, we simply need to add a tracking # argument to the stytra_config: stytra_config = dict( tracking=dict(embedded=True, method="tail"), camera=dict(video_file=str( Path(__file__).parent / "assets" / "fish_compressed.h5")), ) if __name__ == "__main__": s = Stytra(protocol=TrackingGratingsProtocol())
from multiprocessing import Event from stytra.collectors import FramerateQueueAccumulator import qdarkstyle from PyQt5.QtWidgets import QApplication from stytra.hardware.video.write import VideoWriter from stytra.stimulation import Protocol, Pause from stytra.stimulation.stimuli import FullFieldVisualStimulus from lightparam import Param from stytra.experiments.tracking_experiments import CameraVisualExperiment from stytra.tracking.tracking_process import DispatchProcess from stytra import Stytra # Here ve define an empty protocol: class PauseProtocol(Protocol): name = "camera_recording_protocol" # every protocol must have a name. def __init__(self): super().__init__() self.period_sec = Param(10.0, limits=(0.2, None)) def get_stim_sequence(self): return [Pause(duration=self.period_sec)] if __name__ == "__main__": st = Stytra(protocol=PauseProtocol(), recording=True)
frozen = [] for j, c in enumerate(choices): if c is None: coh.extend([0, 0]) frozen.extend([1, 1]) else: coh.extend([c, c]) frozen.extend([0, 0]) t.extend([j * d, (j + 1) * d]) coherence_df = pd.DataFrame(dict(t=t, coherence=coh, frozen=frozen)) return [ RandomDotKinematogram( df_param=coherence_df, theta=self.theta * (np.pi / 180), dot_radius=self.dot_radius, color_dots=(0, 0, 0), color_bg=(255, 255, 255), velocity=self.velocity, max_coherent_for=self.max_coherent_for, dot_density=self.dot_density, ) ] if __name__ == "__main__": stytra = Stytra(protocol=Exp26Protocol())
def get_stim_sequence(self): stimuli = [] # The phototaxis stimulus for zebrafish is bright on one side of the # fish and dark on the other. The type function combines two classes: stim = type("phototaxis", (FishTrackingStimulus, HalfFieldStimulus), {}) # The stimuli are a sequence of a phototactic stimulus and full-field # illumination for i in range(self.n_trials): # The stimulus of interest is wrapped in a CenteringStimulus, # so if the fish moves out of the field of view, a stimulus is # displayed which brings it back stimuli.append( CenteringWrapper(stimulus=stim( duration=self.stim_on_duration, color=(self.brightness, ) * 3, center_dist=self.center_offset, ))) stimuli.append( FullFieldVisualStimulus(color=(self.brightness, ) * 3, duration=self.stim_off_duration)) return stimuli if __name__ == "__main__": s = Stytra(protocol=PhototaxisProtocol())
name = 'voltage_protocol' def __init__(self): super().__init__() self.add_params(v_min=1., v_max=4., time_up=5., time_down=10.) def get_stim_sequence(self): v_list = [ self.params['v_min'], self.params['v_max'], self.params['v_min'] ] t_list = [0, self.params['time_up'], self.params['time_down']] df = pd.DataFrame(dict(t=t_list, voltage=v_list)) # stimuli = [Pause(duration=1), # SetVoltageStimulus(duration=1, voltage=0), # SetVoltageStimulus(duration=1, voltage=1), # SetVoltageStimulus(duration=1, voltage=2) # ] stimuli = [InterpolatedVoltageStimulus(df_param=df)] return stimuli if __name__ == "__main__": st = Stytra(protocols=[VoltageProtocol]) st.base.close() # import nidaqmx from nidaqmx.stream_readers import AnalogSingleChannelReader from nidaqmx.stream_writers import AnalogSingleChannelWriter # with nidaqmx.Task() as task: # task.ao_channels.add_ao_voltage_chan("Dev1/ao0") # task.write(1.0)
super().__init__() self.theta = Param(0, (-360, 360)) self.delta = Param(0, (-360, 360)) def get_stim_sequence(self): MovingStim = type( "MovingStim", (FishRelativeStimulus, InterpolatedStimulus, SeamlessImageStimulus), dict(), ) motion_df = pd.DataFrame( dict(t=[0, 10, 120], x=[50, 50, 1200], y=[50, 50, 50])) stimuli = [ MovingStim( background=Path(__file__).parent / "assets" / "coordinate_system.png", df_param=motion_df, duration=300, x=self.delta, y=self.delta, theta=self.theta * np.pi / 180, ) ] return stimuli if __name__ == "__main__": st = Stytra(protocol=BackgroundProtocol())
from lightparam import Param from stytra import Stytra from stytra.stimulation import Protocol from stytra.stimulation.stimuli import Pause fa = 5 # repetition of stimulus class PauseProtocol(Protocol): name = "free_swimming_protocol" stytra_config = dict(tracking=dict(method="fish"), log_format="hdf5") def __init__(self): super().__init__() # Specify parameters as Param(something) to change them from the interface. If yuo dont care, yust type the umbers self.duration = Param(600.0, limits=(20, 3000)) def get_stim_sequence(self): stimuli = [Pause(duration=self.duration)] return stimuli if __name__ == "__main__": # We make a new instance of Stytra with this protocol as the only option: s = Stytra(protocol=PauseProtocol())
LoomingStimulus = type("LoomingStimulus", (InterpolatedStimulus, CircleStimulus), {}) for i in range(self.params["n_looms"]): # The radius is only specified at the beginning and at the # end of expansion. More elaborate functional relationships # than linear can be implemented by specifying a more # detailed interpolation table radius_df = pd.DataFrame( dict( t=[0, np.random.rand() * self.params["max_loom_duration"]], radius=[ 0, np.random.rand() * self.params["max_loom_size"] ], )) # We construct looming stimuli with the radius change specification # and a random point of origin within the projection area # (specified in fractions from 0 to 1 for each dimension) stimuli.append(LoomingStimulus(df_param=radius_df, origin=(30, 30))) return stimuli if __name__ == "__main__": # We make a new instance of Stytra with this protocol as the only option s = Stytra(protocols=[LoomingProtocol])
return False class FlashProtocol(Protocol): name = "flash protocol" def __init__(self): super().__init__() self.add_params(period_sec=5., flash_duration=2.) def get_stim_sequence(self): stimuli = [ Pause(duration=self.params["period_sec"] - self.params["flash_duration"]), FullFieldVisualStimulus(duration=self.params["flash_duration"], color=(255, 255, 255)), ] return stimuli if __name__ == "__main__": # Select a directory: path = "." # Instantiate the trigger: trigger = NewFileTrigger(path) # Call stytra assigning the triggering. Note that stytra will wait for # the trigger only if the "wait for trigger" checkbox is ticked! st = Stytra(protocols=[FlashProtocol], trigger=trigger)
from pathlib import Path from stytra import Stytra from stytra.examples.windmill_exp import WindmillProtocol REQUIRES_EXTERNAL_HARDWARE = False class TrackingWindmillProtocol(WindmillProtocol): name = "windmill" # To add tracking to a protocol, we simply need to add a tracking # argument to the stytra_config: stytra_config = dict( tracking=dict(embedded=True, method="eyes"), camera=dict(video_file=str( Path(__file__).parent / "assets" / "fish_compressed.h5")), ) if __name__ == "__main__": s = Stytra(protocol=TrackingWindmillProtocol())
t_base = [0, p, p, p + d, p + d, 2 * p + d] vel_base = [0, 0, -v, -v, 0, 0] t = [0] vel = [0] gain = [0] # Low, medium, high gain: for g in gain_values: t.extend(t[-1] + np.array(t_base)) vel.extend(vel_base) gain.extend([0] * 2 + [g] * 2 + [0] * 2) df = pd.DataFrame(dict(t=t, base_vel=vel, gain=gain)) ClosedLoop1DGratings = type("Stim", (GainLagClosedLoop1D, GratingStimulus), {}) stimuli.append( ClosedLoop1DGratings( df_param=df, grating_angle=np.pi / 2, grating_period=self.grating_cycle, grating_col_1=(255, ) * 3, )) return stimuli if __name__ == "__main__": Stytra(protocol=Portugues2011Protocol())
class CombinedProtocol(Protocol): name = "combined_custom_protocol" # every protocol must have a name. stytra_config = dict( tracking=dict(method="tail", estimator="vigor"), camera=dict(video_file=str( Path(__file__).parent / "assets" / "fish_compressed.h5")), ) def get_stim_sequence(self): # This is the # Use six points to specify the velocity step to be interpolated: t = [0, 7] vel = np.array([10, 10]) df = pd.DataFrame(dict(t=t, vel_x=vel)) s_a = MovingGratingStimulus(df_param=df, clip_mask=[0, 0, 1, 0.5]) df = pd.DataFrame(dict(t=t, vel_x=-vel)) s_b = MovingGratingStimulus(df_param=df, grating_angle=180, clip_mask=[0, 0.5, 1, 0.5]) stimuli = [ConditionalCombiner([s_a, s_b])] return stimuli if __name__ == "__main__": st = Stytra(protocol=CombinedProtocol())
class FlashProtocol(Protocol): name = "flash protocol" def __init__(self): super().__init__() self.add_params(period_sec=5., flash_duration=2.) def get_stim_sequence(self): stimuli = [ Pause(duration=self.params["period_sec"] - self.params["flash_duration"]), FullFieldVisualStimulus(duration=self.params["flash_duration"], color=(255, 255, 255)), ] return stimuli if __name__ == "__main__": # trigger = Crappy2PTrigger(r'C:\Users\lpetrucco\Desktop\dummydir') # trigger.start() trigger = ZmqTrigger(port="5555") st = Stytra( protocols=[FlashProtocol], trigger=trigger, directory=r"C:\Users\portugueslab\Desktop\metadata", ) # trigger.terminate_event.set() # print('terminating') # trigger.join()
self.diet = Param("Humans", ["Humans", "Ships", "Unknown"]) # Redefine age with units: self.age = Param(500, limits=(1, 10000), unit="years") # A simple integer, with limits: self.n_tentacles = Param(8, limits=(1, 200)) # An integer with inferior boundary only (no upper limit for the terror): self.n_casualties = Param(8, limits=(1, None)) # A simple float, with limits and measure units: self.dimensions = Param(8.0, limits=(0.5, 100), unit="m") # Some parameters are already defined in the AnimalMetadata class # (species, genotype, comments, id). Here we overwrite them: self.id = Param("") # Define some uninteresting stytra protocol for our docile animal: class FlashProtocol(Protocol): name = "empty_protocol" def get_stim_sequence(self): return [Pause(duration=4.0)] # Finally, just pass Stytra the new class with the keyword "metadata_animal": # Remember to pass the metadata class - KrakenMetadata - and not the object # - KrakenMetadata(). # If you are testing Stytra functionalities you might want to remove the # "stytra_last_config.json" file from user folder after testing this! if __name__ == "__main__": st = Stytra(protocol=FlashProtocol(), metadata_animal=KrakenMetadata)
# The "display overlay" attribute, which does not necessarily have to be # specified, will allow us to overimpose on the GUI an ellipse to monitor # live our tracking. class DrosophilaPipeline(Pipeline): def __init__(self): super().__init__() self.bgsub = BackgroundSubtractor(parent=self.root) self.eyetrack = FlyTrackingMethod(parent=self.bgsub) self.display_overlay = FlyTrackingSelection # Here we define our stumulus protocol (empty in this case), passing in the # config dictionary our custom pipeline: class FlyTrackingProtocol(Protocol): name = "fly_tracking" stytra_config = dict( tracking=dict(method=DrosophilaPipeline), camera=dict(video_file=str(r"/Users/luigipetrucco/Desktop/video.hdf5")), ) def get_stim_sequence(self): # Empty protocol of specified duration: return [Pause(duration=10)] if __name__ == "__main__": s = Stytra(protocol=FlyTrackingProtocol())
self.inter_stim_pause = Param(2.) self.theta_amp = Param(np.pi / 2) self.windmill_freq = Param(0.2) self.grating_vel = Param(10) self.stim_duration = Param(5.) self.wave_shape = Param(value="square", limits=["square", "sinusoidal"]) self.n_arms = Param(10) def get_stim_sequence(self): stimuli = [] p = self.inter_stim_pause / 2 d = self.stim_duration # Windmill STEPS = 0.005 t = np.arange(0, d, STEPS) theta = np.sin(2 * np.pi * t * self.windmill_freq) * self.theta_amp t = [t[0]] + list(t + p) + [(t + 2 * p)[-1]] theta = [theta[0]] + list(theta) + [theta[-1]] df = pd.DataFrame(dict(t=t, theta=theta)) stimuli.append(MovingWindmillStimulus(df_param=df)) return stimuli if __name__ == "__main__": # We make a new instance of Stytra with this protocol as the only option: s = Stytra(protocol=WindmillProtocol())
gain.extend([0, 0, g, g, 0, 0]) df = pd.DataFrame(dict(t=t, vel=vel, gain=gain)) stimuli.append(ClosedLoop1DGratings(df, grating_angle=np.pi/2, grating_period=self.params[ 'grating_cycle'], color=(255, )*3)) return stimuli if __name__ == "__main__": save_dir = r'D:\vilim\stytra\\' camera_config = dict(type="ximea") tracking_config = dict( embedded=True, tracking_method="angle_sweep", estimator="vigor" ) display_config = dict(full_screen=True) # We make a new instance of Stytra with this protocol as the only option s = Stytra( protocols=[ClosedLoop1D], camera_config=camera_config, tracking_config=tracking_config, display_config=display_config, dir_save=save_dir, )
self.grating_period = Param(10) # grating spatial period self.grating_angle_deg = Param(90.0) # grating orientation def get_stim_sequence(self): # Use six points to specify the velocity step to be interpolated: t = [ 0, self.t_pre, self.t_pre, self.t_pre + self.t_move, self.t_pre + self.t_move, 2 * self.t_pre + self.t_move, ] vel = [0, 0, self.grating_vel, self.grating_vel, 0, 0] df = pd.DataFrame(dict(t=t, vel_x=vel)) return [ MovingGratingStimulus( df_param=df, grating_angle=self.grating_angle_deg * np.pi / 180, grating_period=self.grating_period, ) ] if __name__ == "__main__": # We make a new instance of Stytra with this protocol as the only option s = Stytra(protocol=GratingsProtocol())
def paint(self, p, w, h): p.setBrush(QBrush(QColor(*self.color))) # Use chosen color p.drawRect(QRect(0, 0, w, h)) # draw full field rectangle def update(self): fish_vel = self._experiment.estimator.get_velocity() # change color if speed of the fish is higher than threshold: if fish_vel < -5: self.color = (255, 0, 0) else: self.color = (255, 255, 255) class CustomProtocol(Protocol): name = "custom protocol" # protocol name stytra_config = dict( tracking=dict(method="tail", estimator="vigor"), camera=dict( video_file=str(Path(__file__).parent / "assets" / "fish_compressed.h5") ), ) def get_stim_sequence(self): return [NewStimulus(duration=10)] if __name__ == "__main__": Stytra(protocol=CustomProtocol())
from stytra import Stytra from stytra.stimulation.stimuli import Pause from pathlib import Path from stytra.stimulation import Protocol class Nostim(Protocol): name = "empty_protocol" # In the stytra_config class attribute we specify a dictionary of # parameters that control camera, tracking, monitor, etc. # In this particular case, we add a stream of frames from one example # movie saved in stytra assets. stytra_config = dict(camera=dict(type="spinnaker")) # For a streaming from real cameras connected to the computer, specify camera type, e.g.: # stytra_config = dict(camera=dict(type="ximea")) def get_stim_sequence(self): return [Pause(duration=10)] # protocol does not do anything if __name__ == "__main__": s = Stytra(protocol=Nostim())
# it available for other stimuli: try: self._pyb = getattr(experiment, "_pyb") except AttributeError: experiment._pyb = SerialConnection(com_port=self.com_port, baudrate=self.baudrate) self._pyb = getattr(experiment, "_pyb") def start(self): """ """ self._pyb.write("b") # send blinking command at stimulus start class ArduinoCommProtocol(Protocol): name = "arduino_comm_protocol" # every protocol must have a name. stytra_config = dict(camera=dict(type="ximea"), tracking=dict(method="tail")) def get_stim_sequence(self): # This is the stimuli = [] for i in range(5): stimuli.append(Pause(duration=4)) stimuli.append(ArduinoCommStimulus(duration=0)) return stimuli if __name__ == "__main__": st = Stytra(protocol=ArduinoCommProtocol())
t_base = [0, p, p, p + d, p + d, 2 * p + d] vel_base = [0, 0, -v, -v, 0, 0] t = [0] vel = [0] gain = [0] # Low, medium, high gain: for g in gain_values: t.extend(t[-1] + np.array(t_base)) vel.extend(vel_base) gain.extend([0] * 2 + [g] * 2 + [0] * 2) df = pd.DataFrame(dict(t=t, base_vel=vel, gain=gain)) ClosedLoop1DGratings = type("Stim", (GainLagClosedLoop1D, GratingStimulus), {}) stimuli.append( ClosedLoop1DGratings( df_param=df, grating_angle=np.pi / 2, grating_period=self.grating_cycle, grating_col_1=(255, ) * 3, )) return stimuli if __name__ == "__main__": Stytra(protocol=ImagingCLProtocol())
def get_position(self): if len(self.acc_tracking.stored_data) > 0: last_pos = self.acc_tracking.stored_data[-1] return self._data_type(last_pos.snout_x, last_pos.snout_y) else: return self._data_type(-1, -1) # a stimulus which draws a circle at the position of the snout # there is no transform, since this is a virtual experiment, in reality # one would also use a calibration matrix after obtaining the coordinates class PosTrackingStimulus(CircleStimulus): def update(self): self.x, self.y = self._experiment.estimator.get_position() super().update() class RatProtocol(Protocol): name = "follow the mouse" stytra_config = dict(camera=dict(video_file=video_file), tracking=dict(method=MouseTrackPipeline, estimator=SnoutPositionEstimator)) def get_stim_sequence(self): return [PosTrackingStimulus(duration=120)] if __name__ == "__main__": Stytra(protocol=RatProtocol())
from stytra import Stytra, Protocol from stytra.stimulation.stimuli.visual import Pause, FullFieldVisualStimulus # 1. Define a protocol subclass class FlashProtocol(Protocol): name = "flash_protocol" # every protocol must have a name. def get_stim_sequence(self): # This is the method we need to write to create a new stimulus list. # In this case, the protocol is simply a 1 second flash on the entire screen # after a pause of 4 seconds: stimuli = [ Pause(duration=4.), FullFieldVisualStimulus(duration=1., color=(255, 255, 255)), ] return stimuli if __name__ == "__main__": # This is the line that actually opens stytra with the new protocol. st = Stytra(protocol=FlashProtocol())
Pause(duration=self.params["period_sec"] - self.params["flash_duration"]), FullFieldVisualStimulus(duration=self.params["flash_duration"], color=(255, 255, 255)), ] return stimuli if __name__ == "__main__": # Reading from a file: # This will work only with a file! # TODO provide downloadable example file file = r"J:\_Shared\stytra\fish_tail.h5" camera_config = dict(video_file=file, rotation=1) # Reading from a Ximea camera: # camera_config = dict(type="ximea") tracking_config = dict(embedded=True, tracking_method="angle_sweep", preprocessing_method="prefilter") # We make a new instance of Stytra with this protocol as the only option s = Stytra( protocols=[FlashProtocol], camera_config=camera_config, tracking_config=tracking_config, dir_save=r"D:\vilim\stytra\\", )