|
1 |
| -import pathlib |
2 | 1 | import datetime
|
3 |
| -import datajoint as dj |
| 2 | +import pathlib |
4 | 3 | import typing as T
|
5 |
| -import json |
| 4 | +from uuid import UUID |
| 5 | + |
| 6 | +import datajoint as dj |
| 7 | +from element_interface.utils import dict_to_uuid |
6 | 8 |
|
7 | 9 | schema = dj.schema()
|
8 | 10 |
|
@@ -92,18 +94,18 @@ class UnitLevelReport(dj.Computed):
|
92 | 94 | definition = """
|
93 | 95 | -> ephys.CuratedClustering.Unit
|
94 | 96 | ---
|
95 |
| - cluster_quality_label : varchar(100) |
96 |
| - waveform_plotly : longblob |
| 97 | + cluster_quality_label : varchar(100) |
| 98 | + waveform_plotly : longblob |
97 | 99 | autocorrelogram_plotly : longblob
|
98 | 100 | depth_waveform_plotly : longblob
|
99 | 101 | """
|
100 | 102 |
|
101 | 103 | def make(self, key):
|
102 | 104 |
|
103 | 105 | from .plotting.unit_level import (
|
104 |
| - plot_waveform, |
105 | 106 | plot_auto_correlogram,
|
106 | 107 | plot_depth_waveforms,
|
| 108 | + plot_waveform, |
107 | 109 | )
|
108 | 110 |
|
109 | 111 | sampling_rate = (ephys.EphysRecording & key).fetch1(
|
@@ -136,6 +138,94 @@ def make(self, key):
|
136 | 138 | )
|
137 | 139 |
|
138 | 140 |
|
| 141 | +@schema |
| 142 | +class QualityMetricCutoffs(dj.Lookup): |
| 143 | + definition = """ |
| 144 | + cutoffs_id : smallint |
| 145 | + --- |
| 146 | + amplitude_cutoff_maximum=null : float # Defualt null, no cutoff applied |
| 147 | + presence_ratio_minimum=null : float # Defualt null, no cutoff applied |
| 148 | + isi_violations_maximum=null : float # Defualt null, no cutoff applied |
| 149 | + cutoffs_hash: uuid |
| 150 | + unique index (cutoffs_hash) |
| 151 | + """ |
| 152 | + |
| 153 | + contents = [ |
| 154 | + (0, None, None, None, UUID("5d835de1-e1af-1871-d81f-d12a9702ff5f")), |
| 155 | + (1, 0.1, 0.9, 0.5, UUID("f74ccd77-0b3a-2bf8-0bfd-ec9713b5dca8")), |
| 156 | + ] |
| 157 | + |
| 158 | + @classmethod |
| 159 | + def insert_new_cutoffs( |
| 160 | + cls, |
| 161 | + cutoffs_id: int = None, |
| 162 | + amplitude_cutoff_maximum: float = None, |
| 163 | + presence_ratio_minimum: float = None, |
| 164 | + isi_violations_maximum: float = None, |
| 165 | + ): |
| 166 | + if cutoffs_id is None: |
| 167 | + cutoffs_id = (dj.U().aggr(cls, n="max(cutoffs_id)").fetch1("n") or 0) + 1 |
| 168 | + |
| 169 | + param_dict = { |
| 170 | + "amplitude_cutoff_maximum": amplitude_cutoff_maximum, |
| 171 | + "presence_ratio_minimum": presence_ratio_minimum, |
| 172 | + "isi_violations_maximum": isi_violations_maximum, |
| 173 | + } |
| 174 | + param_hash = dict_to_uuid(param_dict) |
| 175 | + param_query = cls & {"cutoffs_hash": param_hash} |
| 176 | + |
| 177 | + if param_query: # If the specified cutoff set already exists |
| 178 | + existing_paramset_idx = param_query.fetch1("cutoffs_id") |
| 179 | + if ( |
| 180 | + existing_paramset_idx == cutoffs_id |
| 181 | + ): # If the existing set has the same id: job done |
| 182 | + return |
| 183 | + # If not same name: human err, adding the same set with different name |
| 184 | + else: |
| 185 | + raise dj.DataJointError( |
| 186 | + f"The specified param-set already exists" |
| 187 | + f" - with paramset_idx: {existing_paramset_idx}" |
| 188 | + ) |
| 189 | + else: |
| 190 | + if {"cutoffs_id": cutoffs_id} in cls.proj(): |
| 191 | + raise dj.DataJointError( |
| 192 | + f"The specified cuttoffs_id {cutoffs_id} already exists," |
| 193 | + f" please pick a different one." |
| 194 | + ) |
| 195 | + cls.insert1( |
| 196 | + {"cutoffs_id": cutoffs_id, **param_dict, "cutoffs_hash": param_hash} |
| 197 | + ) |
| 198 | + |
| 199 | + |
| 200 | +@schema |
| 201 | +class QualityMetricSet(dj.Manual): |
| 202 | + definition = """ |
| 203 | + -> ephys.QualityMetrics |
| 204 | + -> QualityMetricCutoffs |
| 205 | + """ |
| 206 | + |
| 207 | + |
| 208 | +@schema |
| 209 | +class QualityMetricReport(dj.Computed): |
| 210 | + definition = """ |
| 211 | + -> QualityMetricSet |
| 212 | + --- |
| 213 | + plot_grid : longblob |
| 214 | + """ |
| 215 | + |
| 216 | + def make(self, key): |
| 217 | + from .plotting.qc import QualityMetricFigs |
| 218 | + |
| 219 | + cutoffs = (QualityMetricCutoffs & key).fetch1() |
| 220 | + qc_key = ephys.QualityMetrics & key |
| 221 | + |
| 222 | + self.insert1( |
| 223 | + key.update( |
| 224 | + dict(plot_grid=QualityMetricFigs(qc_key, **cutoffs).get_grid().to_json) |
| 225 | + ) |
| 226 | + ) |
| 227 | + |
| 228 | + |
139 | 229 | def _make_save_dir(root_dir: pathlib.Path = None) -> pathlib.Path:
|
140 | 230 | if root_dir is None:
|
141 | 231 | root_dir = pathlib.Path().absolute()
|
|
0 commit comments