Skip to content

Commit 4ddb208

Browse files
committed
updated BaseOptogeneticExperiment
and config and design_experiment included Example configs for major experiment types
1 parent f34587a commit 4ddb208

File tree

7 files changed

+167
-147
lines changed

7 files changed

+167
-147
lines changed

design_experiment.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ def design_experiment():
99
TRIGGER = None,
1010
PROCESS = None,
1111
STIMULATION = None)
12+
available_process_types = ['switch', 'supply']
1213

1314
for input_type in input_dict.keys():
15+
if input_dict['EXPERIMENT'] == 'BaseOptogeneticExperiment' and input_type == 'STIMULATION':
16+
input_dict[input_type] = 'BaseStimulation'
17+
1418
click.echo(f'Available {input_type}s are: ' + ', '.join(config.get_available_module_names(input_type)))
1519
input_value = click.prompt(f'Enter a base {input_type} module', type=str)
1620

@@ -21,7 +25,65 @@ def design_experiment():
2125
input_dict[input_type] = input_value
2226
click.echo(f'{input_type} set to {input_value}.')
2327

24-
config.import_default(experiment_name= input_dict['EXPERIMENT'], trigger_name= input_dict['TRIGGER'], process_name= input_dict['PROCESS'],stimulation_name= input_dict['STIMULATION'])
28+
if input_dict['EXPERIMENT'] == 'BaseTrialExperiment':
29+
valid_input = False
30+
click.echo(f'Available Triggers are: ' + ', '.join(config.get_available_module_names('TRIGGER')))
31+
click.echo('Note, that you cannot select the same Trigger as selected in TRIGGER.')
32+
33+
input_value = click.prompt(f'Enter TRIAL_TRIGGER for BaseTrialExperiment', type=str)
34+
while not config.check_if_default_exists(input_value, 'TRIGGER'):
35+
click.echo(f'TRIGGER {input_value} does not exists.')
36+
input_value = click.prompt(f'Enter a base TRIGGER module', type=str)
37+
38+
input_dict['TRIAL_TRIGGER'] = input_value
39+
click.echo(f'TRIAL_TRIGGER for BaseTrialExperiment set to {input_value}.')
40+
41+
42+
# TODO: Make adaptive for multiple Triggers
43+
if input_dict['EXPERIMENT'] == 'BaseTrialExperiment':
44+
config.import_default(experiment_name=input_dict['EXPERIMENT'], trigger_name=input_dict['TRIGGER'],
45+
process_name=input_dict['PROCESS'], stimulation_name=input_dict['STIMULATION'],
46+
trial_trigger_name=input_dict['TRIAL_TRIGGER'])
47+
48+
config._change_parameter(module_name=input_dict['EXPERIMENT'], parameter_name='TRIAL_TRIGGER',
49+
parameter_value=input_dict['TRIAL_TRIGGER'])
50+
51+
if input_dict['PROCESS'] == 'BaseProtocolProcess':
52+
config._change_parameter(module_name=input_dict['PROCESS'], parameter_name='TYPE',
53+
parameter_value='trial')
54+
55+
if input_dict['EXPERIMENT'] == 'BaseOptogeneticExperiment':
56+
config.import_default(experiment_name=input_dict['EXPERIMENT'], trigger_name=input_dict['TRIGGER'],
57+
process_name=input_dict['PROCESS'], stimulation_name=input_dict['STIMULATION'])
58+
59+
if input_dict['PROCESS'] == 'BaseProtocolProcess':
60+
config._change_parameter(module_name=input_dict['PROCESS'], parameter_name='TYPE',
61+
parameter_value='switch')
62+
63+
64+
else:
65+
config.import_default(experiment_name=input_dict['EXPERIMENT'], trigger_name=input_dict['TRIGGER'],
66+
process_name=input_dict['PROCESS'], stimulation_name=input_dict['STIMULATION'])
67+
68+
if input_dict['PROCESS'] == 'BaseProtocolProcess' and input_dict['EXPERIMENT'] != 'BaseTrialExperiment' and\
69+
input_dict['EXPERIMENT'] != 'BaseOptogeneticExperiment':
70+
valid_input = False
71+
72+
click.echo(f'Available types are: ' + ', '.join(available_process_types))
73+
input_value = click.prompt(f'Enter a type for BaseProtocolProcess', type=str)
74+
if input_value in available_process_types:
75+
valid_input = True
76+
while not valid_input:
77+
click.echo(f'{input_type} {input_value} does not exists.')
78+
input_value = click.prompt(f'Enter a valid type for BaseProtocolProcess', type=str)
79+
if input_value in available_process_types:
80+
valid_input = True
81+
82+
input_dict['PROCESS_TYPE'] = input_value
83+
click.echo(f'BaseProtocolProcess type set to {input_value}.')
84+
config._change_parameter(module_name = input_dict['PROCESS'], parameter_name = 'TYPE',
85+
parameter_value = input_dict['PROCESS_TYPE'])
86+
2587

2688
#Name of experimentor
2789
experimenter = click.prompt('Enter an experimenter name', type = str)

experiments/base/experiments.py

Lines changed: 7 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -77,113 +77,6 @@ def get_name(self):
7777
return self._name
7878

7979

80-
81-
82-
83-
84-
class BaseExampleExperiment(BaseExperiment):
85-
"""
86-
Simple class to contain all of the experiment properties
87-
Uses multiprocess to ensure the best possible performance and
88-
to showcase that it is possible to work with any type of equipment, even timer-dependent
89-
"""
90-
def __init__(self):
91-
super().__init__()
92-
self._name = 'BaseExampleExperiment'
93-
self._parameter_dict = dict(TRIGGER = 'str',
94-
PROCESS = 'str',
95-
INTERTRIAL_TIME = 'int',
96-
TRIAL_TIME = 'int',
97-
EXP_LENGTH = 'int',
98-
EXP_COMPLETION = 'int',
99-
EXP_TIME = 'int')
100-
self._settings_dict = get_experiment_settings(self._name, self._parameter_dict)
101-
self.experiment_finished = False
102-
self._process = setup_process(self._settings_dict['PROCESS'])
103-
self._event = None
104-
self._current_trial = None
105-
self._trial_count = {trial: 0 for trial in self._trials}
106-
self._trial_timers = {trial: Timer(self._settings_dict['TRIAL_TIME']) for trial in self._trials}
107-
self._exp_timer = Timer(self._settings_dict['EXP_TIME'])
108-
109-
def check_skeleton(self, frame, skeleton):
110-
"""
111-
Checking each passed animal skeleton for a pre-defined set of conditions
112-
Outputting the visual representation, if exist
113-
Advancing trials according to inherent logic of an experiment
114-
:param frame: frame, on which animal skeleton was found
115-
:param skeleton: skeleton, consisting of multiple joints of an animal
116-
"""
117-
self.check_exp_timer() # checking if experiment is still on
118-
for trial in self._trial_count:
119-
# checking if any trial hit a predefined cap
120-
if self._trial_count[trial] >= 10:
121-
self.stop_experiment()
122-
123-
if not self.experiment_finished:
124-
result, response = False, None
125-
for trial in self._trials:
126-
# check for all trials if condition is met
127-
result, response = self._trials[trial]['trigger'](skeleton=skeleton)
128-
plot_triggers_response(frame, response)
129-
if result:
130-
if self._current_trial is None:
131-
if not self._trial_timers[trial].check_timer():
132-
self._current_trial = trial
133-
self._trial_timers[trial].reset()
134-
self._trial_count[trial] += 1
135-
print(trial, self._trial_count[trial])
136-
else:
137-
if self._current_trial == trial:
138-
self._current_trial = None
139-
self._trial_timers[trial].start()
140-
141-
self._process.put(self._current_trial)
142-
143-
@property
144-
def _trials(self):
145-
"""
146-
Defining the trials
147-
"""
148-
trigger = setup_trigger(self._settings_dict['TRIGGER'])
149-
trials = {'Greenbar_whiteback': dict(trigger=trigger.check_skeleton,
150-
count=0)}
151-
return trials
152-
153-
def check_exp_timer(self):
154-
"""
155-
Checking the experiment timer
156-
"""
157-
if not self._exp_timer.check_timer():
158-
print("Experiment is finished")
159-
print("Time ran out.")
160-
self.stop_experiment()
161-
162-
def start_experiment(self):
163-
"""
164-
Start the experiment
165-
"""
166-
self._process.start()
167-
if not self.experiment_finished:
168-
self._exp_timer.start()
169-
170-
def stop_experiment(self):
171-
"""
172-
Stop the experiment and reset the timer
173-
"""
174-
self.experiment_finished = True
175-
print('Experiment completed!')
176-
self._exp_timer.reset()
177-
# don't forget to end the process!
178-
self._process.end()
179-
180-
def get_trial(self):
181-
"""
182-
Check which trial is going on right now
183-
"""
184-
return self._current_trial
185-
186-
18780
class BaseTrialExperiment(BaseExperiment):
18881
def __init__(self):
18982
super().__init__()
@@ -215,7 +108,6 @@ def __init__(self):
215108
self._exp_timer = Timer(self._settings_dict['EXP_TIME'])
216109
self._intertrial_timer = Timer(self._settings_dict['INTERTRIAL_TIME'])
217110

218-
219111
def check_skeleton(self, frame, skeleton):
220112
status, trial = self._process.get_status()
221113
if status:
@@ -404,9 +296,10 @@ def __init__(self):
404296
MAX_TOTAL_STIM_TIME = 'int',
405297
EXP_LENGTH = 'int',
406298
EXP_COMPLETION = 'int',
407-
EXP_TIME = 'int')
299+
EXP_TIME = 'int',
300+
PROCESS = 'str')
408301
self._settings_dict = get_experiment_settings(self._name, self._exp_parameter_dict)
409-
302+
self._process = setup_process(self._settings_dict['PROCESS'])
410303
self._intertrial_timer = Timer(self._settings_dict['INTERTRIAL_TIME'])
411304
self._exp_timer = Timer(self._settings_dict['EXP_TIME'])
412305
self._event = False
@@ -425,10 +318,6 @@ def __init__(self):
425318
#trigger
426319
self._trigger = setup_trigger(self._settings_dict['TRIGGER'])
427320

428-
#Stimulation
429-
self._stimulus = BaseStimulation()
430-
431-
432321
def check_skeleton(self, frame, skeleton):
433322

434323
if self._exp_timer.check_timer():
@@ -441,14 +330,13 @@ def check_skeleton(self, frame, skeleton):
441330
if not self._intertrial_timer.check_timer():
442331
# check if there is an intertrial time running right now, if not continue
443332
# check if the trigger is true
444-
trigger_result, _ = self._trigger.check_skeleton(skeleton)
445-
if trigger_result:
333+
result, _ = self._trigger.check_skeleton(skeleton)
334+
if result:
446335
if not self._event:
447336
# if a stimulation event wasn't started already, start one
448337
print("Starting Stimulation")
449338
self._event = True
450339
# and activate the laser, start the timer and reset the intertrial timer
451-
self._stimulus.start()
452340
self._event_start = time.time()
453341
self._intertrial_timer.reset()
454342
else:
@@ -460,7 +348,6 @@ def check_skeleton(self, frame, skeleton):
460348
# turn off the laser and start inter-trial time
461349
print("Ending Stimulation, Stimulation time ran out")
462350
self._event = False
463-
self._stimulus.stop()
464351
trial_time = time.time() - self._event_start
465352
self._total_time += trial_time
466353
self._results.append(trial_time)
@@ -478,20 +365,19 @@ def check_skeleton(self, frame, skeleton):
478365
# turn of the laser and start intertrial time
479366
print("Ending Stimulation, Trigger is False")
480367
self._event = False
481-
self._stimulus.stop()
482368
trial_time = time.time() - self._event_start
483369
self._total_time += trial_time
484370
self._results.append(trial_time)
485371
print("Stimulation duration", trial_time)
486372
self._intertrial_timer.start()
373+
self._process.put(self._event)
374+
487375

488376
else:
489377
# if maximum experiment time was reached, stop experiment
490378
print("Ending experiment, timer ran out")
491379
self.stop_experiment()
492380

493-
return self._event
494-
495381
def start_experiment(self):
496382
self._exp_timer.start()
497383

experiments/configs/example_config.ini renamed to experiments/configs/BaseConditionalExperiment_example.ini

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
[EXPERIMENT]
22
BASE = BaseConditionalExperiment
3-
EXPERIMENTER = DEFAULT
3+
EXPERIMENTER = Example
44

55
[BaseConditionalExperiment]
6-
TRIGGER = BaseHeaddirectionTrigger
6+
TRIGGER = BaseRegionTrigger
77
PROCESS = BaseProtocolProcess
88
INTERTRIAL_TIME = 40
99
EXP_LENGTH = 40
1010
EXP_TIME = 3600
1111
EXP_COMPLETION = 10
1212

13-
[BaseHeaddirectionTrigger]
14-
POINT = 550, 63
15-
ANLGE = 30
13+
[BaseRegionTrigger]
14+
TYPE = circle
15+
CENTER = 550, 63
16+
RADIUS = 30
1617
BODYPARTS = neck
1718
DEBUG = False
1819

1920
[BaseProtocolProcess]
2021
TYPE = switch
21-
STIMULATION = ScreenStimulation
22+
STIMULATION = BaseStimulation
23+
24+
[BaseStimulation]
25+
TYPE = NI
26+
PORT = Dev1/PFI6
27+
STIM_TIME = 3.5
2228

23-
[ScreenStimulation]
24-
TYPE = image
25-
STIM_PATH = PATH_TO_IMAGE
26-
BACKGROUND_PATH = PATH_TO_BACKGROUND
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[EXPERIMENT]
2+
BASE = BaseOptogeneticExperiment
3+
EXPERIMENTER = Example
4+
5+
[BaseOptogeneticExperiment]
6+
TRIGGER = BaseRegionTrigger
7+
INTERTRIAL_TIME = 40
8+
MAX_STIM_TIME = 10
9+
MIN_STIM_TIME = 3
10+
MAX_TOTAL_STIM_TIME = 500
11+
EXP_LENGTH = 40
12+
EXP_TIME = 3600
13+
EXP_COMPLETION = 10
14+
PROCESS = BaseProtocolProcess
15+
16+
[BaseRegionTrigger]
17+
TYPE = circle
18+
CENTER = 550, 63
19+
RADIUS = 30
20+
BODYPARTS = neck
21+
DEBUG = False
22+
23+
[BaseProtocolProcess]
24+
TYPE = switch
25+
STIMULATION = BaseStimulation
26+
27+
[BaseStimulation]
28+
TYPE = NI
29+
PORT = Dev1/PFI6
30+
STIM_TIME = 3.5
31+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[EXPERIMENT]
2+
BASE = BaseTrialExperiment
3+
EXPERIMENTER = Example
4+
5+
[BaseTrialExperiment]
6+
TRIGGER = BaseScreenTrigger
7+
PROCESS = BaseProtocolProcess
8+
INTERTRIAL_TIME = 40
9+
TRIAL_NAME = Trial
10+
TRIAL_TRIGGER = BaseRegionTrigger
11+
TRIAL_TIME = 10
12+
STIMULUS_TIME = 10
13+
RESULT_FUNC = any
14+
EXP_LENGTH = 40
15+
EXP_COMPLETION = 20
16+
EXP_TIME = 6000
17+
18+
[BaseScreenTrigger]
19+
ANGLE = 60
20+
DIRECTION = North
21+
BODYPARTS = nose, neck
22+
DEBUG = False
23+
24+
[BaseProtocolProcess]
25+
TYPE = trial
26+
STIMULATION = ScreenStimulation
27+
28+
[ScreenStimulation]
29+
TYPE = image
30+
STIM_PATH = PATH_TO_IMAGE
31+
BACKGROUND_PATH = PATH_TO_BACKGROUND
32+
33+
[BaseRegionTrigger]
34+
TYPE = circle
35+
CENTER = 550, 63
36+
RADIUS = 30
37+
BODYPARTS = neck
38+
DEBUG = False
39+

0 commit comments

Comments
 (0)