|
1 | 1 | import datetime
|
2 | 2 | import pathlib
|
| 3 | +from uuid import UUID |
3 | 4 |
|
4 | 5 | import datajoint as dj
|
| 6 | +from element_interface.utils import dict_to_uuid |
5 | 7 |
|
6 | 8 | from . import probe
|
7 | 9 |
|
@@ -153,6 +155,94 @@ def make(self, key):
|
153 | 155 | )
|
154 | 156 |
|
155 | 157 |
|
| 158 | +@schema |
| 159 | +class QualityMetricCutoffs(dj.Lookup): |
| 160 | + definition = """ |
| 161 | + cutoffs_id : smallint |
| 162 | + --- |
| 163 | + amplitude_cutoff_maximum=null : float # Defualt null, no cutoff applied |
| 164 | + presence_ratio_minimum=null : float # Defualt null, no cutoff applied |
| 165 | + isi_violations_maximum=null : float # Defualt null, no cutoff applied |
| 166 | + cutoffs_hash: uuid |
| 167 | + unique index (cutoffs_hash) |
| 168 | + """ |
| 169 | + |
| 170 | + contents = [ |
| 171 | + (0, None, None, None, UUID("5d835de1-e1af-1871-d81f-d12a9702ff5f")), |
| 172 | + (1, 0.1, 0.9, 0.5, UUID("f74ccd77-0b3a-2bf8-0bfd-ec9713b5dca8")), |
| 173 | + ] |
| 174 | + |
| 175 | + @classmethod |
| 176 | + def insert_new_cutoffs( |
| 177 | + cls, |
| 178 | + cutoffs_id: int = None, |
| 179 | + amplitude_cutoff_maximum: float = None, |
| 180 | + presence_ratio_minimum: float = None, |
| 181 | + isi_violations_maximum: float = None, |
| 182 | + ): |
| 183 | + if cutoffs_id is None: |
| 184 | + cutoffs_id = (dj.U().aggr(cls, n="max(cutoffs_id)").fetch1("n") or 0) + 1 |
| 185 | + |
| 186 | + param_dict = { |
| 187 | + "amplitude_cutoff_maximum": amplitude_cutoff_maximum, |
| 188 | + "presence_ratio_minimum": presence_ratio_minimum, |
| 189 | + "isi_violations_maximum": isi_violations_maximum, |
| 190 | + } |
| 191 | + param_hash = dict_to_uuid(param_dict) |
| 192 | + param_query = cls & {"cutoffs_hash": param_hash} |
| 193 | + |
| 194 | + if param_query: # If the specified cutoff set already exists |
| 195 | + existing_paramset_idx = param_query.fetch1("cutoffs_id") |
| 196 | + if ( |
| 197 | + existing_paramset_idx == cutoffs_id |
| 198 | + ): # If the existing set has the same id: job done |
| 199 | + return |
| 200 | + # If not same name: human err, adding the same set with different name |
| 201 | + else: |
| 202 | + raise dj.DataJointError( |
| 203 | + f"The specified param-set already exists" |
| 204 | + f" - with paramset_idx: {existing_paramset_idx}" |
| 205 | + ) |
| 206 | + else: |
| 207 | + if {"cutoffs_id": cutoffs_id} in cls.proj(): |
| 208 | + raise dj.DataJointError( |
| 209 | + f"The specified cuttoffs_id {cutoffs_id} already exists," |
| 210 | + f" please pick a different one." |
| 211 | + ) |
| 212 | + cls.insert1( |
| 213 | + {"cutoffs_id": cutoffs_id, **param_dict, "cutoffs_hash": param_hash} |
| 214 | + ) |
| 215 | + |
| 216 | + |
| 217 | +@schema |
| 218 | +class QualityMetricSet(dj.Manual): |
| 219 | + definition = """ |
| 220 | + -> ephys.QualityMetrics |
| 221 | + -> QualityMetricCutoffs |
| 222 | + """ |
| 223 | + |
| 224 | + |
| 225 | +@schema |
| 226 | +class QualityMetricReport(dj.Computed): |
| 227 | + definition = """ |
| 228 | + -> QualityMetricSet |
| 229 | + --- |
| 230 | + plot_grid : longblob |
| 231 | + """ |
| 232 | + |
| 233 | + def make(self, key): |
| 234 | + from .plotting.qc import QualityMetricFigs |
| 235 | + |
| 236 | + cutoffs = (QualityMetricCutoffs & key).fetch1() |
| 237 | + qc_key = ephys.QualityMetrics & key |
| 238 | + |
| 239 | + self.insert1( |
| 240 | + key.update( |
| 241 | + dict(plot_grid=QualityMetricFigs(qc_key, **cutoffs).get_grid().to_json) |
| 242 | + ) |
| 243 | + ) |
| 244 | + |
| 245 | + |
156 | 246 | def _make_save_dir(root_dir: pathlib.Path = None) -> pathlib.Path:
|
157 | 247 | if root_dir is None:
|
158 | 248 | root_dir = pathlib.Path().absolute()
|
|
0 commit comments