class OptogenExperiment: def __init__(self): self.experiment_finished = False self._point = POINT self._start_angle, self._end_angle = ANGLE_WINDOW self._intertrial_timer = Timer(15) self._experiment_timer = Timer(1800) self._event = False self._event_start = None self._results = [] self._max_trial_time = 5 self._min_trial_time = 1 self._max_total_time = 600 self._total_time = 0 self._trial_time = 0 def check_skeleton(self, frame, skeleton): if self._experiment_timer.check_timer(): if self._total_time >= self._max_total_time: # check if total time to stimulate per experiment is reached print("Ending experiment, total event time ran out") self.stop_experiment() else: # if not continue if not self._intertrial_timer.check_timer(): # check if there is an intertrial time running right now, if not continue # check if the headdirection angle is within limits _, angle_point = angle_between_vectors( *skeleton["neck"], *skeleton["nose"], *self._point) if self._start_angle <= angle_point <= self._end_angle: if not self._event: # if a stimulation event wasn't started already, start one print("Starting Stimulation") self._event = True # and activate the laser, start the timer and reset the intertrial timer laser_switch(True) self._event_start = time.time() self._intertrial_timer.reset() else: if time.time( ) - self._event_start <= self._max_trial_time: # if the total event time has not reached the maximum time per event # self._trial_time = time.time() - self._event_start pass else: # if the maximum event time was reached, reset the event, # turn off the laser and start intertrial time print( "Ending Stimulation, Stimulation time ran out" ) self._event = False # laser_toggle(False) laser_switch(False) # self._trial_time = time.time() - self._event_start trial_time = time.time() - self._event_start self._total_time += trial_time self._results.append(trial_time) print("Stimulation duration", trial_time) self._intertrial_timer.start() else: # if the headdirection is not within the parameters if self._event: # but the stimulation is still going if time.time( ) - self._event_start < self._min_trial_time: # check if the minimum event time was not reached, then pass pass else: # if minumum event time has been reached, reset the event, # turn of the laser and start intertrial time print("Ending Stimulation, angle not in range") self._event = False # laser_toggle(False) laser_switch(False) # self._trial_time = time.time() - self._event_start trial_time = time.time() - self._event_start self._total_time += trial_time self._results.append(trial_time) print("Stimulation duration", trial_time) self._intertrial_timer.start() else: # if maximum experiment time was reached, stop experiment print("Ending experiment, timer ran out") self.stop_experiment() return self._event def start_experiment(self): # not necessary as this experiment is not needing any multiprocessing self._experiment_timer.start() def stop_experiment(self): self.experiment_finished = True print("Experiment completed!") print("Total event duration", sum(self._results)) print(self._results) def get_trial(self): return self._event def get_info(self): """ returns optional info""" info = None return info
class SpeedExperiment: """ Simple class to contain all of the experiment properties Uses multiprocess to ensure the best possible performance and to showcase that it is possible to work with any type of equipment, even timer-dependent """ def __init__(self): self.experiment_finished = False self._threshold = 10 self._event = None self._current_trial = None self._event_count = 0 self._trigger = SpeedTrigger(threshold=self._threshold, bodypart="tailroot", timewindow_len=5) self._exp_timer = Timer(600) def check_skeleton(self, frame, skeleton): """ Checking each passed animal skeleton for a pre-defined set of conditions Outputting the visual representation, if exist Advancing trials according to inherent logic of an experiment :param frame: frame, on which animal skeleton was found :param skeleton: skeleton, consisting of multiple joints of an animal """ self.check_exp_timer() # checking if experiment is still on if not self.experiment_finished: result, response = self._trigger.check_skeleton(skeleton=skeleton) plot_triggers_response(frame, response) if result: laser_switch(True) self._event_count += 1 print(self._event_count) print("Light on") else: laser_switch(False) print("Light off") return result, response def check_exp_timer(self): """ Checking the experiment timer """ if not self._exp_timer.check_timer(): print("Experiment is finished") print("Time ran out.") self.stop_experiment() def start_experiment(self): """ Start the experiment """ if not self.experiment_finished: self._exp_timer.start() def stop_experiment(self): """ Stop the experiment and reset the timer """ self.experiment_finished = True print("Experiment completed!") self._exp_timer.reset() # don't forget to stop the laser for safety! laser_switch(False) def get_trial(self): """ Check which trial is going on right now """ return self._current_trial
class ExampleExperiment: """ Simple class to contain all of the experiment properties Uses multiprocess to ensure the best possible performance and to showcase that it is possible to work with any type of equipment, even timer-dependent """ def __init__(self): self.experiment_finished = False self._process = ExampleProtocolProcess() self._green_point = (550, 163) self._blue_point = (372, 163) self._radius = 40 self._event = None self._current_trial = None self._trial_count = {trial: 0 for trial in self._trials} self._trial_timers = {trial: Timer(10) for trial in self._trials} self._exp_timer = Timer(600) def check_skeleton(self, frame, skeleton): """ Checking each passed animal skeleton for a pre-defined set of conditions Outputting the visual representation, if exist Advancing trials according to inherent logic of an experiment :param frame: frame, on which animal skeleton was found :param skeleton: skeleton, consisting of multiple joints of an animal """ self.check_exp_timer() # checking if experiment is still on for trial in self._trial_count: # checking if any trial hit a predefined cap if self._trial_count[trial] >= 10: self.stop_experiment() if not self.experiment_finished: result, response = False, None for trial in self._trials: # check for all trials if condition is met result, response = self._trials[trial]["trigger"]( skeleton=skeleton) plot_triggers_response(frame, response) if result: if self._current_trial is None: if not self._trial_timers[trial].check_timer(): self._current_trial = trial self._trial_timers[trial].reset() self._trial_count[trial] += 1 print(trial, self._trial_count[trial]) else: if self._current_trial == trial: self._current_trial = None self._trial_timers[trial].start() self._process.set_trial(self._current_trial) return result, response @property def _trials(self): """ Defining the trials """ green_roi = RegionTrigger("circle", self._green_point, self._radius * 2 + 7.5, "neck") blue_roi = RegionTrigger("circle", self._blue_point, self._radius * 2 + 7.5, "neck") trials = { "Greenbar_whiteback": dict(trigger=green_roi.check_skeleton, count=0), "Bluebar_whiteback": dict(trigger=blue_roi.check_skeleton, count=0), } return trials def check_exp_timer(self): """ Checking the experiment timer """ if not self._exp_timer.check_timer(): print("Experiment is finished") print("Time ran out.") self.stop_experiment() def start_experiment(self): """ Start the experiment """ self._process.start() if not self.experiment_finished: self._exp_timer.start() def stop_experiment(self): """ Stop the experiment and reset the timer """ self.experiment_finished = True print("Experiment completed!") self._exp_timer.reset() # don't forget to end the process! self._process.end() def get_trial(self): """ Check which trial is going on right now """ return self._current_trial
class ExampleSocialInteractionExperiment: """ In this experiment the skeleton/instance of each animal will be considers for the trigger, any animal can trigger the stimulation (the first one to result in TRUE). Simple class to contain all of the experiment properties Uses multiprocess to ensure the best possible performance and to showcase that it is possible to work with any type of equipment, even timer-dependent """ def __init__(self): self.experiment_finished = False self._process = ExampleProtocolProcess() self._proximity_threshold = 30 self._min_animals = 2 self._event = None self._current_trial = None self._max_reps = 999 self._trial_count = {trial: 0 for trial in self._trials} self._trial_timers = {trial: Timer(10) for trial in self._trials} self._exp_timer = Timer(600) def check_skeleton(self, frame, skeletons): """ Checking passed animal skeletons for a pre-defined set of conditions Outputting the visual representation, if exist Advancing trials according to inherent logic of an experiment :param frame: frame, on which animal skeleton was found :param skeletons: skeletons, consisting of multiple joints of an animal """ self.check_exp_timer() # checking if experiment is still on for trial in self._trial_count: # checking if any trial hit a predefined cap if self._trial_count[trial] >= self._max_reps: self.stop_experiment() if not self.experiment_finished: result, response = False, None # checking if enough animals were detected if len(skeletons) >= self._min_animals: for trial in self._trials: # check if social interaction trigger is true result, response = self._trials[trial]["trigger"]( skeletons=skeletons) plot_triggers_response(frame, response) if result: if self._current_trial is None: if not self._trial_timers[trial].check_timer(): self._current_trial = trial self._trial_timers[trial].reset() self._trial_count[trial] += 1 print(trial, self._trial_count[trial]) else: if self._current_trial == trial: self._current_trial = None self._trial_timers[trial].start() self._process.set_trial(self._current_trial) else: pass return result, response @property def _trials(self): """ Defining the trials """ identification_dict = dict(active={ "animal": 1, "bp": ["bp0"] }, passive={ "animal": 0, "bp": ["bp2"] }) interaction_trigger = SocialInteractionTrigger( threshold=self._proximity_threshold, identification_dict=identification_dict, interaction_type="proximity", debug=True, ) trials = { "DLStream_test": dict(trigger=interaction_trigger.check_skeleton, count=0) } return trials def check_exp_timer(self): """ Checking the experiment timer """ if not self._exp_timer.check_timer(): print("Experiment is finished") print("Time ran out.") self.stop_experiment() def start_experiment(self): """ Start the experiment """ self._process.start() if not self.experiment_finished: self._exp_timer.start() def stop_experiment(self): """ Stop the experiment and reset the timer """ self.experiment_finished = True print("Experiment completed!") self._exp_timer.reset() # don't forget to end the process! self._process.end() def get_trial(self): """ Check which trial is going on right now """ return self._current_trial
class ExampleMultipleAnimalExperiment: """ In this experiment the skeleton/instance of each animal will be considers for the trigger, any animal can trigger the stimulation (the first one to result in TRUE). Simple class to contain all of the experiment properties Uses multiprocess to ensure the best possible performance and to showcase that it is possible to work with any type of equipment, even timer-dependent """ def __init__(self): self.experiment_finished = False self._process = ExampleProtocolProcess() self._green_point = (550, 163) self._radius = 40 self._dist_threshold = 80 self._event = None self._current_trial = None self._max_reps = 10 self._trial_count = {trial: 0 for trial in self._trials} self._trial_timers = {trial: Timer(10) for trial in self._trials} self._exp_timer = Timer(600) def check_skeleton(self, frame, skeletons): """ Checking each passed animal skeleton for a pre-defined set of conditions Outputting the visual representation, if exist Advancing trials according to inherent logic of an experiment :param frame: frame, on which animal skeleton was found :param skeletons: skeletons, consisting of multiple joints of an animal """ self.check_exp_timer() # checking if experiment is still on for trial in self._trial_count: # checking if any trial hit a predefined cap if self._trial_count[trial] >= self._max_reps: self.stop_experiment() if not self.experiment_finished: result, response = False, None for trial in self._trials: # check for all trials if condition is met result_list = [] for skeleton in skeletons: # checking each skeleton for trigger success result, response = self._trials[trial]['trigger']( skeleton=skeleton) # if one of the triggers is true, break the loop and continue (the first True) if result: break plot_triggers_response(frame, response) if result: if self._current_trial is None: if not self._trial_timers[trial].check_timer(): self._current_trial = trial self._trial_timers[trial].reset() self._trial_count[trial] += 1 print(trial, self._trial_count[trial]) else: if self._current_trial == trial: self._current_trial = None self._trial_timers[trial].start() self._process.set_trial(self._current_trial) return result, response @property def _trials(self): """ Defining the trials """ green_roi = RegionTrigger('circle', self._green_point, self._radius * 2 + 7.5, 'bp1') trials = { 'Greenbar_whiteback': dict(trigger=green_roi.check_skeleton, count=0) } return trials def check_exp_timer(self): """ Checking the experiment timer """ if not self._exp_timer.check_timer(): print("Experiment is finished") print("Time ran out.") self.stop_experiment() def start_experiment(self): """ Start the experiment """ self._process.start() if not self.experiment_finished: self._exp_timer.start() def stop_experiment(self): """ Stop the experiment and reset the timer """ self.experiment_finished = True print('Experiment completed!') self._exp_timer.reset() # don't forget to end the process! self._process.end() def get_trial(self): """ Check which trial is going on right now """ return self._current_trial