API reference

Pipeline

End-to-end pipeline: extract single-unit waveforms, engineer quality-metric features, and train/evaluate a classifier of sorted single-unit quality.

spikecurate.pipeline.run(recording, sorting_true, sorting, we_save_path: str, single_unit_ids: ndarray, good_unit_ids: ndarray, bad_unit_ids: ndarray, *, predict_unit_ids: ndarray | None = None, delta_time: float = 1.3, n_components_pca: int = 5, load_we_if_exists: bool = False, load_qm_if_exists: bool = False, extract_waveforms_kwargs: dict | None = None, job_kwargs: dict | None = None, eval_seeds: ndarray | None = None, eval_split_ratio: float = 0.75, eval_thresh: float = 0.8, eval_scale_data: bool = False) → dict[source]

Run the full single-unit quality curation pipeline.

Parameters:
  • recording – SpikeInterface RecordingExtractor.

  • sorting_true – SpikeInterface ground-truth SortingExtractor.

  • sorting – SpikeInterface SortingExtractor for the sorter under test (e.g. Kilosort4 output), containing all sorted units.

  • we_save_path – folder to save (or load) the WaveformExtractor for the single units selected via single_unit_ids.

  • single_unit_ids – unit ids in sorting classified as single units by the sorter (e.g. Kilosort4’s KSLabel == “good”).

  • good_unit_ids – subset of single_unit_ids labeled accurately-sorted (>80% agreement with ground truth) - positive class for training.

  • bad_unit_ids – subset of single_unit_ids labeled poorly-sorted - negative class for training. Every id in single_unit_ids must appear in exactly one of good_unit_ids/bad_unit_ids.

  • predict_unit_ids – unit ids (subset of single_unit_ids) to classify with the model trained on the full dataset - e.g. a handful of example units to demo the classifier on. Defaults to all of single_unit_ids.

  • delta_time – coincidence window (ms) used to compute sorted/ground-truth spike-train agreement scores.

  • n_components_pca – number of PCA components computed per channel, required for the silhouette quality metric.

  • load_qm_if_exists (load_we_if_exists /) – reuse a previously computed WaveformExtractor / quality-metrics extension at we_save_path instead of recomputing them.

  • extract_waveforms_kwargs – overrides for spikeinterface.extract_waveforms (ms_before, ms_after, max_spikes_per_unit, sparse, …).

  • job_kwargs – SpikeInterface parallelization kwargs (n_jobs, …).

  • eval_seeds – passed to FractionalLogisticClassifier.crossval_evaluate/train.

  • eval_split_ratio – passed to FractionalLogisticClassifier.crossval_evaluate/train.

  • eval_thresh – passed to FractionalLogisticClassifier.crossval_evaluate/train.

  • eval_scale_data – passed to FractionalLogisticClassifier.crossval_evaluate/train.

Returns:

“we”: the single-unit WaveformExtractor “data”: output of features.load_dataset (dataset, predictors, …) “feature_correlations”: pd.DataFrame, dataset.corr() “model”: the FractionalLogisticClassifier, trained on the full dataset “results”: crossval_evaluate() output (metric_data, metric_stats) “predictions”: model.predict() output for predict_unit_ids

Return type:

dict with keys

Classifier

Fractional-logistic classifier for single-unit sorting quality.

API is intentionally scikit-learn-flavored: train/predict, with fit state stored on the instance.

class spikecurate.model.FractionalLogisticClassifier(predictors, thresh: float = 0.8)[source]

Bases: object

GLM (binomial family) classifier predicting quality_label (1=good, 0=bad sorted single-unit) from a set of quality-metric predictors.

Usage:

model = FractionalLogisticClassifier(predictors) model.train(dataset) # fit on the full labeled dataset model.crossval_evaluate(dataset) # cross-validated precision/recall model.predict(features) # good/bad label for new units

property is_trained: bool

Whether train() has been called.

train(dataset: DataFrame, scale_data: bool = False, regularization: str = 'elastic_net', maxiter: int = 100, cnvrg_tol: float = 1e-10) → FractionalLogisticClassifier[source]

Fit on the full labeled dataset (with a regularized warm-start, then one unregularized refit to recover p-values - see statsmodels’ GLM.fit_regularized docs). Stores the fitted result (and, if scale_data, the fitted scaler) on the instance for later predict() calls.

Returns self, so this chains: model.train(dataset).predict(…).

predict(features: DataFrame) → DataFrame[source]

Classify units from their quality-metric features.

Parameters:

features – DataFrame indexed by unit id, with (at least) the columns in self.predictors. Any quality_label column is ignored - this is for units whose label you want predicted, labeled or not.

Returns:

probability: P(good unit) from the fitted GLM predicted_label: 1 (good) / 0 (bad), thresholded at self.thresh predicted_quality: “good” / “bad”

Return type:

DataFrame indexed like features, with columns

crossval_evaluate(dataset: DataFrame, seeds: ndarray | None = None, split_ratio: float = 0.75, scale_data: bool = False) → dict[source]

Cross-validated precision/recall over many random train/test splits (one per seed). Does not require - or affect - train(); each fold fits its own model on a subset of dataset.

score(dataset: DataFrame) → dict[source]

Precision/recall of the trained model against dataset’s own quality_label column (e.g. the training set, or a held-out set with known labels). Requires train() first.

Feature engineering

Quality-metric feature engineering for sorted single units.

spikecurate.features.get_agreement_scores(sorting_true, sorting, delta_time: float = 1.3) → DataFrame[source]

Agreement scores between ground-truth and sorted units.

spikecurate.features.compute_quality_metrics(we, load_qm_if_exists: bool = False, skip_pc_metrics: bool = True, job_kwargs: dict | None = None) → DataFrame[source]

Compute SpikeInterface quality metrics for every unit in we.

we must already have a principal_components extension computed (required for the silhouette metric) - see spikeinterface.postprocessing.compute_principal_components.

spikecurate.features.engineer_quality_features(single_unit_ids: ndarray, we, load_qm_if_exists: bool = False, job_kwargs: dict | None = None) → DataFrame[source]

Quality-metric feature matrix (rows=units, cols=metrics) for single_unit_ids.

spikecurate.features.build_labeled_dataset(qmetrics: DataFrame, good_unit_ids: ndarray, bad_unit_ids: ndarray, sorting, sorting_true, delta_time: float = 1.3) → tuple[DataFrame, Index][source]

Attach ground-truth agreement scores are not used as a feature here; build the (features, quality_label) dataset used to train the classifier.

quality_label: 1 for units in good_unit_ids, 0 for units in bad_unit_ids.

spikecurate.features.load_dataset(single_unit_ids: ndarray, good_unit_ids: ndarray, bad_unit_ids: ndarray, sorting, sorting_true, we, load_qm_if_exists: bool = False, delta_time: float = 1.3, job_kwargs: dict | None = None) → dict[source]

Engineer the full quality-metric feature dataset used to train/evaluate the single-unit quality classifier.

Returns a dict with keys: dataset, predictors, qmetrics.

Cross-validation

Cross-validated fitting/evaluation of a GLM (fractional logistic) classifier.

spikecurate.crossval.single_fold_metrics(model_formula: str, dataset: DataFrame, split_ratio: float = 0.75, seed: int = 0, thresh: float = 0.8, scale_data: bool = False) → dict[source]

Precision/recall of one random train/test split.

spikecurate.crossval.crossval_metrics(dataset: DataFrame, model_formula: str, split_ratio: float = 0.75, seeds: ndarray | None = None, thresh: float = 0.8, scale_data: bool = False) → ndarray[source]

Precision/recall across many random train/test splits (one per seed).

spikecurate.crossval.summarize_metrics(metric_data: ndarray) → dict[source]

Median, std, and 95% CI of half-width for precision and recall.

Plotting

Plotting helpers for classifier evaluation results.

spikecurate.plotting.plot_precision_recall(ax, metric_data)[source]

Strip plot of per-fold precision/recall with median +/- 95% CI.