Skip to content

Commit 523f2e9

Browse files
committed
2 parents e613fc4 + 0f518f1 commit 523f2e9

27 files changed

+487
-337
lines changed

.pre-commit-config.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
default_stages: [commit, push]
2+
exclude: (^.github/|^docs/|^images/)
3+
4+
repos:
5+
- repo: https://github.com/pre-commit/pre-commit-hooks
6+
rev: v4.4.0
7+
hooks:
8+
- id: trailing-whitespace
9+
- id: end-of-file-fixer
10+
- id: check-yaml
11+
- id: check-added-large-files # prevent giant files from being committed
12+
- id: requirements-txt-fixer
13+
- id: mixed-line-ending
14+
args: ["--fix=lf"]
15+
description: Forces to replace line ending by the UNIX 'lf' character.
16+
17+
# black
18+
- repo: https://github.com/psf/black
19+
rev: 22.12.0
20+
hooks:
21+
- id: black
22+
- id: black-jupyter
23+
args:
24+
- --line-length=88
25+
26+
# isort
27+
- repo: https://github.com/pycqa/isort
28+
rev: 5.11.2
29+
hooks:
30+
- id: isort
31+
args: ["--profile", "black"]
32+
description: Sorts imports in an alphabetical order
33+
34+
# flake8
35+
- repo: https://github.com/pycqa/flake8
36+
rev: 4.0.1
37+
hooks:
38+
- id: flake8
39+
args: # arguments to configure flake8
40+
# making isort line length compatible with black
41+
- "--max-line-length=88"
42+
- "--max-complexity=18"
43+
- "--select=B,C,E,F,W,T4,B9"
44+
45+
# these are errors that will be ignored by flake8
46+
# https://www.flake8rules.com/rules/{code}.html
47+
- "--ignore=E203,E501,W503,W605"
48+
# E203 - Colons should not have any space before them.
49+
# Needed for list indexing
50+
# E501 - Line lengths are recommended to be no greater than 79 characters.
51+
# Needed as we conform to 88
52+
# W503 - Line breaks should occur after the binary operator.
53+
# Needed because not compatible with black
54+
# W605 - a backslash-character pair that is not a valid escape sequence now
55+
# generates a DeprecationWarning. This will eventually become a SyntaxError.
56+
# Needed because we use \d as an escape sequence

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Observes [Semantic Versioning](https://semver.org/spec/v2.0.0.html) standard and
4848

4949
+ Update - Rename module for acute probe insertions from `ephys.py` to `ephys_acute.py`.
5050
+ Add - Module for pre-clustering steps (`ephys_precluster.py`), which is built off of `ephys_acute.py`.
51-
+ Add - Module for chronic probe insertions (`ephys_chronic.py`).
51+
+ Add - Module for chronic probe insertions (`ephys_chronic.py`).
5252
+ Bugfix - Missing `fileTimeSecs` key in SpikeGLX meta file.
5353
+ Update - Move common functions to `element-interface` package.
5454
+ Add - NWB export function

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Contribution Guidelines
22

3-
This project follows the [DataJoint Contribution Guidelines](https://docs.datajoint.io/python/community/02-Contribute.html). Please reference the link for more full details.
3+
This project follows the [DataJoint Contribution Guidelines](https://datajoint.com/docs/community/contribute/). Please reference the link for more full details.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ fully functional pipeline.
88

99
![diagram](https://raw.githubusercontent.com/datajoint/element-array-ephys/main/images/diagram_flowchart.svg)
1010

11-
Installation and usage instructions can be found at the
11+
Installation and usage instructions can be found at the
1212
[Element documentation](https://datajoint.com/docs/elements/element-array-ephys).

docs/src/api/make_pages.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,3 @@
4141

4242
with mkdocs_gen_files.open("api/navigation.md", "w") as nav_file:
4343
nav_file.writelines(nav.build_literate_nav())
44-

docs/src/concepts.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ Tables related to information about physiological recordings and automatic inges
104104
| CuratedClusting.Unit | A part table containing single unit information after spike sorting and optional curation. |
105105
| WaveformSet | A table containing spike waveforms for single units. |
106106

107+
### `ephys_report` schema ([API docs](../api/element_array_ephys/ephys_report))
108+
Tables for storing probe or unit-level visualization results.
109+
110+
| Table | Description |
111+
| --- | --- |
112+
| ProbeLevelReport | A table to store drift map figures generated from each recording probe. |
113+
| UnitLevelReport | A table to store figures (waveforms, autocorrelogram, peak waveform + neighbors) generated for each unit. |
114+
107115
## Element Development
108116

109117
Through our interviews and direct collaboration on the precursor projects, we identified the common motifs to create the [Array Electrophysiology Element](https://github.com/datajoint/element-array-ephys).

element_array_ephys/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import datajoint as dj
21
import logging
32
import os
43

4+
import datajoint as dj
5+
6+
from . import ephys_acute as ephys
7+
8+
__all__ = ["ephys", "get_logger"]
59

610
dj.config["enable_python_native_blobs"] = True
711

@@ -10,6 +14,3 @@ def get_logger(name):
1014
log = logging.getLogger(name)
1115
log.setLevel(os.getenv("LOGLEVEL", "INFO"))
1216
return log
13-
14-
15-
from . import ephys_acute as ephys

element_array_ephys/ephys_acute.py

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import datajoint as dj
1+
import gc
2+
import importlib
3+
import inspect
24
import pathlib
35
import re
4-
import numpy as np
5-
import inspect
6-
import importlib
7-
import gc
86
from decimal import Decimal
9-
import pandas as pd
107

11-
from element_interface.utils import find_root_directory, find_full_path, dict_to_uuid
8+
import datajoint as dj
9+
import numpy as np
10+
import pandas as pd
11+
from element_interface.utils import dict_to_uuid, find_full_path, find_root_directory
1212

13-
from .readers import spikeglx, kilosort, openephys
14-
from . import probe, get_logger, ephys_report
13+
from . import ephys_report, get_logger, probe
14+
from .readers import kilosort, openephys, spikeglx
1515

1616
log = get_logger(__name__)
1717

@@ -127,7 +127,7 @@ class AcquisitionSoftware(dj.Lookup):
127127
"""
128128

129129
definition = """ # Software used for recording of neuropixels probes
130-
acq_software: varchar(24)
130+
acq_software: varchar(24)
131131
"""
132132
contents = zip(["SpikeGLX", "Open Ephys"])
133133

@@ -265,7 +265,7 @@ class EphysRecording(dj.Imported):
265265

266266
definition = """
267267
# Ephys recording from a probe insertion for a given session.
268-
-> ProbeInsertion
268+
-> ProbeInsertion
269269
---
270270
-> probe.ElectrodeConfig
271271
-> AcquisitionSoftware
@@ -473,9 +473,9 @@ class Electrode(dj.Part):
473473

474474
definition = """
475475
-> master
476-
-> probe.ElectrodeConfig.Electrode
476+
-> probe.ElectrodeConfig.Electrode
477477
---
478-
lfp: longblob # (uV) recorded lfp at this electrode
478+
lfp: longblob # (uV) recorded lfp at this electrode
479479
"""
480480

481481
# Only store LFP for every 9th channel, due to high channel density,
@@ -629,7 +629,7 @@ class ClusteringParamSet(dj.Lookup):
629629
# Parameter set to be used in a clustering procedure
630630
paramset_idx: smallint
631631
---
632-
-> ClusteringMethod
632+
-> ClusteringMethod
633633
paramset_desc: varchar(128)
634634
param_set_hash: uuid
635635
unique index (param_set_hash)
@@ -694,7 +694,7 @@ class ClusterQualityLabel(dj.Lookup):
694694
695695
Attributes:
696696
cluster_quality_label (foreign key, varchar(100) ): Cluster quality type.
697-
cluster_quality_description (varchar(4000) ): Description of the cluster quality type.
697+
cluster_quality_description ( varchar(4000) ): Description of the cluster quality type.
698698
"""
699699

700700
definition = """
@@ -718,7 +718,7 @@ class ClusteringTask(dj.Manual):
718718
Attributes:
719719
EphysRecording (foreign key): EphysRecording primary key.
720720
ClusteringParamSet (foreign key): ClusteringParamSet primary key.
721-
clustering_outdir_dir (varchar (255) ): Relative path to output clustering results.
721+
clustering_output_dir ( varchar (255) ): Relative path to output clustering results.
722722
task_mode (enum): `Trigger` computes clustering or and `load` imports existing data.
723723
"""
724724

@@ -808,14 +808,14 @@ class Clustering(dj.Imported):
808808
Attributes:
809809
ClusteringTask (foreign key): ClusteringTask primary key.
810810
clustering_time (datetime): Time when clustering results are generated.
811-
package_version (varchar(16) ): Package version used for a clustering analysis.
811+
package_version ( varchar(16) ): Package version used for a clustering analysis.
812812
"""
813813

814814
definition = """
815815
# Clustering Procedure
816816
-> ClusteringTask
817817
---
818-
clustering_time: datetime # time of generation of this set of clustering results
818+
clustering_time: datetime # time of generation of this set of clustering results
819819
package_version='': varchar(16)
820820
"""
821821

@@ -857,6 +857,10 @@ def make(self, key):
857857
spikeglx_meta_filepath.parent
858858
)
859859
spikeglx_recording.validate_file("ap")
860+
run_CatGT = (
861+
params.pop("run_CatGT", True)
862+
and "_tcat." not in spikeglx_meta_filepath.stem
863+
)
860864

861865
if clustering_method.startswith("pykilosort"):
862866
kilosort_triggering.run_pykilosort(
@@ -877,7 +881,7 @@ def make(self, key):
877881
ks_output_dir=kilosort_dir,
878882
params=params,
879883
KS2ver=f'{Decimal(clustering_method.replace("kilosort", "")):.1f}',
880-
run_CatGT=True,
884+
run_CatGT=run_CatGT,
881885
)
882886
run_kilosort.run_modules()
883887
elif acq_software == "Open Ephys":
@@ -930,22 +934,22 @@ class Curation(dj.Manual):
930934
Clustering (foreign key): Clustering primary key.
931935
curation_id (foreign key, int): Unique curation ID.
932936
curation_time (datetime): Time when curation results are generated.
933-
curation_output_dir (varchar(255) ): Output directory of the curated results.
937+
curation_output_dir ( varchar(255) ): Output directory of the curated results.
934938
quality_control (bool): If True, this clustering result has undergone quality control.
935939
manual_curation (bool): If True, manual curation has been performed on this clustering result.
936-
curation_note (varchar(2000) ): Notes about the curation task.
940+
curation_note ( varchar(2000) ): Notes about the curation task.
937941
"""
938942

939943
definition = """
940944
# Manual curation procedure
941945
-> Clustering
942946
curation_id: int
943947
---
944-
curation_time: datetime # time of generation of this set of curated clustering results
948+
curation_time: datetime # time of generation of this set of curated clustering results
945949
curation_output_dir: varchar(255) # output directory of the curated results, relative to root data directory
946950
quality_control: bool # has this clustering result undergone quality control?
947951
manual_curation: bool # has manual curation been performed on this clustering result?
948-
curation_note='': varchar(2000)
952+
curation_note='': varchar(2000)
949953
"""
950954

951955
def create1_from_clustering_task(self, key, curation_note=""):
@@ -994,7 +998,7 @@ class CuratedClustering(dj.Imported):
994998

995999
definition = """
9961000
# Clustering results of a curation.
997-
-> Curation
1001+
-> Curation
9981002
"""
9991003

10001004
class Unit(dj.Part):
@@ -1021,7 +1025,7 @@ class Unit(dj.Part):
10211025
spike_count: int # how many spikes in this recording for this unit
10221026
spike_times: longblob # (s) spike times of this unit, relative to the start of the EphysRecording
10231027
spike_sites : longblob # array of electrode associated with each spike
1024-
spike_depths=null : longblob # (um) array of depths associated with each spike, relative to the (0, 0) of the probe
1028+
spike_depths=null : longblob # (um) array of depths associated with each spike, relative to the (0, 0) of the probe
10251029
"""
10261030

10271031
def make(self, key):
@@ -1149,8 +1153,8 @@ class Waveform(dj.Part):
11491153
# Spike waveforms and their mean across spikes for the given unit
11501154
-> master
11511155
-> CuratedClustering.Unit
1152-
-> probe.ElectrodeConfig.Electrode
1153-
---
1156+
-> probe.ElectrodeConfig.Electrode
1157+
---
11541158
waveform_mean: longblob # (uV) mean waveform across spikes of the given unit
11551159
waveforms=null: longblob # (uV) (spike x sample) waveforms of a sampling of spikes at the given electrode for the given unit
11561160
"""
@@ -1281,7 +1285,7 @@ class QualityMetrics(dj.Imported):
12811285

12821286
definition = """
12831287
# Clusters and waveforms metrics
1284-
-> CuratedClustering
1288+
-> CuratedClustering
12851289
"""
12861290

12871291
class Cluster(dj.Part):
@@ -1306,26 +1310,26 @@ class Cluster(dj.Part):
13061310
contamination_rate (float): Frequency of spikes in the refractory period.
13071311
"""
13081312

1309-
definition = """
1313+
definition = """
13101314
# Cluster metrics for a particular unit
13111315
-> master
13121316
-> CuratedClustering.Unit
13131317
---
1314-
firing_rate=null: float # (Hz) firing rate for a unit
1318+
firing_rate=null: float # (Hz) firing rate for a unit
13151319
snr=null: float # signal-to-noise ratio for a unit
13161320
presence_ratio=null: float # fraction of time in which spikes are present
13171321
isi_violation=null: float # rate of ISI violation as a fraction of overall rate
13181322
number_violation=null: int # total number of ISI violations
13191323
amplitude_cutoff=null: float # estimate of miss rate based on amplitude histogram
13201324
isolation_distance=null: float # distance to nearest cluster in Mahalanobis space
1321-
l_ratio=null: float #
1325+
l_ratio=null: float #
13221326
d_prime=null: float # Classification accuracy based on LDA
13231327
nn_hit_rate=null: float # Fraction of neighbors for target cluster that are also in target cluster
13241328
nn_miss_rate=null: float # Fraction of neighbors outside target cluster that are in target cluster
13251329
silhouette_score=null: float # Standard metric for cluster overlap
13261330
max_drift=null: float # Maximum change in spike depth throughout recording
1327-
cumulative_drift=null: float # Cumulative change in spike depth throughout recording
1328-
contamination_rate=null: float #
1331+
cumulative_drift=null: float # Cumulative change in spike depth throughout recording
1332+
contamination_rate=null: float #
13291333
"""
13301334

13311335
class Waveform(dj.Part):
@@ -1345,7 +1349,7 @@ class Waveform(dj.Part):
13451349
velocity_below (float) inverse velocity of waveform propagation from soma toward the bottom of the probe.
13461350
"""
13471351

1348-
definition = """
1352+
definition = """
13491353
# Waveform metrics for a particular unit
13501354
-> master
13511355
-> CuratedClustering.Unit

0 commit comments

Comments
 (0)