1414
1515
1616def activate (ephys_schema_name , probe_schema_name = None , create_schema = True , create_tables = True , add_objects = None ):
17- upstream_tables = ("Session" , "SkullReference" )
1817 assert isinstance (add_objects , Mapping )
18+
19+ upstream_tables = ("Session" , "SkullReference" )
1920 try :
2021 raise RuntimeError ("Table %s is required for module ephys" % next (
2122 name for name in upstream_tables
22- if not isinstance (add_objects .get (name , None ), (dj .Manual , dj .Lookup , dj .Imported , dj .Computed ))))
23+ if not isinstance (add_objects .get (name , None ), (dj .Manual , dj .Lookup , dj .Imported , dj .Computed , dj . user_tables . OrderedClass ))))
2324 except StopIteration :
2425 pass # all ok
2526
2627 required_functions = ("get_neuropixels_data_directory" , "get_paramset_idx" , "get_kilosort_output_directory" )
27- assert isinstance (add_objects , Mapping )
2828 try :
2929 raise RuntimeError ("Function %s is required for module ephys" % next (
3030 name for name in required_functions
3131 if not inspect .isfunction (add_objects .get (name , None ))))
3232 except StopIteration :
3333 pass # all ok
3434
35- if not probe .schema .is_activated :
35+ if not probe .schema .database :
3636 probe .schema .activate (probe_schema_name or ephys_schema_name ,
3737 create_schema = create_schema , create_tables = create_tables )
38+
3839 schema .activate (ephys_schema_name , create_schema = create_schema ,
3940 create_tables = create_tables , add_objects = add_objects )
4041
4142
4243# REQUIREMENTS: The workflow module must define these functions ---------------
4344
4445
45- def get_neuropixels_data_directory ():
46- return None
46+ def get_neuropixels_data_directory (probe_insertion_key : dict ) -> str :
47+ """
48+ Retrieve the recorded Neuropixels data directory for a given ProbeInsertion
49+ :param probe_insertion_key: a dictionary of one ProbeInsertion `key`
50+ :return: a string for full path to the resulting Neuropixels data directory
51+ """
52+ assert set (ProbeInsertion ().primary_key ) <= set (probe_insertion_key )
53+ raise NotImplementedError ('Workflow module should define function: "get_neuropixels_data_directory"' )
4754
4855
4956def get_kilosort_output_directory (clustering_task_key : dict ) -> str :
5057 """
5158 Retrieve the Kilosort output directory for a given ClusteringTask
52- :param clustering_task_key: a dictionary of one EphysRecording
59+ :param clustering_task_key: a dictionary of one ClusteringTask `key`
5360 :return: a string for full path to the resulting Kilosort output directory
5461 """
5562 assert set (EphysRecording ().primary_key ) <= set (clustering_task_key )
56- raise NotImplementedError ('Workflow module should define' )
63+ raise NotImplementedError ('Workflow module should define function: "get_kilosort_output_directory" ' )
5764
5865
5966def get_paramset_idx (ephys_rec_key : dict ) -> int :
6067 """
61- Retrieve attribute `paramset_idx` from the ClusteringParamSet record for the given EphysRecording key .
62- :param ephys_rec_key: a dictionary of one EphysRecording
68+ Retrieve attribute `paramset_idx` from the ClusteringParamSet record for the given EphysRecording.
69+ :param ephys_rec_key: a dictionary of one EphysRecording `key`
6370 :return: int specifying the `paramset_idx`
6471 """
6572 assert set (EphysRecording ().primary_key ) <= set (ephys_rec_key )
66- raise NotImplementedError ('Workflow module should define' )
73+ raise NotImplementedError ('Workflow module should define function: get_paramset_idx ' )
6774
6875
69- def dict_to_uuid (key ):
70- """
71- Given a dictionary `key`, returns a hash string
72- """
73- hashed = hashlib .md5 ()
74- for k , v in sorted (key .items ()):
75- hashed .update (str (k ).encode ())
76- hashed .update (str (v ).encode ())
77- return uuid .UUID (hex = hashed .hexdigest ())
78-
7976# ===================================== Probe Insertion =====================================
8077
8178
@@ -109,17 +106,13 @@ class InsertionLocation(dj.Manual):
109106
110107
111108# ===================================== Ephys Recording =====================================
112- # The abstract function _get_neuropixels_data_directory() should expect one argument in the form of a
113- # dictionary with the keys from user-defined Subject and Session, as well as
114- # "insertion_number" (as int) based on the "ProbeInsertion" table definition in this djephys
115-
116109
117110@schema
118111class EphysRecording (dj .Imported ):
119112 definition = """
120113 -> ProbeInsertion
121114 ---
122- -> ElectrodeConfig
115+ -> probe. ElectrodeConfig
123116 sampling_rate: float # (Hz)
124117 """
125118
@@ -143,7 +136,7 @@ def make(self, key):
143136 neuropixels_meta .probe_model ))
144137
145138 # ---- compute hash for the electrode config (hash of dict of all ElectrodeConfig.Electrode) ----
146- ec_hash = uuid . UUID ( dict_to_uuid ({k ['electrode' ]: k for k in eg_members }) )
139+ ec_hash = dict_to_uuid ({k ['electrode' ]: k for k in eg_members })
147140
148141 el_list = sorted ([k ['electrode' ] for k in eg_members ])
149142 el_jumps = [- 1 ] + np .where (np .diff (el_list ) > 1 )[0 ].tolist () + [len (el_list ) - 1 ]
@@ -185,7 +178,7 @@ class Electrode(dj.Part):
185178 """
186179
187180 def make (self , key ):
188- neuropixels_dir = EphysRecording . _get_neuropixels_data_directory (key )
181+ neuropixels_dir = get_neuropixels_data_directory (key )
189182 neuropixels_recording = neuropixels .Neuropixels (neuropixels_dir )
190183
191184 lfp = neuropixels_recording .lfdata [:, :- 1 ].T # exclude the sync channel
@@ -201,7 +194,7 @@ def make(self, key):
201194 q_electrodes = probe .ProbeType .Electrode * probe .ElectrodeConfig .Electrode & key
202195 electrodes = []
203196 for recorded_site in np .arange (lfp .shape [0 ]):
204- shank , shank_col , shank_row , _ = neuropixels_recording .neuropixels_meta .shankmap ['data' ][recorded_site ]
197+ shank , shank_col , shank_row , _ = neuropixels_recording .npx_meta .shankmap ['data' ][recorded_site ]
205198 electrodes .append ((q_electrodes
206199 & {'shank' : shank ,
207200 'shank_col' : shank_col ,
@@ -269,14 +262,15 @@ class ClusteringTask(dj.Imported):
269262 """
270263
271264 def make (self , key ):
272- key ['paramset_idx' ] = ClusteringTask ._get_paramset_idx (key )
273- self .insert1 (key )
265+ key ['paramset_idx' ] = get_paramset_idx (key )
274266
275- data_dir = pathlib .Path (ClusteringTask . _get_ks_data_dir (key ))
267+ data_dir = pathlib .Path (get_kilosort_output_directory (key ))
276268 if not data_dir .exists ():
277269 # this is where we can trigger the clustering job
278270 print (f'Clustering results not yet found for { key } - Triggering kilosort not yet implemented!' )
279271
272+ self .insert1 (key )
273+
280274
281275@schema
282276class ClusterQualityLabel (dj .Lookup ):
@@ -319,7 +313,7 @@ class Unit(dj.Part):
319313 """
320314
321315 def make (self , key ):
322- ks_dir = ClusteringTask . _get_ks_data_dir (key )
316+ ks_dir = get_kilosort_output_directory (key )
323317 ks = kilosort .Kilosort (ks_dir )
324318 # ---------- Clustering ----------
325319 creation_time , is_curated , is_qc = kilosort .extract_clustering_info (ks_dir )
@@ -462,7 +456,7 @@ def make(self, key):
462456
463457
464458def get_neuropixels_chn2electrode_map (ephys_recording_key ):
465- neuropixels_dir = EphysRecording . _get_neuropixels_data_directory (ephys_recording_key )
459+ neuropixels_dir = get_neuropixels_data_directory (ephys_recording_key )
466460 meta_filepath = next (pathlib .Path (neuropixels_dir ).glob ('*.ap.meta' ))
467461 neuropixels_meta = neuropixels .NeuropixelsMeta (meta_filepath )
468462 e_config_key = (EphysRecording * probe .ElectrodeConfig & ephys_recording_key ).fetch1 ('KEY' )
@@ -475,3 +469,14 @@ def get_neuropixels_chn2electrode_map(ephys_recording_key):
475469 'shank_col' : shank_col ,
476470 'shank_row' : shank_row }).fetch1 ('KEY' )
477471 return chn2electrode_map
472+
473+
474+ def dict_to_uuid (key ):
475+ """
476+ Given a dictionary `key`, returns a hash string
477+ """
478+ hashed = hashlib .md5 ()
479+ for k , v in sorted (key .items ()):
480+ hashed .update (str (k ).encode ())
481+ hashed .update (str (v ).encode ())
482+ return uuid .UUID (hex = hashed .hexdigest ())
0 commit comments