{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Model Based Curation Tutorial\n", "#### This notebook provides a step-by-step guide on how to use machine learning classifier for curating spike sorted output into 'noise', multi-unit-activity' (MUA) and 'single-unit-activity' (SUA) using Spikeinterface. \n", "\n", "\n", "#### To use this, you should have already done spike sorting.\n", "#### In this notebook we will compute quality metrics and load machine model to predict curation labels for previously uncurated electrophysiology data.\n", "#### The classifier is trained on Neuropixels data from 11 mice recorded in V1,SC and ALM\n", "\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of cores set to: 23\n" ] } ], "source": [ "from pathlib import Path\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import spikeinterface as si\n", "import spikeinterface.extractors as se\n", "import spikeinterface.postprocessing as spost\n", "import spikeinterface.qualitymetrics as sqm\n", "import os\n", "from os import cpu_count\n", "import json\n", "# Set the number of CPU cores to be used globally - defaults to all cores -1\n", "n_cores = cpu_count() -1\n", "si.set_global_job_kwargs(n_jobs = n_cores)\n", "print(f\"Number of cores set to: {n_cores}\")\n", "\n", "# SET OUTPUT FOLDER\n", "output_folder = Path(r\"E:\\spikeinterface_outputs\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import spikeinterface\n", "print(spikeinterface.__version__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Load data " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First step: Loading the recording and sorting objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the tutorial, we are using simulated data to create recording and sorting objects." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "# Generate a synthetic recording\n", "recording = si.generate_recording(num_channels=50, sampling_frequency=30000.,\n", " durations=[30], set_probe=True)\n", "# load your recoring depeding on the acquistion software you used, for example:\n", "# recording = se.read_spikeglx(recording_path, stream_name='imec0.ap')\n", "\n", "# Generate a synthetic sorting\n", "sorting = si.generate_sorting(num_units=100, sampling_frequency=30000., durations=[30],\n", " firing_rates=15, refractory_period_ms=1.5)\n", "# load your sorting depeding on the which spike sorter you used, for example:\n", "# sorting = se.read_kilosort(folder_path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Second step: Create SortingAnalyzer " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SortingAnalyzer is a postprocessing module which is used to compute quality metrics and template metrics.\n", "To know more about it, please refer to : https://spikeinterface.readthedocs.io/en/latest/modules/postprocessing.html\n", "\n", "If you have already have WaveformExtractor from previous run, you can use it to create a SortingAnalyzer. \n", "Please refer to: https://spikeinterface.readthedocs.io/en/latest/tutorials/waveform_extractor_to_sorting_analyzer.html\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "analyzer = si.create_sorting_analyzer(sorting = sorting, recording = recording, sparse = True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Third step: Compute metrics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quality metrics serve as features for the machine learning model. We generate these metrics and use the model to predict labels based on them." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# Defines a function to compute all analyzer properties and quality metrics\n", "# Note: this can be a time-consuming step, especially computing PCA-based metrics for long recordings\n", "\n", "def compute_all_metrics(analyzer):\n", "\n", " # Compute required extensions for quality metrics\n", " analyzer.compute({\n", "\t'noise_levels': {},\n", "\t'random_spikes': {'max_spikes_per_unit': 1_000},\n", "\t'templates': {'ms_before': 1.5, 'ms_after': 3.5},\n", "\t'spike_amplitudes': {},\n", "\t'waveforms': {},\n", "\t'principal_components': {},\n", "\t'spike_locations': {},\n", "\t'unit_locations': {},\n", "\t})\n", "\n", " # Compute all available quality metrics\n", " analyzer.compute(\"quality_metrics\", metric_names = sqm.get_quality_metric_list() + sqm.get_quality_pca_metric_list())\n", " analyzer.compute(\"template_metrics\", metric_names = spost.get_template_metric_names())\n", "\n", "\t# Make metric dataframe\n", " quality_metrics = analyzer.extensions['quality_metrics'].data[\"metrics\"]\n", " template_metrics = analyzer.extensions['template_metrics'].data[\"metrics\"]\n", " calculated_metrics = pd.concat([quality_metrics, template_metrics], axis = 1)\n", "\n", " return calculated_metrics" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Compute all metrics\n", "metrics = compute_all_metrics(analyzer)\n", "metrics.index.name = 'cluster_id'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# save the analyzer\n", "analyzer.save_as(folder=output_folder / 'sorting_analyzer', format=\"binary_folder\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load a pretrained model from the Hugging Face Hub" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First we use noise vs neuron classifier" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "analyzer = si.load_sorting_analyzer(folder= output_folder / 'sorting_analyzer', format=\"binary_folder\")" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\jain\\Documents\\Github_extend\\spikeinterface\\src\\spikeinterface\\curation\\model_based_curation.py:353: UserWarning: No 'model_info.json' file found in folder. No metadata can be checked.\n", " warnings.warn(\"No 'model_info.json' file found in folder. No metadata can be checked.\")\n" ] } ], "source": [ "import skops.io as sio\n", "from huggingface_hub import hf_hub_download\n", "\n", "model_path = hf_hub_download(\"AnoushkaJain3/curation_machine_learning_models\", \"noise_neuron_model.skops\")\n", "untrusted_types = sio.get_untrusted_types(file=model_path)\n", "\n", "# Load pretrained noise/neural activity model and predict on unlabelled data\n", "from spikeinterface.curation.model_based_curation import auto_label_units\n", "\n", "label_conversion = {1: 'noise',0: 'neuron'}\n", "\n", "label_dict_noise = auto_label_units(sorting_analyzer = analyzer,\n", " repo_id = \"AnoushkaJain3/curation_machine_learning_models\",\n", " model_name= 'noise_neuron_model.skops',\n", " label_conversion=label_conversion,\n", " trusted= untrusted_types\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Second we use sua vs mua classifier" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\jain\\Documents\\Github_extend\\spikeinterface\\src\\spikeinterface\\curation\\model_based_curation.py:353: UserWarning: No 'model_info.json' file found in folder. No metadata can be checked.\n", " warnings.warn(\"No 'model_info.json' file found in folder. No metadata can be checked.\")\n" ] } ], "source": [ "model_path = hf_hub_download(\"AnoushkaJain3/curation_machine_learning_models\", \"sua_mua_model.skops\")\n", "untrusted_types = sio.get_untrusted_types(file=model_path)\n", "\n", "label_conversion = {1: 'sua',0: 'mua'}\n", "\n", "label_dict_sua= auto_label_units(sorting_analyzer = analyzer,\n", " repo_id = \"AnoushkaJain3/curation_machine_learning_models\",\n", " model_name= 'sua_mua_model.skops',\n", " label_conversion=label_conversion,\n", " trusted= untrusted_types\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Combine the predictions and probabilities from the two models" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{0: ('noise', 0.6136904761904761), 1: ('noise', 0.5225), 2: ('noise', 0.6099285714285715), 3: ('noise', 0.6553571428571427), 4: ('noise', 0.6146904761904761), 5: ('noise', 0.6320238095238095), 6: ('noise', 0.6036904761904761), 7: ('noise', 0.6036904761904761), 8: ('noise', 0.7125), 9: ('noise', 0.6025), 10: ('noise', 0.5891666666666666), 11: ('noise', 0.6911666666666666), 12: ('noise', 0.7113571428571429), 13: ('noise', 0.6826904761904761), 14: ('noise', 0.6248333333333334), 15: ('noise', 0.6308333333333335), 16: ('noise', 0.5936904761904762), 17: ('noise', 0.6193571428571428), 18: ('noise', 0.5803571428571428), 19: ('noise', 0.5836904761904761), 20: ('noise', 0.6753571428571428), 21: ('noise', 0.5824999999999999), 22: ('noise', 0.6633333333333333), 23: ('noise', 0.6806904761904762), 24: ('noise', 0.6986904761904762), 25: ('noise', 0.7125), 26: ('noise', 0.6036904761904761), 27: ('noise', 0.6633571428571429), 28: ('noise', 0.6958333333333333), 29: ('noise', 0.6136904761904761), 30: ('noise', 0.6093571428571428), 31: ('noise', 0.5338333333333334), 32: ('noise', 0.5577380952380951), 33: ('noise', 0.6425), 34: ('noise', 0.5836904761904761), 35: ('noise', 0.5910714285714286), 36: ('noise', 0.5458333333333333), 37: ('noise', 0.6320238095238095), 38: ('noise', 0.6353571428571428), 39: ('noise', 0.6591666666666667), 40: ('noise', 0.6453571428571427), 41: ('noise', 0.6508333333333334), 42: ('noise', 0.6420238095238094), 43: ('noise', 0.7020238095238095), 44: ('noise', 0.6541666666666666), 45: ('noise', 0.6625), 46: ('noise', 0.6986904761904762), 47: ('noise', 0.6886904761904762), 48: ('noise', 0.6236904761904761), 49: ('noise', 0.6008333333333333), 50: ('noise', 0.6786904761904762), 51: ('noise', 0.6276666666666667), 52: ('noise', 0.5775), 53: ('noise', 0.7025), 54: ('noise', 0.6225), 55: ('noise', 0.5825), 56: ('noise', 0.6708333333333334), 57: ('noise', 0.6203571428571428), 58: ('noise', 0.6753571428571428), 59: ('noise', 0.6653571428571428), 60: ('noise', 0.7226904761904762), 61: ('noise', 0.6225), 62: ('noise', 0.6753571428571428), 63: ('noise', 0.6548333333333334), 64: ('noise', 0.7358333333333333), 65: ('noise', 0.6593571428571429), 66: ('noise', 0.6600238095238095), 67: ('noise', 0.5974999999999999), 68: ('noise', 0.6036904761904761), 69: ('noise', 0.6386904761904761), 70: ('noise', 0.6886904761904762), 71: ('noise', 0.6403571428571427), 72: ('noise', 0.6586904761904762), 73: ('noise', 0.7053571428571429), 74: ('noise', 0.5651666666666667), 75: ('noise', 0.5941666666666666), 76: ('noise', 0.5975), 77: ('noise', 0.6986904761904762), 78: ('noise', 0.7058333333333333), 79: ('noise', 0.6830238095238096), 80: ('noise', 0.6886904761904762), 81: ('noise', 0.6796666666666666), 82: ('noise', 0.6886904761904762), 83: ('noise', 0.6141666666666666), 84: ('noise', 0.5966666666666667), 85: ('noise', 0.7021666666666667), 86: ('noise', 0.6608333333333334), 87: ('noise', 0.6926904761904763), 88: ('noise', 0.6720238095238095), 89: ('noise', 0.5858333333333333), 90: ('noise', 0.6425), 91: ('noise', 0.5908333333333333), 92: ('noise', 0.6175), 93: ('noise', 0.6170238095238095), 94: ('noise', 0.6308333333333332), 95: ('noise', 0.6041666666666666), 96: ('noise', 0.6236904761904761), 97: ('noise', 0.5891666666666666), 98: ('noise', 0.6248333333333334), 99: ('noise', 0.6805000000000001)}\n" ] } ], "source": [ "# Combine data\n", "decoder_output = {}\n", "\n", "for key, value in label_dict_noise.items():\n", " label, prob1 = value\n", " if label == 'noise':\n", " decoder_output[key] = (label, prob1) # Keep 'noise' and its probability\n", " else:\n", " sua_mua_label, prob2 = label_dict_sua[key] # Get 'sua' or 'mua' label and its probability\n", " decoder_output[key] = (sua_mua_label, prob2) # Replace 'neuron' with 'sua'/'mua' and their probabilities\n", "\n", "# Print the resulting combined data\n", "print(decoder_output)\n", "\n", "# Save the decoder output\n", "with open(output_folder / 'decoder_output.json', 'w') as f:\n", " json.dump(decoder_output, f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Assess model performance by comparing with human labels" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To assess the performance of the model relative to human labels, we can load (or here generate randomly) some labels, and plot a confusion matrix of predicted vs human labels for all clusters" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "image/png": "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BAYG6jMOIiIi08VVG0RERKQtQ9zZ8lXhqg0iIiLSGisSRERE+saKBBEREZE6ViSIiIj0zJTnSGicSDx+/Bhz587Fnj17kJmZCYVCobL/77//1llwREREZNw0TiT+85//4MCBA3jrrbfg6elplDehGmmfaegQiIzSj/A0dAhE/05c/vk/O3fuxPbt29GmTRt9xENERGR6THhoQ+PJlk5OTnB2dtZHLERERPSa0TiRmD17NmbMmIG8vDx9xENERGR6hI42I6Tx0Ma8efNw7do1uLu7o2bNmrCwsFDZf+rUKZ0FR0REZAq4auMZffr00UMYRERE9DrSOJGIjo7WRxxERESmixUJIiIi0hoTif8pLi7GggULsG7dOqSmpqKgoEBl/z///KOz4IiIiMi4abxqIyYmBvPnz8fgwYORk5ODqKgo9OvXD1KpFDNnztRDiERERK83idDNZow0TiQSExOxYsUKvPvuuzA3N8fQoUPx7bffYsaMGTh27Jg+YiQiInq9CYluNiOkcSKRnp4OX19fAICtrS1ycnIAAD169MD27dt1Gx0REZEpMOH7SGicSFSrVg1paWkAgNq1a+OXX34BAJw4cQIymUy30REREZFR0ziR6Nu3L/bs2QMAmDhxIj7++GPUrVsXYWFhGD16tM4DJCIiet2Z8hwJjVdtzJ07V/n14MGDUaNGDRw9ehR169ZFz549dRocERGRSTDSJEAXXvo+EgEBAQgICNBFLERERPSa0SqRuHv3Lg4fPozMzEwoFAqVfZMmTdJJYERERKbCWIcldEHjRCIhIQFjx46FpaUlXFxcIJH8bzmKRCJhIkFERPQ8JhL/8/HHH2PGjBmYPn06pFKN52oSERGRCdE4kcjLy8OQIUOYRBAREVWUCVckNM4GxowZg6SkJH3EQkREZJK4/PMZsbGx6NGjB3bt2gVfX19YWFio7J8/f77OgiMiIiLjplUisXv3btSvXx8A1CZbEhER0b+HxonEvHnzsGrVKowcOVIP4RAREZkgIx2W0AWNEwmZTIY2bdroIxYiIiKTZKzzG3RB48mWkydPxuLFi/URCxEREb1mNK5I/P7779i7dy+2bduGRo0aqU223Lhxo86CIyIiMgkmXJHQOJFwdHREv3799BELERGRaWIi8T/x8fH6iIOIiIheQy/99E8iIiIqnylPttQ4kfD29i73fhF/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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from sklearn.metrics import confusion_matrix, balanced_accuracy_score\n", "import seaborn as sns\n", "\n", "# Use 'ground-truth' labels to check prediction accuracy\n", "# These are assigned randomly here but you could load these from phy 'cluster_group.tsv', from the 'quality' property of the sorting, or similar\n", "human_labels = np.random.choice(list(label_conversion.values()), analyzer.get_num_units())\n", "\n", "# Get labels from phy sorting (if loaded) using:\n", "# human_labels = unlabelled_analyzer.sorting.get_property('quality')\n", "\n", "predictions = analyzer.sorting.get_property('label_prediction')\n", "\n", "conf_matrix = confusion_matrix(human_labels, predictions)\n", "\n", "# Calculate balanced accuracy for the confusion matrix\n", "balanced_accuracy = balanced_accuracy_score(human_labels, predictions)\n", "\n", "sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='viridis')\n", "plt.xlabel('Predicted Label')\n", "plt.ylabel('Human Label')\n", "plt.xticks(ticks = [0.5, 1.5], labels = list(label_conversion.values()))\n", "plt.yticks(ticks = [0.5, 1.5], labels = list(label_conversion.values()))\n", "plt.title('Predicted vs Human Label')\n", "plt.suptitle(f\"Balanced Accuracy: {balanced_accuracy}\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also see how the model's confidence relates to the probability that the model label matches the human label\n", "\n", "This could be used to set a threshold above which you might accept the model's classification, and only manually curate those which it is less sure of" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "image/png": "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y8sL69evt0SMREREVITJHqb5+eefsX79erRs2RKDBw9Gs2bNUKVKFVSsWBEbNmxAv379LBEnERERFVGye0YSExPh6+sLIHt+SGJiIgCgadOmOHTokHmjIyIioiJPdjLi6+uL6OhoAIC/vz82b94MILvHJOfBeURERESmkp2MDB48GOfPnwcATJo0CUuXLoVGo8F7772H999/3+wBEhERUdEme87Ie++9J33ftm1bXL58GadPn0aVKlVQq1YtswZHRERERZ/snpEnVaxYET169ECpUqXw1ltvmSMmIiIiKkaeORnJkZCQgNWrV5vrdERERFRMmC0ZISIiIioIJiNERERkVUxGiIiIyKpMXk3To0ePfN9PSkp61liIiIioGDI5GXFxcXnq+wMGDHjmgIiIiKh4MTkZWbt2rSXjICIiomKKc0aIiIjIqpiMEBERkVUxGSEiIiKrYjJCREREVsVkhIiIiKxK9lN7ASAyMhL79+9HfHw89Hq9wXtTp041S2BERERUPMhORr755hu88847KFOmDMqWLQuFQiG9p1AomIwQERGRLLKTkRkzZmDmzJn44IMPLBEPERERFTOy54zcv38fb7zxhiViISIiomJIdjLyxhtvYO/evZaIhYiIiIoh2cM0VapUwZQpU3DixAkEBARApVIZvD9mzBizBUdERERFn+xkZOXKlXBycsLBgwdx8OBBg/cUCgWTESIiIpJFdjISHR1tiTiIiIiomOKmZ0RERGRVBdr07NatW9i+fTtiYmKQmZlp8N6CBQvMEhgREREVD7KTkYiICLz22mvw9fXF5cuXUbNmTVy/fh1CCNSrV88SMRIREVERJnuYZvLkyZgwYQIuXLgAjUaDbdu24ebNm2jRogX3HyEiIiLZZCcjly5dwoABAwAAtra2ePToEZycnPDpp59izpw5Zg+QiIiIijbZyYijo6M0T8TT0xNRUVHSe/fu3TNfZERERFQsyJ4z8sorr+DIkSOoVq0aOnbsiPHjx+PChQsICwvDK6+8YokYiYiIqAiTnYwsWLAAKSkpAIDp06cjJSUFmzZtQtWqVbmShoiIiGSTnYz4+vpK3zs6OmLFihVmDYiIiIiKlwLtM5IjJSUFer3eoMzZ2fmZAiIiIqLiRfYE1ujoaHTq1AmOjo5wcXFByZIlUbJkSbi6uqJkyZKWiJGIiIiKMNk9I2+++SaEEFizZg08PDygUCgsERcREREVE7KTkfPnz+P06dPw8/OzRDxERERUzMgepnn55Zdx8+ZNS8RCRERExZDsnpFVq1bh7bffxu3bt1GzZk2oVCqD92vVqmW24IiIiKjok52M3L17F1FRURg8eLBUplAoIISAQqGATqcza4BERERUtMlORoYMGYK6devi+++/5wRWIiIiemayk5EbN25g+/btqFKliiXiISIiomJG9gTW1q1b4/z585aIhYiIiIoh2T0jXbp0wXvvvYcLFy4gICDAaALra6+9ZrbgiIiIqOiTnYy8/fbbAIBPP/3U6D1OYCUiIiK5ZCcjTz6LhoiIiOhZyJ4zQkRERGROsntGchueedzUqVMLHAwREREVP7KTkR9++MHgtVarRXR0NGxtbVG5cmUmI0RERCSL7GTk7NmzRmXJyckYNGgQunfvbpagiIiIqPgwy5wRZ2dnTJ8+HVOmTDHH6YiIiKgYMdsE1gcPHuDBgwfmOh0REREVE7KHab788kuD10II3LlzB99++y06dOhgtsCIiIioeJCdjCxcuNDgtY2NDdzc3DBw4EBMnjzZbIERERFR8SA7GYmOjrZEHERERFRMcdMzIiIisiqTe0Z69OhhUr2wsLACB0NERETFj8nJiIuLi8HrjRs3okuXLihRooTZgyIiIqLiw+RkZO3atQavt27dirlz58LX19fsQREREVHxwTkjREREZFVMRoiIiMiqmIwQERGRVZk8Z2T79u0Gr/V6PSIiInDx4kWD8tdee808kREREVGxYHIy0q1bN6OyESNGGLxWKBTQ6XTPHBQREREVHyYP0+j1+qd+FSQRWbp0KXx8fKDRaNCoUSOcPHky3/pJSUkYNWoUPD09oVar8dJLL2HXrl2yr0tERETPB9nbwZvTpk2bEBISghUrVqBRo0ZYtGgRgoKCcOXKFbi7uxvVz8zMRLt27eDu7o6tW7eiXLlyuHHjBlxdXQs/eCIiIjILqyYjCxYswPDhwzF48GAAwIoVK7Bz506sWbMGkyZNMqq/Zs0aJCYm4tixY1CpVAAAHx+fwgyZiIiewc4/7uDvuIfoUa8cKpZ2tHY49JywWjKSmZmJ06dPGzzp18bGBm3btsXx48dzPWb79u0IDAzEqFGj8NNPP8HNzQ19+/bFBx98AKVSmesxGRkZyMjIkF4nJycDALRaLbRa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RZjsYZr58+dDoVBgwIAByMrKAgCoVCq88847+Pzzz80eIBERERVtspMROzs7LF68GLNnz0ZUVBQAoHLlynBwcDB7cERERFT0FWifEQBwcHCAq6ur9D0RERFRQcieM5KVlYUpU6bAxcUFPj4+8PHxgYuLCz7++GNotVpLxEhERERFmOyekXfffRdhYWGYO3cuAgMDAQDHjx/HJ598goSEBCxfvtzsQRIREVHRJTsZ2bhxI0JDQ9GhQweprFatWvD29kafPn2YjBAREZEssodp1Go1fHx8jMorVaoEOzs7c8RERERExYjsZGT06NH47LPPkJGRIZVlZGRg5syZGD16tFmDIyIioqJP9jDN2bNnERERgfLly6N27doAgPPnzyMzMxNt2rRBjx49pLphYWHmi5SIiIiKJNnJiKurK3r27GlQ5u3tbbaAiIiIqHiRnYysXbvWEnEQERFRMVXgTc/u3r2LK1euAAD8/Pzg5uZmtqCIiIio+JA9gTU1NRVDhgyBp6cnmjdvjubNm8PLywtDhw5FWlqaJWIkIiKiIkx2MhISEoKDBw/i559/RlJSEpKSkvDTTz/h4MGDGD9+vCViJCIioiJM9jDNtm3bsHXrVrRs2VIq69ixI+zt7dGrVy9uekZERESyyO4ZSUtLg4eHh1G5u7s7h2mIiIhINtnJSGBgIKZNm4b09HSp7NGjR5g+fbr0rBoiIiIiU8keplm0aBHat29vtOmZRqPBnj17zB4gERERFW2yk5GAgABERkZiw4YNuHz5MgCgT58+6NevH+zt7c0eIBERERVtspIRrVYLf39/7NixA8OHD7dUTERERFSMyJozolKpDOaKEBERET0r2RNYR40ahTlz5iArK8sS8RAREVExI3vOyO+//46IiAjs3bsXAQEBcHR0NHifT+olIiIiOczy1F4iIiKignountq7dOlSzJs3D7GxsahduzaWLFmChg0b5lr3m2++wfr163Hx4kUAQP369TFr1qw86xMREdHzzeQ5I3q9HnPmzEGTJk3w8ssvY9KkSXj06NEzB7Bp0yaEhIRg2rRpOHPmDGrXro2goCDEx8fnWv/AgQPo06cP9u/fj+PHj8Pb2xuvvvoqbt++/cyxEBERUeEzORmZOXMmPvzwQzg5OaFcuXJYvHgxRo0a9cwBLFiwAMOHD8fgwYNRvXp1rFixAg4ODlizZk2u9Tds2ICRI0eiTp068Pf3x6pVq6DX6xEREfHMsRAREVHhM3mYZv369Vi2bBlGjBgBANi3bx86deqEVatWwcZG9qIcAEBmZiZOnz6NyZMnS2U2NjZo27Ytjh8/btI50tLSoNVqUapUqVzfz8jIQEZGhvQ6OTkZQPaeKVqttkBxkzw57cz2Ljxs88LHNi98bPPCZ6m2NjkZiYmJQceOHaXXbdu2hUKhwD///IPy5csX6OL37t2DTqczevCeh4eHtLvr03zwwQfw8vJC27Ztc31/9uzZmD59ulH5/v374eDgID9oKrDw8HBrh1DssM0LH9u88LHNC4+lHohrcjKSlZUFjUZjUKZSqayakX7++ecIDQ3FgQMHjGLLMXnyZISEhEivk5OT4e3tjVatWqF06dKFFWqxptVqER4ejnbt2kGlUlk7nGKBbV742OaFj21e+BISEixyXpOTESEEBg0aBLVaLZWlp6fj7bffNthrRM4+I2XKlIFSqURcXJxBeVxcHMqWLZvvsfPnz8fnn3+Offv2oVatWnnWU6vVBjHnUKlUvHkLGdu88LHNCx/bvPCxzQuPpdrZ5GRk4MCBRmVvvvnmM13czs4O9evXR0REBLp16wYA0mTU0aNH53nc3LlzMXPmTOzZswcNGjR4phiIiIjIukxORiyxvwgAhISEYODAgWjQoAEaNmyIRYsWITU1FYMHDwYADBgwAOXKlcPs2bMBAHPmzMHUqVOxceNG+Pj4IDY2FgDg5OQEJycni8RIREREliN70zNzCw4Oxt27dzF16lTExsaiTp062L17tzSpNSYmxmC1zvLly5GZmYnXX3/d4DzTpk3DJ598UpihExERkRlYPRkBgNGjR+c5LHPgwAGD19evX7d8QERERFRoCrZBCBEREZGZMBkhIiIiq2IyQkRERFbFZISIiIisiskIERERWRWTESIiIrIqJiNERERkVUxGiIiIyKqYjBAREZFVMRkhIiIiq2IyQkRERFbFZISIiIisiskIERERWRWTESIiIrIqJiNERERkVUxGiIiIyKqYjBAREZFVMRkhIiIiq2IyQkRERFbFZISIiIisiskIERERWRWTESIiIrIqJiNERERkVUxGiIiIyKqYjBAREZFVMRkhIiIiq2IyQkRERFbFZISIiIisiskIERERWRWTESIiIrIqJiNERERkVUxGiIiI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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "confidences = analyzer.sorting.get_property('label_confidence')\n", "\n", "# Make dataframe of human label, model label, and confidence\n", "label_df = pd.DataFrame(data = {\n", " 'phy_label': human_labels,\n", " 'decoder_label': predictions,\n", " 'confidence': confidences},\n", " index = decoder_output.keys())\n", "\n", "# Calculate the proportion of agreed labels by confidence decile\n", "label_df['model_x_human_agreement'] = label_df['phy_label'] == label_df['decoder_label']\n", "\n", "def calculate_moving_avg(label_df, confidence_label, window_size):\n", "\n", " label_df[f'{confidence_label}_decile'] = pd.cut(label_df[confidence_label], 10, labels=False, duplicates='drop')\n", " # Group by decile and calculate the proportion of correct labels (agreement)\n", " p_label_grouped = label_df.groupby(f'{confidence_label}_decile')['model_x_human_agreement'].mean()\n", " # Convert decile to range 0-1\n", " p_label_grouped.index = p_label_grouped.index / 10\n", " # Sort the DataFrame by confidence scores\n", " label_df_sorted = label_df.sort_values(by=confidence_label)\n", "\n", " p_label_moving_avg = label_df_sorted['model_x_human_agreement'].rolling(window=window_size).mean()\n", "\n", " return label_df_sorted[confidence_label], p_label_moving_avg\n", "\n", "p_agreement_sorted, p_agreement_moving_avg = calculate_moving_avg(label_df, 'confidence', 20)\n", "\n", "# Plot the moving average of agreement\n", "plt.figure(figsize=(6, 6))\n", "plt.plot(p_agreement_sorted, p_agreement_moving_avg, label = 'Moving Average')\n", "plt.axhline(y=1/len(np.unique(predictions)), color='black', linestyle='--', label='Chance')\n", "plt.xlabel('Confidence'); plt.xlim(0.5, 1)\n", "plt.ylabel('Proportion Agreement with Human Label'); plt.ylim(0, 1)\n", "plt.title('Agreement vs Confidence (Moving Average)')\n", "plt.legend(); plt.grid(True); plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# If you only have metrics files" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you don't have access to to sorting analyzer for a particular recording, you can still use the pretrained model to predict on a new data" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Load your files\n", "\n", "data_directory = Path(r\"Y:\\invivo_ephys\\Neuropixels\")\n", "recording_folder = '2838_20240620'\n", "metrics_folder = data_directory / recording_folder / 'metrics'\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# load quality metrics and template metrics csv files\n", "\n", "quality_metrics = pd.read_csv(metrics_folder / 'quality_metrics.csv')\n", "template_metrics = pd.read_csv(metrics_folder / 'template_metrics.csv')\n", "\n", "# merge them based on the index\n", "metrics = pd.merge(quality_metrics, template_metrics, left_index=True, right_index=True)\n", "\n", "# Replace infinities with NaNs and convert to float32\n", "metrics_dataframe = metrics.applymap(lambda x: np.nan if np.isinf(x) else x).astype(\"float32\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First we use noise vs neuron classifier" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import skops.io as sio\n", "from huggingface_hub import hf_hub_download\n", "\n", "json_path = hf_hub_download(repo_id=\"AnoushkaJain3/curation_machine_learning_models\", filename=\"features_sequence.json\")\n", "\n", "# Load the JSON file\n", "with open(json_path, 'r') as file:\n", " column_list = json.load(file)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "model_path_noise = hf_hub_download(repo_id=\"AnoushkaJain3/curation_test\", filename=\"noise_neuron_model.skops\")\n", "\n", "# Get the untrusted types from the skops file\n", "untrusted_types = sio.get_untrusted_types(file = model_path_noise)\n", "clf = sio.load(model_path_noise, trusted=untrusted_types)\n", "\n", "# Perform prediction\n", "noise_predictions = clf.predict(metrics_dataframe[column_list])\n", "noise_probabs = clf.predict_proba(metrics_dataframe[column_list])\n", "\n", "metrics_dataframe['noise_label'] = noise_predictions\n", "metrics_dataframe['noise_probs'] = noise_probabs[:,1]\n", "metrics_dataframe['noise_label'] = metrics_dataframe['noise_label'].map({1: 'noise', 0: 'neural'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First we use sua vs mua classifier" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "model_path_sua = hf_hub_download(repo_id=\"AnoushkaJain3/curation_test\", filename=\"sua_mua_model.skops\")\n", "\n", "# Get the untrusted types from the skops file\n", "untrusted_types = sio.get_untrusted_types(file = model_path_sua)\n", "clf = sio.load(model_path_sua, trusted=untrusted_types)\n", "\n", "# Perform prediction\n", "sua_predictions = clf.predict(metrics_dataframe[column_list])\n", "sua_probabs = clf.predict_proba(metrics_dataframe[column_list])\n", "metrics_dataframe['sua_label'] = sua_predictions\n", "metrics_dataframe['sua_probs'] = sua_probabs[:,1]\n", "metrics_dataframe['sua_label'] = metrics_dataframe['sua_label'].map({1 : 'sua', 0 :'mua'})" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Combine the predictions and probabilities from the two models\n", "\n", "# Create the 'decoder_label' column\n", "metrics_dataframe['decoder_label'] = metrics_dataframe.apply(lambda row: row['noise_label'] if row['noise_label'] == 'noise' else row['sua_label'], axis=1)\n", " \n", "# Create the 'decoder_probs' column\n", "metrics_dataframe['decoder_probs'] = metrics_dataframe.apply(lambda row: row['noise_probs'] if row['decoder_label'] == 'noise' else row['sua_probs'], axis=1)\n", "\n", "# Update 'decoder_probs' for 'mua' values\n", "metrics_dataframe.loc[metrics_dataframe['decoder_label'] == 'mua', 'decoder_probs'] = 1 - metrics_dataframe['decoder_probs']" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "metrics_dataframe['decoder_label']" ] } ], "metadata": { "kernelspec": { "display_name": "spike_interface", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.16" } }, "nbformat": 4, "nbformat_minor": 2 }