1010import time
1111from functools import partial
1212from collections import Counter
13- from experiments .custom .stimulus_process import ClassicProtocolProcess , SimpleProtocolProcess ,Timer , ExampleProtocolProcess
14- from experiments .custom .triggers import ScreenTrigger , RegionTrigger , OutsideTrigger , DirectionTrigger , SpeedTrigger
13+ from experiments .custom .stimulus_process import ClassicProtocolProcess , SimpleProtocolProcess ,Timer \
14+ , ExampleProtocolProcess
15+ from experiments .custom .triggers import ScreenTrigger , RegionTrigger , OutsideTrigger , DirectionTrigger \
16+ , SpeedTrigger , SocialInteractionTrigger
1517from utils .plotter import plot_triggers_response
1618from utils .analysis import angle_between_vectors
1719from experiments .custom .stimulation import show_visual_stim_img ,laser_switch
1820
1921
20- class ExampleSocialExperiment :
22+ """Social or multiple animal experiments in combination with SLEAP or non-flattened maDLC pose estimation"""
23+
24+ class ExampleSocialInteractionExperiment :
2125 """
26+ In this experiment the skeleton/instance of each animal will be considers for the trigger,
27+ any animal can trigger the stimulation (the first one to result in TRUE).
28+
2229 Simple class to contain all of the experiment properties
2330 Uses multiprocess to ensure the best possible performance and
2431 to showcase that it is possible to work with any type of equipment, even timer-dependent
2532 """
2633 def __init__ (self ):
2734 self .experiment_finished = False
2835 self ._process = ExampleProtocolProcess ()
29- self ._green_point = ( 313 , 552 )
30- self ._radius = 80
36+ self ._proximity_threshold = 30
37+ self ._min_animals = 2
3138 self ._event = None
3239 self ._current_trial = None
40+ self ._max_reps = 999
3341 self ._trial_count = {trial : 0 for trial in self ._trials }
3442 self ._trial_timers = {trial : Timer (10 ) for trial in self ._trials }
3543 self ._exp_timer = Timer (600 )
3644
3745 def check_skeleton (self , frame , skeletons ):
3846 """
39- Checking each passed animal skeleton for a pre-defined set of conditions
47+ Checking passed animal skeletons for a pre-defined set of conditions
4048 Outputting the visual representation, if exist
4149 Advancing trials according to inherent logic of an experiment
4250 :param frame: frame, on which animal skeleton was found
@@ -45,40 +53,161 @@ def check_skeleton(self, frame, skeletons):
4553 self .check_exp_timer () # checking if experiment is still on
4654 for trial in self ._trial_count :
4755 # checking if any trial hit a predefined cap
48- if self ._trial_count [trial ] >= 10 :
56+ if self ._trial_count [trial ] >= self . _max_reps :
4957 self .stop_experiment ()
5058
5159 if not self .experiment_finished :
5260 result , response = False , None
61+ #checking if enough animals were detected
62+ if len (skeletons ) >= self ._min_animals :
63+ for trial in self ._trials :
64+ # check if social interaction trigger is true
65+ result , response = self ._trials [trial ]['trigger' ](skeletons = skeletons )
66+ plot_triggers_response (frame , response )
67+ if result :
68+ if self ._current_trial is None :
69+ if not self ._trial_timers [trial ].check_timer ():
70+ self ._current_trial = trial
71+ self ._trial_timers [trial ].reset ()
72+ self ._trial_count [trial ] += 1
73+ print (trial , self ._trial_count [trial ])
74+ else :
75+ if self ._current_trial == trial :
76+ self ._current_trial = None
77+ self ._trial_timers [trial ].start ()
78+
79+ self ._process .set_trial (self ._current_trial )
80+ else :
81+ pass
82+ return result , response
83+
84+ @property
85+ def _trials (self ):
86+ """
87+ Defining the trials
88+ """
89+ identification_dict = dict (active = {'animal' : 1
90+ , 'bp' : ['bp0' ]
91+ }
92+ ,passive = {'animal' : 0
93+ , 'bp' : ['bp2' ]
94+ }
95+ )
96+
97+ interaction_trigger = SocialInteractionTrigger (threshold = self ._proximity_threshold
98+ , identification_dict = identification_dict
99+ , interaction_type = 'proximity'
100+ , debug = True
101+ )
102+
103+ trials = {'DLStream_test' : dict (trigger = interaction_trigger .check_skeleton ,
104+ count = 0 )}
105+ return trials
106+
107+ def check_exp_timer (self ):
108+ """
109+ Checking the experiment timer
110+ """
111+ if not self ._exp_timer .check_timer ():
112+ print ("Experiment is finished" )
113+ print ("Time ran out." )
114+ self .stop_experiment ()
115+
116+ def start_experiment (self ):
117+ """
118+ Start the experiment
119+ """
120+ self ._process .start ()
121+ if not self .experiment_finished :
122+ self ._exp_timer .start ()
123+
124+ def stop_experiment (self ):
125+ """
126+ Stop the experiment and reset the timer
127+ """
128+ self .experiment_finished = True
129+ print ('Experiment completed!' )
130+ self ._exp_timer .reset ()
131+ # don't forget to end the process!
132+ self ._process .end ()
133+
134+ def get_trial (self ):
135+ """
136+ Check which trial is going on right now
137+ """
138+ return self ._current_trial
139+
140+
141+ class ExampleMultipleAnimalExperiment :
142+ """
143+ In this experiment the skeleton/instance of each animal will be considers for the trigger,
144+ any animal can trigger the stimulation (the first one to result in TRUE).
145+
146+ Simple class to contain all of the experiment properties
147+ Uses multiprocess to ensure the best possible performance and
148+ to showcase that it is possible to work with any type of equipment, even timer-dependent
149+ """
150+
151+ def __init__ (self ):
152+ self .experiment_finished = False
153+ self ._process = ExampleProtocolProcess ()
154+ self ._green_point = (550 , 163 )
155+ self ._radius = 40
156+ self ._dist_threshold = 80
157+ self ._event = None
158+ self ._current_trial = None
159+ self ._max_reps = 10
160+ self ._trial_count = {trial : 0 for trial in self ._trials }
161+ self ._trial_timers = {trial : Timer (10 ) for trial in self ._trials }
162+ self ._exp_timer = Timer (600 )
163+
164+ def check_skeleton (self ,frame ,skeletons ):
165+ """
166+ Checking each passed animal skeleton for a pre-defined set of conditions
167+ Outputting the visual representation, if exist
168+ Advancing trials according to inherent logic of an experiment
169+ :param frame: frame, on which animal skeleton was found
170+ :param skeletons: skeletons, consisting of multiple joints of an animal
171+ """
172+ self .check_exp_timer () # checking if experiment is still on
173+ for trial in self ._trial_count :
174+ # checking if any trial hit a predefined cap
175+ if self ._trial_count [trial ] >= self ._max_reps :
176+ self .stop_experiment ()
177+
178+ if not self .experiment_finished :
179+ result ,response = False ,None
53180 for trial in self ._trials :
54181 # check for all trials if condition is met
55182 result_list = []
56183 for skeleton in skeletons :
57- result , response = self ._trials [trial ]['trigger' ](skeleton = skeleton )
184+ # checking each skeleton for trigger success
185+ result ,response = self ._trials [trial ]['trigger' ](skeleton = skeleton )
186+ # if one of the triggers is true, break the loop and continue (the first True)
58187 if result :
59188 break
60- plot_triggers_response (frame , response )
189+ plot_triggers_response (frame ,response )
61190 if result :
62191 if self ._current_trial is None :
63192 if not self ._trial_timers [trial ].check_timer ():
64193 self ._current_trial = trial
65194 self ._trial_timers [trial ].reset ()
66195 self ._trial_count [trial ] += 1
67- print (trial , self ._trial_count [trial ])
196+ print (trial ,self ._trial_count [trial ])
68197 else :
69198 if self ._current_trial == trial :
70199 self ._current_trial = None
71200 self ._trial_timers [trial ].start ()
72201
73202 self ._process .set_trial (self ._current_trial )
74- return result , response
203+ return result ,response
75204
76205 @property
77206 def _trials (self ):
78207 """
79208 Defining the trials
80209 """
81- green_roi = RegionTrigger ('circle' , self ._green_point , self ._radius * 2 + 7.5 , 'bp1' )
210+ green_roi = RegionTrigger ('circle' ,self ._green_point ,self ._radius * 2 + 7.5 ,'bp1' )
82211 trials = {'Greenbar_whiteback' : dict (trigger = green_roi .check_skeleton ,
83212 count = 0 )}
84213 return trials
@@ -117,6 +246,10 @@ def get_trial(self):
117246 return self ._current_trial
118247
119248
249+ """Single animal or flattened multi animal pose estimation experiments (e.g. different fur color)
250+ or by use of the FLATTEN_MA parameter in advanced settings"""
251+
252+
120253class ExampleExperiment :
121254 """
122255 Simple class to contain all of the experiment properties
0 commit comments