@@ -5,6 +5,10 @@ Comparison module
55SpikeInterface has a :py:mod: `~spikeinterface.comparison ` module, which contains functions and tools to compare
66spike trains and templates (useful for tracking units over multiple sessions).
77
8+ .. note ::
9+
10+ In version 0.102.0 the benchmark part of comparison has moved in the new :py:mod: `~spikeinterface.benchmark `
11+
812In addition, the :py:mod: `~spikeinterface.comparison ` module contains advanced benchmarking tools to evaluate
913the effects of spike collisions on spike sorting results, and to construct hybrid recordings for comparison.
1014
@@ -242,135 +246,6 @@ An **over-merged** unit has a relatively high agreement (>= 0.2 by default) for
242246
243247 cmp_gt_HS.get_redundant_units(redundant_score = 0.2 )
244248
245-
246- **Example: compare many sorters with a Ground Truth Study **
247-
248- We also have a high level class to compare many sorters against ground truth:
249- :py:func: `~spikeinterface.comparison.GroundTruthStudy() `
250-
251- A study is a systematic performance comparison of several ground truth recordings with several sorters or several cases
252- like the different parameter sets.
253-
254- The study class proposes high-level tool functions to run many ground truth comparisons with many "cases"
255- on many recordings and then collect and aggregate results in an easy way.
256-
257- The all mechanism is based on an intrinsic organization into a "study_folder" with several subfolders:
258-
259- * datasets: contains ground truth datasets
260- * sorters : contains outputs of sorters
261- * sortings: contains light copy of all sorting
262- * metrics: contains metrics
263- * ...
264-
265-
266- .. code-block :: python
267-
268- import matplotlib.pyplot as plt
269- import seaborn as sns
270-
271- import spikeinterface.extractors as se
272- import spikeinterface.widgets as sw
273- from spikeinterface.comparison import GroundTruthStudy
274-
275-
276- # generate 2 simulated datasets (could be also mearec files)
277- rec0, gt_sorting0 = generate_ground_truth_recording(num_channels = 4 , durations = [30 .], seed = 42 )
278- rec1, gt_sorting1 = generate_ground_truth_recording(num_channels = 4 , durations = [30 .], seed = 91 )
279-
280- datasets = {
281- " toy0" : (rec0, gt_sorting0),
282- " toy1" : (rec1, gt_sorting1),
283- }
284-
285- # define some "cases" here we want to test tridesclous2 on 2 datasets and spykingcircus2 on one dataset
286- # so it is a two level study (sorter_name, dataset)
287- # this could be more complicated like (sorter_name, dataset, params)
288- cases = {
289- (" tdc2" , " toy0" ): {
290- " label" : " tridesclous2 on tetrode0" ,
291- " dataset" : " toy0" ,
292- " run_sorter_params" : {
293- " sorter_name" : " tridesclous2" ,
294- },
295- },
296- (" tdc2" , " toy1" ): {
297- " label" : " tridesclous2 on tetrode1" ,
298- " dataset" : " toy1" ,
299- " run_sorter_params" : {
300- " sorter_name" : " tridesclous2" ,
301- },
302- },
303-
304- (" sc" , " toy0" ): {
305- " label" : " spykingcircus2 on tetrode0" ,
306- " dataset" : " toy0" ,
307- " run_sorter_params" : {
308- " sorter_name" : " spykingcircus" ,
309- " docker_image" : True
310- },
311- },
312- }
313- # this initilizes a folder
314- study = GroundTruthStudy.create(study_folder = study_folder, datasets = datasets, cases = cases,
315- levels = [" sorter_name" , " dataset" ])
316-
317-
318- # all cases in one function
319- study.run_sorters()
320-
321- # Collect comparisons
322- #
323- # You can collect in one shot all results and run the
324- # GroundTruthComparison on it.
325- # So you can have fine access to all individual results.
326- #
327- # Note: use exhaustive_gt=True when you know exactly how many
328- # units in the ground truth (for synthetic datasets)
329-
330- # run all comparisons and loop over the results
331- study.run_comparisons(exhaustive_gt = True )
332- for key, comp in study.comparisons.items():
333- print (' *' * 10 )
334- print (key)
335- # raw counting of tp/fp/...
336- print (comp.count_score)
337- # summary
338- comp.print_summary()
339- perf_unit = comp.get_performance(method = ' by_unit' )
340- perf_avg = comp.get_performance(method = ' pooled_with_average' )
341- # some plots
342- m = comp.get_confusion_matrix()
343- w_comp = sw.plot_agreement_matrix(sorting_comparison = comp)
344-
345- # Collect synthetic dataframes and display
346- # As shown previously, the performance is returned as a pandas dataframe.
347- # The spikeinterface.comparison.get_performance_by_unit() function,
348- # gathers all the outputs in the study folder and merges them into a single dataframe.
349- # Same idea for spikeinterface.comparison.get_count_units()
350-
351- # this is a dataframe
352- perfs = study.get_performance_by_unit()
353-
354- # this is a dataframe
355- unit_counts = study.get_count_units()
356-
357- # we can also access run times
358- run_times = study.get_run_times()
359- print (run_times)
360-
361- # Easy plotting with seaborn
362- fig1, ax1 = plt.subplots()
363- sns.barplot(data = run_times, x = ' rec_name' , y = ' run_time' , hue = ' sorter_name' , ax = ax1)
364- ax1.set_title(' Run times' )
365-
366- # #############################################################################
367-
368- fig2, ax2 = plt.subplots()
369- sns.swarmplot(data = perfs, x = ' sorter_name' , y = ' recall' , hue = ' rec_name' , ax = ax2)
370- ax2.set_title(' Recall' )
371- ax2.set_ylim(- 0.1 , 1.1 )
372-
373-
374249 .. _symmetric :
375250
3762512. Compare the output of two spike sorters (symmetric comparison)
@@ -540,32 +415,4 @@ sorting analyzers from day 1 (:code:`analyzer_day1`) to day 5 (:code:`analyzer_d
540415
541416
542417
543- Benchmark spike collisions
544- --------------------------
545-
546- SpikeInterface also has a specific toolset to benchmark how well sorters are at recovering spikes in "collision".
547-
548- We have three classes to handle collision-specific comparisons, and also to quantify the effects on correlogram
549- estimation:
550-
551- * :py:class: `~spikeinterface.comparison.CollisionGTComparison `
552- * :py:class: `~spikeinterface.comparison.CorrelogramGTComparison `
553- * :py:class: `~spikeinterface.comparison.CollisionGTStudy `
554- * :py:class: `~spikeinterface.comparison.CorrelogramGTStudy `
555-
556- For more details, checkout the following paper:
557-
558- `Samuel Garcia, Alessio P. Buccino and Pierre Yger. "How Do Spike Collisions Affect Spike Sorting Performance?" <https://doi.org/10.1523/ENEURO.0105-22.2022 >`_
559-
560-
561- Hybrid recording
562- ----------------
563-
564- To benchmark spike sorting results, we need ground-truth spiking activity.
565- This can be generated with artificial simulations, e.g., using `MEArec <https://mearec.readthedocs.io/ >`_, or
566- alternatively by generating so-called "hybrid" recordings.
567-
568- The :py:mod: `~spikeinterface.comparison ` module includes functions to generate such "hybrid" recordings:
569418
570- * :py:func: `~spikeinterface.comparison.create_hybrid_units_recording `: add new units to an existing recording
571- * :py:func: `~spikeinterface.comparison.create_hybrid_spikes_recording `: add new spikes to existing units in a recording
0 commit comments