Skip to content

Commit 54d7eac

Browse files
committed
store trial data to disk
1 parent c6e18d9 commit 54d7eac

File tree

1 file changed

+47
-13
lines changed
  • iblrig_custom_tasks/samuel_tonotopicMapping

1 file changed

+47
-13
lines changed

iblrig_custom_tasks/samuel_tonotopicMapping/task.py

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,38 @@
11
import logging
2+
import time
23

34
import numpy as np
45
import pandas as pd
56

67
from iblrig import sound
8+
from iblrig.base_choice_world import NTRIALS_INIT
79
from iblrig.base_tasks import BaseSession, BpodMixin
810
from iblrig.misc import get_task_arguments
911
from pybpodapi.state_machine import StateMachine
1012

11-
logger = logging.getLogger('iblrig')
13+
from iblrig.pydantic_definitions import TrialDataModel
14+
15+
log = logging.getLogger('iblrig')
16+
17+
18+
class TonotopicMappingTrialData(TrialDataModel):
19+
"""Pydantic Model for Trial Data."""
20+
21+
frequency_sequence: list[int]
22+
1223

1324

1425
class Session(BpodMixin, BaseSession):
1526
protocol_name = 'samuel_tonotopicMapping'
27+
TrialDataModel = TonotopicMappingTrialData
1628

1729
frequencies: list[int] = []
1830
sequence: list[int] = []
31+
trial_num: int = -1
1932

2033
def __init__(self, *args, **kwargs):
2134
super().__init__(*args, **kwargs)
35+
self.trials_table = self.TrialDataModel.preallocate_dataframe(NTRIALS_INIT)
2236

2337
assert self.hardware_settings.device_sound.OUTPUT == 'harp', 'This task requires a Harp sound-card'
2438
assert self.task_params['n_freqs'] <= 30, 'Harp only supports up to 30 individual sounds'
@@ -76,11 +90,11 @@ def n_frequencies(self):
7690
return len(self.frequencies)
7791

7892
@property
79-
def n_state_machines(self):
93+
def n_trials(self):
8094
return len(self.repetitions)
8195

8296
def start_mixin_sound(self):
83-
logger.info(f'Pushing {len(self.frequencies)} stimuli to Harp soundcard')
97+
log.info(f'Pushing {len(self.frequencies)} stimuli to Harp soundcard')
8498
sound.configure_sound_card(sounds=self.stimuli, indexes=self.indices, sample_rate=self.task_params['fs'])
8599

86100
module = self.bpod.sound_card
@@ -110,13 +124,13 @@ def softcode_handler(softcode: int) -> None:
110124
frequency_index = Session.sequence[state_index]
111125
frequency = Session.frequencies[frequency_index]
112126
n_states = len(Session.sequence)
113-
logger.info(f'- {state_index + 1:03d}/{n_states}: {frequency:5d} Hz')
127+
log.info(f'- {state_index + 1:03d}/{n_states}: {frequency:5d} Hz')
114128

115-
def get_state_machine(self, sma_idx: int) -> StateMachine:
116-
# generate sequence, optionally shuffled (seeded with state machine number)
117-
Session.sequence = np.repeat(np.arange(len(self.frequencies)), self.repetitions[sma_idx])
129+
def get_state_machine(self, trial_number: int) -> StateMachine:
130+
# generate sequence, optionally shuffled (seeded with trial number)
131+
Session.sequence = np.repeat(np.arange(len(self.frequencies)), self.repetitions[trial_number])
118132
if self.task_params['shuffle']:
119-
np.random.seed(sma_idx)
133+
np.random.seed(trial_number)
120134
np.random.shuffle(Session.sequence)
121135

122136
# build state machine
@@ -131,15 +145,35 @@ def get_state_machine(self, sma_idx: int) -> StateMachine:
131145
return sma
132146

133147
def _run(self):
134-
logger.info('Sending spacers to BNC ports')
148+
log.info('Sending spacers to BNC ports')
135149
self.send_spacers()
136150

137-
for sma_idx in range(self.n_state_machines):
138-
logger.info(f'State Machine {sma_idx + 1}/{self.n_state_machines}')
139-
sma = self.get_state_machine(sma_idx)
151+
for trial_number in range(self.n_trials):
152+
self.trial_num = trial_number
153+
154+
# run state machine
155+
log.info(f'Starting Trial #{trial_number} ({trial_number + 1}/{self.n_trials})')
156+
sma = self.get_state_machine(trial_number)
140157
self.bpod.send_state_machine(sma)
141158
self.bpod.run_state_machine(sma)
142-
self.bpod.session.current_trial.export()
159+
160+
# handle pause event
161+
if self.paused and trial_number < (self.task_params.NTRIALS - 1):
162+
log.info(f'Pausing session inbetween trials #{trial_number} and #{trial_number + 1}')
163+
while self.paused and not self.stopped:
164+
time.sleep(1)
165+
if not self.stopped:
166+
log.info('Resuming session')
167+
168+
# save trial data
169+
self.trials_table.at[self.trial_num, 'frequency_sequence'] = self.frequencies[self.sequence]
170+
bpod_data = self.bpod.session.current_trial.export()
171+
self.save_trial_data_to_json(bpod_data)
172+
173+
# handle stop event
174+
if self.stopped:
175+
log.info('Stopping session after trial #%d', trial_number)
176+
break
143177

144178

145179
if __name__ == '__main__':

0 commit comments

Comments
 (0)