def test_sync_3A(self): if not self.folder3a.exists(): return # the assertion is already in the files # test both residual smoothed and linear for ses_path in self.folder3a.rglob('raw_ephys_data'): self.assertTrue(sync_probes.version3A(ses_path.parent)) self.assertTrue(sync_probes.version3A(ses_path.parent, linear=True, tol=2))
def test_sync_3A_single(self): ses_path = self.folder3a_single.joinpath('sub', '2019-08-09', '004') self.assertTrue(sync_probes.version3A(ses_path, display=False)) self.assertTrue( np.all( np.load(list(ses_path.rglob('*.sync.npy'))[0]) == np.array( [[0, 0], [1, 1]])))
def test_sync_3A(self): if not self.folder3a.exists(): return # the assertion is already in the files # test both residual smoothed and linear for ses_path in self.folder3a.rglob('raw_ephys_data'): # we switched to sync using frame2ttl on November 2019 channel = 12 if '2019-11-05' in str(ses_path) else 2 self.assertTrue( sync_probes.version3A(ses_path.parent, type='linear', tol=2, display=False)) self.assertTrue( sync_probes.version3A(ses_path.parent, display=True)) dt = _check_session_sync(ses_path, channel=channel) self.assertTrue(np.all(np.abs(dt * 30000) < 2))
def validate_ttl_test(ses_path, display=False): """ For a mock session on the Ephys Choice world task, check the sync channels for all device properly connected and perform a synchronization if dual probes to check that all channels are recorded properly :param ses_path: session path :param display: show the probe synchronization plot if several probes :return: True if tests pass, errors otherwise """ def _single_test(assertion, str_ok, str_ko): if assertion: _logger.info(str_ok) return True else: _logger.error(str_ko) return False EXPECTED_RATES_HZ = {'left_camera': 60, 'right_camera': 150, 'body_camera': 30} SYNC_RATE_HZ = 1 MIN_TRIALS_NB = 6 ok = True ses_path = Path(ses_path) if not ses_path.exists(): return False rawsync, sync_map = fpga._get_main_probe_sync(ses_path) last_time = rawsync['times'][-1] # get upgoing fronts for each sync = Bunch({}) for k in sync_map: fronts = fpga._get_sync_fronts(rawsync, sync_map[k]) sync[k] = fronts['times'][fronts['polarities'] == 1] wheel = fpga.extract_wheel_sync(rawsync, chmap=sync_map, save=False) frame_rates = {'right_camera': np.round(1 / np.median(np.diff(sync.right_camera))), 'left_camera': np.round(1 / np.median(np.diff(sync.left_camera))), 'body_camera': np.round(1 / np.median(np.diff(sync.body_camera)))} # check the camera frame rates for lab in frame_rates: expect = EXPECTED_RATES_HZ[lab] ok &= _single_test(assertion=abs((1 - frame_rates[lab] / expect)) < 0.1, str_ok=f'PASS: {lab} frame rate: {frame_rates[lab]} = {expect} Hz', str_ko=f'FAILED: {lab} frame rate: {frame_rates[lab]} != {expect} Hz') # check that the wheel has a minimum rate of activity on both channels re_test = abs(1 - sync.rotary_encoder_1.size / sync.rotary_encoder_0.size) < 0.1 re_test &= len(wheel['re_pos']) / last_time > 5 ok &= _single_test(assertion=re_test, str_ok="PASS: Rotary encoder", str_ko="FAILED: Rotary encoder") # check that the frame 2 ttls has a minimum rate of activity ok &= _single_test(assertion=len(sync.frame2ttl) / last_time > 0.2, str_ok="PASS: Frame2TTL", str_ko="FAILED: Frame2TTL") # the audio has to have at least one event per trial ok &= _single_test(assertion=len(sync.bpod) > len(sync.audio) > MIN_TRIALS_NB, str_ok="PASS: audio", str_ko="FAILED: audio") # the bpod has to have at least twice the amount of min trial pulses ok &= _single_test(assertion=len(sync.bpod) > MIN_TRIALS_NB * 2, str_ok="PASS: Bpod", str_ko="FAILED: Bpod") try: # note: tried to depend as little as possible on the extraction code but for the valve... behaviour = fpga.extract_behaviour_sync(rawsync, save=False, chmap=sync_map) res = behaviour.valve_open.size > 1 except AssertionError: res = False # check that the reward valve is actionned at least once ok &= _single_test(assertion=res, str_ok="PASS: Valve open", str_ko="FAILED: Valve open not detected") _logger.info('ALL CHECKS PASSED !') # the imec sync is for 3B Probes only if sync.get('imec_sync') is not None: ok &= _single_test(assertion=np.all(1 - SYNC_RATE_HZ * np.diff(sync.imec_sync) < 0.1), str_ok="PASS: imec sync", str_ko="FAILED: imec sync") # second step is to test that we can make the sync. Assertions are whithin the synch code if sync.get('imec_sync') is not None: sync_result = sync_probes.version3B(ses_path, display=display) else: sync_result = sync_probes.version3A(ses_path, display=display) ok &= _single_test(assertion=sync_result, str_ok="PASS: synchronisation", str_ko="FAILED: probe synchronizations threshold exceeded") if not ok: raise ValueError('FAILED TTL test') return ok