1+ import json
2+
13import pandas as pd
4+ import numpy as np
5+ import logging
6+
7+ from pybpodapi .state_machine import StateMachine
28
3- import iblrig
4- import iblrig .misc
5- import iblrig .sound
9+ from iblrig import sound
610from iblrig .base_tasks import BaseSession , BpodMixin
11+ from iblrig .misc import get_task_arguments
12+
13+ logger = logging .getLogger ('iblrig' )
714
815
916class Session (BpodMixin , BaseSession ):
@@ -12,10 +19,80 @@ class Session(BpodMixin, BaseSession):
1219 def __init__ (self , * args , ** kwargs ):
1320 super ().__init__ (* args , ** kwargs )
1421
15- self .attenuation = pd .read_csv (self .get_task_directory ().joinpath ('attenuation.csv' ))
22+ assert self .hardware_settings .device_sound .OUTPUT == 'harp' , 'This task requires a Harp sound-card'
23+ assert self .task_params ['n_freqs' ] <= 31 , 'Harp only supports up to 31 individual sounds'
24+
25+ # define frequencies (log spaced from freq_0 to freq_1, rounded to nearest integer)
26+ self .frequencies = np .logspace (
27+ np .log10 (self .task_params ['freq_0' ]),
28+ np .log10 (self .task_params ['freq_1' ]),
29+ num = self .task_params ['n_freqs' ],
30+ )
31+ self .frequencies = np .round (self .frequencies ).astype (int )
32+
33+ # generate stimuli
34+ self .stimuli = []
35+ for f in self .frequencies :
36+ tmp = sound .make_sound (
37+ rate = self .task_params ['fs' ],
38+ frequency = f ,
39+ duration = self .task_params ['d_sound' ],
40+ amplitude = self .task_params ['amplitude' ],
41+ fade = self .task_params ['d_ramp' ],
42+ chans = 'stereo' ,
43+ gain_db = 0 ,
44+ )
45+ self .stimuli .append (tmp )
46+ self .indices = [i for i in range (2 , len (self .stimuli ) + 2 )]
47+
48+ # self.attenuation = pd.read_csv(self.get_task_directory().joinpath('attenuation.csv'))
49+
50+ def start_mixin_sound (self ):
51+ logger .info (f'Pushing { len (self .frequencies )} stimuli to Harp soundcard' )
52+ sound .configure_sound_card (sounds = self .stimuli , indexes = self .indices , sample_rate = self .task_params ['fs' ])
53+
54+ module = self .bpod .sound_card
55+ module_port = f'Serial{ module .serial_port if module is not None else "3" } '
56+ for idx , harp_index in enumerate (self .indices ):
57+ bpod_message = [ord ("P" ), harp_index ]
58+ bpod_action = (module_port , self .bpod ._define_message (self .bpod .sound_card , bpod_message ))
59+ self .bpod .actions .update ({f'play_{ idx } ' : bpod_action })
60+
61+ def start_hardware (self ):
62+ self .start_mixin_bpod ()
63+ self .start_mixin_sound ()
64+
65+ def get_state_machine (self , sequence ):
66+ sma = StateMachine (self .bpod )
67+ # table = self.sequence_table[self.sequence_table['sequence'] == sequence].reindex()
68+
69+ for i , frequency in enumerate (self .frequencies ):
70+ sma .add_state (
71+ state_name = f"trigger_sound_{ i } " ,
72+ state_timer = self .task_params ['d_sound' ] + self .task_params ['d_pause' ],
73+ output_actions = [self .bpod .actions [f'play_{ i } ' ]],
74+ state_change_conditions = {
75+ "Tup" : f"trigger_sound_{ i + 1 } " ,
76+ },
77+ )
78+ sma .add_state (
79+ state_name = f"trigger_sound_{ i + 1 } " ,
80+ state_timer = 0.0 ,
81+ state_change_conditions = {"Tup" : "exit" },
82+ )
83+ return sma
84+
85+ def _run (self ):
86+ logger .info ("Sending spacers to BNC ports" )
87+ self .send_spacers ()
88+
89+ sma = self .get_state_machine (1 )
90+ self .bpod .send_state_machine (sma )
91+ self .bpod .run_state_machine (sma )
92+
1693
1794
1895if __name__ == '__main__' : # pragma: no cover
19- kwargs = iblrig . misc . get_task_arguments ()
96+ kwargs = get_task_arguments ()
2097 sess = Session (** kwargs )
2198 sess .run ()
0 commit comments