|
| 1 | +import logging |
| 2 | +from pathlib import Path |
1 | 3 | import time |
| 4 | + |
2 | 5 | import numpy as np |
3 | | -# (Previously required `os.path` to get file info before memmapping) |
4 | | -# import os.path as op |
| 6 | + |
5 | 7 | from ibllib.io import spikeglx |
6 | 8 |
|
| 9 | +_logger = logging.getLogger('ibllib') |
| 10 | + |
7 | 11 |
|
8 | 12 | def extract_waveforms(ephys_file, ts, ch, t=2.0, sr=30000, n_ch_probe=385, car=True): |
9 | 13 | """ |
@@ -100,3 +104,52 @@ def extract_waveforms(ephys_file, ts, ch, t=2.0, sr=30000, n_ch_probe=385, car=T |
100 | 104 | print('Done. ({})'.format(time.ctime())) |
101 | 105 |
|
102 | 106 | return waveforms |
| 107 | + |
| 108 | + |
| 109 | +def stream(pid, t0, nsecs=1, one=None, cache_folder=None, dsets=None, typ='ap'): |
| 110 | + """ |
| 111 | + NB: returned Reader object must be closed after use |
| 112 | + :param pid: Probe UUID |
| 113 | + :param t0: time of the first sample |
| 114 | + :param nsecs: duration of the streamed data |
| 115 | + :param one: An instance of ONE |
| 116 | + :param cache_folder: |
| 117 | + :param typ: 'ap' or 'lf' |
| 118 | + :return: sr, dsets, t0 |
| 119 | + """ |
| 120 | + CHUNK_DURATION_SECS = 1 # the mtscomp chunk duration. Right now it's a constant |
| 121 | + if nsecs > 10: |
| 122 | + ValueError(f'Streamer works only with 10 or less seconds, set nsecs to lesss than {nsecs}') |
| 123 | + assert one |
| 124 | + assert typ in ['lf', 'ap'] |
| 125 | + t0 = np.floor(t0 / CHUNK_DURATION_SECS) * CHUNK_DURATION_SECS |
| 126 | + if cache_folder is None: |
| 127 | + samples_folder = Path(one.alyx._par.CACHE_DIR).joinpath('cache', typ) |
| 128 | + sample_file_name = Path(f"{pid}_{str(int(t0)).zfill(5)}.meta") |
| 129 | + |
| 130 | + if samples_folder.joinpath(sample_file_name).exists(): |
| 131 | + _logger.info(f'loading {sample_file_name} from cache') |
| 132 | + sr = spikeglx.Reader(samples_folder.joinpath(sample_file_name).with_suffix('.bin'), |
| 133 | + open=True) |
| 134 | + return sr, t0 |
| 135 | + |
| 136 | + eid, pname = one.pid2eid(pid) |
| 137 | + cbin_rec = one.list_datasets(eid, collection=f"*{pname}", filename='*ap.*bin', details=True) |
| 138 | + ch_rec = one.list_datasets(eid, collection=f"*{pname}", filename='*ap.ch', details=True) |
| 139 | + meta_rec = one.list_datasets(eid, collection=f"*{pname}", filename='*ap.meta', details=True) |
| 140 | + ch_file = one._download_datasets(ch_rec)[0] |
| 141 | + one._download_datasets(meta_rec)[0] |
| 142 | + |
| 143 | + first_chunk = int(t0 / CHUNK_DURATION_SECS) |
| 144 | + last_chunk = int((t0 + nsecs) / CHUNK_DURATION_SECS) - 1 |
| 145 | + |
| 146 | + samples_folder.mkdir(exist_ok=True, parents=True) |
| 147 | + sr = spikeglx.download_raw_partial( |
| 148 | + one=one, |
| 149 | + url_cbin=one.record2url(cbin_rec)[0], |
| 150 | + url_ch=ch_file, |
| 151 | + first_chunk=first_chunk, |
| 152 | + last_chunk=last_chunk, |
| 153 | + cache_dir=samples_folder) |
| 154 | + |
| 155 | + return sr, t0 |
0 commit comments