11import gc
22from dataclasses import replace
33from pathlib import Path
4- from typing import ClassVar
4+ from typing import ClassVar , Self
55
66import numpy as np
77import torch
@@ -83,19 +83,19 @@ def __post_init__(self):
8383 assert v .shape [0 ] == ntemp
8484
8585 @property
86- def spike_length_samples (self ):
86+ def spike_length_samples (self ) -> int :
8787 return self .templates .shape [1 ]
8888
89- def snrs_by_channel (self ):
89+ def snrs_by_channel (self ) -> np . ndarray :
9090 amp_vecs = np .nan_to_num (np .ptp (self .templates , axis = 1 ), nan = - np .inf )
9191 if self .spike_counts_by_channel is not None :
9292 amp_vecs *= np .sqrt (self .spike_counts_by_channel )
9393 return amp_vecs
9494
95- def main_channels (self ):
95+ def main_channels (self ) -> np . ndarray :
9696 return self .snrs_by_channel ().argmax (axis = 1 )
9797
98- def template_locations (self , mode = "channel" , radius = 100.0 ):
98+ def template_locations (self , mode = "channel" , radius = 100.0 ) -> np . ndarray :
9999 assert mode in ("localization" , "channel" )
100100
101101 if mode == "channel" :
@@ -112,11 +112,11 @@ def template_locations(self, mode="channel", radius=100.0):
112112 rdepths = np .c_ [rdepths ["x" ], rdepths ["z_abs" ]]
113113 return rdepths
114114
115- def registered_depths_um (self , mode = "channel" , radius = 100.0 ):
115+ def registered_depths_um (self , mode = "channel" , radius = 100.0 ) -> np . ndarray :
116116 return self .template_locations (mode = mode , radius = radius )[:, 1 ]
117117
118118 @classmethod
119- def from_npz (cls , npz_path ):
119+ def from_npz (cls , npz_path ) -> Self :
120120 with np .load (npz_path , allow_pickle = True ) as data :
121121 data = dict (** data )
122122 data ["whiten_strategy" ] = str (data ["whiten_strategy" ])
@@ -182,7 +182,7 @@ def to_npz(self, npz_path):
182182 to_save [f"__prop_{ k } " ] = p
183183 np .savez (npz_path , ** to_save ) # type: ignore
184184
185- def __getitem__ (self , subset ):
185+ def __getitem__ (self , subset ) -> Self :
186186 if not np .array_equal (self .unit_ids , np .arange (len (self .unit_ids ))):
187187 subset_ixs = np .searchsorted (self .unit_ids , subset , side = "right" ) - 1
188188 matched = self .unit_ids [subset_ixs ] == subset
@@ -212,7 +212,7 @@ def __getitem__(self, subset):
212212 whiten_strategy = self .whiten_strategy ,
213213 )
214214
215- def coarsen (self ):
215+ def coarsen (self ) -> Self :
216216 """Weighted average all templates that share a unit id."""
217217 # update templates
218218 unit_ids_unique , flat_ids = np .unique (self .unit_ids , return_inverse = True )
@@ -231,10 +231,10 @@ def coarsen(self):
231231 tsvd = self .tsvd ,
232232 )
233233
234- def unit_mask (self , unit_id ):
234+ def unit_mask (self , unit_id ) -> np . ndarray :
235235 return np .isin (self .unit_ids , unit_id )
236236
237- def unit_templates (self , unit_id ):
237+ def unit_templates (self , unit_id ) -> np . ndarray :
238238 return self .templates [self .unit_mask (unit_id )]
239239
240240 def __init_subclass__ (cls ):
@@ -258,7 +258,7 @@ def from_config(
258258 featurization_basis = None ,
259259 computation_cfg : ComputationConfig | None = None ,
260260 show_progress : bool = True ,
261- ) -> "TemplateData" :
261+ ) -> Self :
262262 # load if saved already and not overwriting
263263 if save_folder is not None :
264264 save_folder = Path (save_folder )
@@ -326,7 +326,7 @@ def _from_config(
326326 whitener : Whitener | None = None ,
327327 tsvd = None ,
328328 computation_cfg : ComputationConfig | None = None ,
329- ) -> "TemplateData" :
329+ ) -> Self :
330330 raise NotImplementedError
331331
332332
@@ -353,4 +353,4 @@ def _try_reload_svd(
353353 logger .dartsortdebug (f"Reloading TSVD from { tnpz } " )
354354 else :
355355 logger .dartsortdebug (f"No TSVD to reload in { tnpz } " )
356- return tsvd
356+ return tsvd # ty: ignore[invalid-return-type]
0 commit comments