API for module: spikeinterface.comparison

Class: CollisionGTComparison
  Docstring:
    This class is an extension of GroundTruthComparison by focusing to benchmark spike in collision.
    
    This class needs maintenance and need a bit of refactoring.
    
    Parameters
    ----------
    gt_sorting : BaseSorting
        The first sorting for the comparison
    collision_lag : float, default 2.0
        Collision lag in ms.
    tested_sorting : BaseSorting
        The second sorting for the comparison
    nbins : int, default : 11
        Number of collision bins
    **kwargs : dict
        Keyword arguments for `GroundTruthComparison`
  __init__(self, gt_sorting, tested_sorting, collision_lag=2.0, nbins=11, **kwargs)
  Method: compute_all_pair_collision_bins(self)
    Docstring:
      None
  Method: compute_collision_by_similarity(self, similarity_matrix, unit_ids=None, good_only=False, min_accuracy=0.9)
    Docstring:
      None
  Method: detect_gt_collision(self)
    Docstring:
      None
  Method: get_label_count_per_collision_bins(self, gt_unit_id1, gt_unit_id2, bins)
    Docstring:
      None
  Method: get_label_for_collision(self, gt_unit_id1, gt_unit_id2)
    Docstring:
      None

Class: CorrelogramGTComparison
  Docstring:
    This class is an extension of GroundTruthComparison by focusing
    to benchmark correlation reconstruction.
    
    This class needs maintenance and need a bit of refactoring.
    
    Parameters
    ----------
    gt_sorting : BaseSorting
        The first sorting for the comparison
    tested_sorting : BaseSorting
        The second sorting for the comparison
    bin_ms : float, default: 1.0
        Size of bin for correlograms
    window_ms : float, default: 100.0
        The window around the spike to compute the correlation in ms.
    well_detected_score : float, default: 0.8
        Agreement score above which units are well detected
    **kwargs : dict
        Keyword arguments for `GroundTruthComparison`
  __init__(self, gt_sorting, tested_sorting, window_ms=100.0, bin_ms=1.0, well_detected_score=0.8, **kwargs)
  Method: compute_correlogram_by_similarity(self, similarity_matrix, window_ms=None)
    Docstring:
      None
  Method: compute_correlograms(self)
    Docstring:
      None
  Method: error(self, window_ms=None)
    Docstring:
      None

Class: GroundTruthComparison
  Docstring:
    Compares a sorter to a ground truth.
    
    This class can:
      * compute a "match between gt_sorting and tested_sorting
      * compute optionally the score label (TP, FN, CL, FP) for each spike
      * count by unit of GT the total of each (TP, FN, CL, FP) into a Dataframe
        GroundTruthComparison.count
      * compute the confusion matrix .get_confusion_matrix()
      * compute some performance metric with several strategy based on
        the count score by unit
      * count well detected units
      * count false positive detected units
      * count redundant units
      * count overmerged units
      * summary all this
    
    
    Parameters
    ----------
    gt_sorting : BaseSorting
        The first sorting for the comparison
    tested_sorting : BaseSorting
        The second sorting for the comparison
    gt_name : str, default: None
        The name of sorter 1
    tested_name : : str, default: None
        The name of sorter 2
    delta_time : float, default: 0.4
        Number of ms to consider coincident spikes.
        This means that two spikes are considered simultaneous if they are within `delta_time` of each other or
        mathematically abs(spike1_time - spike2_time) <= delta_time.
    match_score : float, default: 0.5
        Minimum agreement score to match units
    chance_score : float, default: 0.1
        Minimum agreement score to for a possible match
    redundant_score : float, default: 0.2
        Agreement score above which units are redundant
    overmerged_score : float, default: 0.2
        Agreement score above which units can be overmerged
    well_detected_score : float, default: 0.8
        Agreement score above which units are well detected
    exhaustive_gt : bool, default: False
        Tell if the ground true is "exhaustive" or not. In other world if the
        GT have all possible units. It allows more performance measurement.
        For instance, MEArec simulated dataset have exhaustive_gt=True
    match_mode : "hungarian" | "best", default: "hungarian"
        The method to match units
    agreement_method : "count" | "distance", default: "count"
        The method to compute agreement scores. The "count" method computes agreement scores from spike counts.
        The "distance" method computes agreement scores from spike time distance functions.
    compute_labels : bool, default: False
        If True, labels are computed at instantiation
    compute_misclassifications : bool, default: False
        If True, misclassifications are computed at instantiation
    verbose : bool, default: False
        If True, output is verbose
    
    Returns
    -------
    sorting_comparison : SortingComparison
        The SortingComparison object
  __init__(self, gt_sorting: 'BaseSorting', tested_sorting: 'BaseSorting', gt_name: 'str | None' = None, tested_name: 'str | None' = None, delta_time: 'float' = 0.4, match_score: 'float' = 0.5, well_detected_score: 'float' = 0.8, redundant_score: 'float' = 0.2, overmerged_score: 'float' = 0.2, chance_score: 'float' = 0.1, exhaustive_gt: 'bool' = False, agreement_method: 'str' = 'count', match_mode: 'str' = 'hungarian', compute_labels: 'bool' = False, compute_misclassifications: 'bool' = False, verbose: 'bool' = False)
  Method: count_bad_units(self)
    Docstring:
      See get_bad_units
  Method: count_false_positive_units(self, redundant_score=None)
    Docstring:
      See get_false_positive_units().
      
      Parameters
      ----------
      redundant_score : float | None, default: None
          The agreement score below which tested units
          are counted as "false positive"" (and not "redundant").
  Method: count_overmerged_units(self, overmerged_score=None)
    Docstring:
      See get_overmerged_units().
      
      Parameters
      ----------
      overmerged_score : float, default: None
          Tested units with 2 or more agreement scores above "overmerged_score"
          are counted as "overmerged".
  Method: count_redundant_units(self, redundant_score=None)
    Docstring:
      See get_redundant_units().
      
       Parameters
       ----------
       redundant_score : float, default: None
           The agreement score below which tested units
           are counted as "false positive"" (and not "redundant").
  Method: count_units_categories(self, well_detected_score=None, overmerged_score=None, redundant_score=None)
    Docstring:
      None
  Method: count_well_detected_units(self, well_detected_score)
    Docstring:
      Count how many well detected units.
      kwargs are the same as get_well_detected_units.
      
      Parameters
      ----------
      well_detected_score : float, default: None
          The agreement score above which tested units
          are counted as "well detected".
  Method: get_bad_units(self)
    Docstring:
      Return units list of "bad units".
      
      "bad units" are defined as units in tested that are not
      in the best match list of GT units.
      
      So it is the union of "false positive units" + "redundant units".
      
      Need exhaustive_gt=True
  Method: get_confusion_matrix(self)
    Docstring:
      Computes the confusion matrix.
      
      Returns
      -------
      confusion_matrix : pandas.DataFrame
          The confusion matrix
  Method: get_false_positive_units(self, redundant_score=None)
    Docstring:
      Return units list of "false positive units" from tested_sorting.
      
      "false positive units" are defined as units in tested that
      are not matched at all in GT units.
      
      Need exhaustive_gt=True
      
      Parameters
      ----------
      redundant_score : float, default: None
          The agreement score below which tested units
          are counted as "false positive"" (and not "redundant").
  Method: get_labels1(self, unit_id)
    Docstring:
      None
  Method: get_labels2(self, unit_id)
    Docstring:
      None
  Method: get_overmerged_units(self, overmerged_score=None)
    Docstring:
      Return "overmerged units"
      
      "overmerged units" are defined as units in tested
      that match more than one GT unit with an agreement score larger than overmerged_score.
      
      Parameters
      ----------
      overmerged_score : float, default: None
          Tested units with 2 or more agreement scores above "overmerged_score"
          are counted as "overmerged".
  Method: get_performance(self, method='by_unit', output='pandas')
    Docstring:
      Get performance rate with several method:
        * "raw_count" : just render the raw count table
        * "by_unit" : render perf as rate unit by unit of the GT
        * "pooled_with_average" : compute rate unit by unit and average
      
      Parameters
      ----------
      method : "by_unit" | "pooled_with_average", default: "by_unit"
          The method to compute performance
      output : "pandas" | "dict", default: "pandas"
          The output format
      
      Returns
      -------
      perf : pandas dataframe/series (or dict)
          dataframe/series (based on "output") with performance entries
  Method: get_redundant_units(self, redundant_score=None)
    Docstring:
      Return "redundant units"
      
      "redundant units" are defined as units in tested
      that match a GT units with a big agreement score
      but it is not the best match.
      In other world units in GT that detected twice or more.
      
      Parameters
      ----------
      redundant_score : float, default: None
          The agreement score above which tested units
          are counted as "redundant" (and not "false positive" ).
  Method: get_well_detected_units(self, well_detected_score=None)
    Docstring:
      Return units list of "well detected units" from tested_sorting.
      
      "well detected units" are defined as units in tested that
      are well matched to GT units.
      
      Parameters
      ----------
      well_detected_score : float, default: None
          The agreement score above which tested units
          are counted as "well detected".
  Method: print_performance(self, method='pooled_with_average')
    Docstring:
      Print performance with the selected method
      
      Parameters
      ----------
      method : "by_unit" | "pooled_with_average", default: "pooled_with_average"
          The method to compute performance
  Method: print_summary(self, well_detected_score=None, redundant_score=None, overmerged_score=None)
    Docstring:
      Print a global performance summary that depend on the context:
        * exhaustive= True/False
        * how many gt units (one or several)
      
      This summary mix several performance metrics.
      
      Parameters
      ----------
      well_detected_score : float, default: None
          The agreement score above which tested units
          are counted as "well detected".
      redundant_score : float, default: None
          The agreement score below which tested units
          are counted as "false positive"" (and not "redundant").
      overmerged_score : float, default: None
          Tested units with 2 or more agreement scores above "overmerged_score"
          are counted as "overmerged".

Class: GroundTruthStudy
  Docstring:
    None
  __init__(self, study_folder)

Class: HybridSpikesRecording
  Docstring:
    Class for creating a hybrid recording where additional spikes are added
    to already existing units.
    
    Parameters
    ----------
    wvf_extractor : WaveformExtractor
        The waveform extractor object of the existing recording.
    injected_sorting : BaseSorting | None
        Additional spikes to inject.
        If None, will generate it.
    max_injected_per_unit : int
        If injected_sorting=None, the max number of spikes per unit
        that is allowed to be injected.
    unit_ids : list[int] | None
        unit_ids to take in the wvf_extractor for spikes injection.
    injected_rate : float
        If injected_sorting=None, the max fraction of spikes per
        unit that is allowed to be injected.
    refractory_period_ms : float
        If injected_sorting=None, the injected spikes need to respect
        this refractory period.
    injected_sorting_folder : str | Path | None
        If given, the injected sorting is saved to this folder.
        It must be specified if injected_sorting is None or not serializable to file.
    
    Returns
    -------
    hybrid_spikes_recording : HybridSpikesRecording:
        The recording containing units with real and hybrid spikes.
  __init__(self, wvf_extractor, injected_sorting: 'Union[BaseSorting, None]' = None, unit_ids: 'Union[List[int], None]' = None, max_injected_per_unit: 'int' = 1000, injected_rate: 'float' = 0.05, refractory_period_ms: 'float' = 1.5, injected_sorting_folder: 'Union[str, Path, None]' = None) -> 'None'

Class: HybridUnitsRecording
  Docstring:
    Class for creating a hybrid recording where additional units are added
    to an existing recording.
    
    Parameters
    ----------
    parent_recording : BaseRecording
        Existing recording to add on top of.
    templates : np.ndarray[n_units, n_samples, n_channels]
        Array containing the templates to inject for all the units.
    injected_sorting : BaseSorting | None:
        The sorting for the injected units.
        If None, will be generated using the following parameters.
    nbefore : list[int] | int | None
        Where is the center of the template for each unit?
        If None, will default to the highest peak.
    firing_rate : float
        The firing rate of the injected units (in Hz).
    amplitude_factor : np.ndarray | None:
        The amplitude factor for each spike.
        If None, will be generated as a gaussian centered at 1.0 and with an std of amplitude_std.
    amplitude_std : float
        The standard deviation of the amplitude (centered at 1.0).
    refractory_period_ms : float
        The refractory period of the injected spike train (in ms).
    injected_sorting_folder : str | Path | None
        If given, the injected sorting is saved to this folder.
        It must be specified if injected_sorting is None or not serialisable to file.
    seed : int, default: None
        Random seed for amplitude_factor
    
    Returns
    -------
    hybrid_units_recording : HybridUnitsRecording
        The recording containing real and hybrid units.
  __init__(self, parent_recording: 'BaseRecording', templates: 'np.ndarray', injected_sorting: 'Union[BaseSorting, None]' = None, nbefore: 'Union[List[int], int, None]' = None, firing_rate: 'float' = 10, amplitude_factor: 'Union[np.ndarray, None]' = None, amplitude_std: 'float' = 0.0, refractory_period_ms: 'float' = 2.0, injected_sorting_folder: 'Union[str, Path, None]' = None, seed=None)

Class: MultiSortingComparison
  Docstring:
    Compares multiple spike sorting outputs based on spike trains.
    
    - Pair-wise comparisons are made
    - An agreement graph is built based on the agreement score
    
    It allows to return a consensus-based sorting extractor with the `get_agreement_sorting()` method.
    
    Parameters
    ----------
    sorting_list : list
        List of sorting extractor objects to be compared
    name_list : list, default: None
        List of spike sorter names. If not given, sorters are named as "sorter0", "sorter1", "sorter2", etc.
    delta_time : float, default: 0.4
        Number of ms to consider coincident spikes
    match_score : float, default: 0.5
        Minimum agreement score to match units
    chance_score : float, default: 0.1
        Minimum agreement score to for a possible match
    agreement_method : "count" | "distance", default: "count"
        The method to compute agreement scores. The "count" method computes agreement scores from spike counts.
        The "distance" method computes agreement scores from spike time distance functions.
    n_jobs : int, default: -1
       Number of cores to use in parallel. Uses all available if -1
    spiketrain_mode : "union" | "intersection", default: "union"
        Mode to extract agreement spike trains:
            - "union" : spike trains are the union between the spike trains of the best matching two sorters
            - "intersection" : spike trains are the intersection between the spike trains of the
               best matching two sorters
    verbose : bool, default: False
        If True, output is verbose
    do_matching : bool, default: True
        If True, the comparison is done when the `MultiSortingComparison` is initialized
    
    Returns
    -------
    multi_sorting_comparison : MultiSortingComparison
        MultiSortingComparison object with the multiple sorter comparison
  __init__(self, sorting_list, name_list=None, delta_time=0.4, match_score=0.5, chance_score=0.1, agreement_method='count', n_jobs=-1, spiketrain_mode='union', verbose=False, do_matching=True)
  Method: get_agreement_sorting(self, minimum_agreement_count=1, minimum_agreement_count_only=False)
    Docstring:
      Returns AgreementSortingExtractor with units with a "minimum_matching" agreement.
      
      Parameters
      ----------
      minimum_agreement_count : int
          Minimum number of matches among sorters to include a unit.
      minimum_agreement_count_only : bool
          If True, only units with agreement == "minimum_matching" are included.
          If False, units with an agreement >= "minimum_matching" are included
      
      Returns
      -------
      agreement_sorting : AgreementSortingExtractor
          The output AgreementSortingExtractor
  Method: load_from_folder(folder_path)
    Docstring:
      None
  Method: save_to_folder(self, save_folder)
    Docstring:
      None

Class: MultiTemplateComparison
  Docstring:
    Compares multiple waveform extractors using template similarity.
    
    - Pair-wise comparisons are made
    - An agreement graph is built based on the agreement score
    
    Parameters
    ----------
    waveform_list : list
        List of waveform extractor objects to be compared
    name_list : list, default: None
        List of session names. If not given, sorters are named as "sess0", "sess1", "sess2", etc.
    match_score : float, default: 0.8
        Minimum agreement score to match units
    chance_score : float, default: 0.3
        Minimum agreement score to for a possible match
    verbose : bool, default: False
        If True, output is verbose
    do_matching : bool, default: True
        If True, the comparison is done when the `MultiSortingComparison` is initialized
    support : "dense" | "union" | "intersection", default: "union"
        The support to compute the similarity matrix.
    num_shifts : int, default: 0
        Number of shifts to use to shift templates to maximize similarity.
    similarity_method : "cosine" | "l1" | "l2", default: "cosine"
        Method for the similarity matrix.
    
    Returns
    -------
    multi_template_comparison : MultiTemplateComparison
        MultiTemplateComparison object with the multiple template comparisons
  __init__(self, waveform_list, name_list=None, match_score=0.8, chance_score=0.3, verbose=False, similarity_method='cosine', support='union', num_shifts=0, do_matching=True)

Class: SymmetricSortingComparison
  Docstring:
    Compares two spike sorter outputs.
    
    - Spike trains are matched based on their agreement scores
    - Individual spikes are labelled as true positives (TP), false negatives (FN), false positives 1 (FP from spike
      train 1), false positives 2 (FP from spike train 2), misclassifications (CL)
    
    It also allows to get confusion matrix and agreement fraction, false positive fraction and
    false negative fraction.
    
    Parameters
    ----------
    sorting1 : BaseSorting
        The first sorting for the comparison
    sorting2 : BaseSorting
        The second sorting for the comparison
    sorting1_name : str, default: None
        The name of sorter 1
    sorting2_name : : str, default: None
        The name of sorter 2
    delta_time : float, default: 0.4
        Number of ms to consider coincident spikes
    match_score : float, default: 0.5
        Minimum agreement score to match units
    chance_score : float, default: 0.1
        Minimum agreement score to for a possible match
    agreement_method : "count" | "distance", default: "count"
        The method to compute agreement scores. The "count" method computes agreement scores from spike counts.
        The "distance" method computes agreement scores from spike time distance functions.
    verbose : bool, default: False
        If True, output is verbose
    
    Returns
    -------
    sorting_comparison : SortingComparison
        The SortingComparison object
  __init__(self, sorting1: 'BaseSorting', sorting2: 'BaseSorting', sorting1_name: 'str | None' = None, sorting2_name: 'str | None' = None, delta_time: 'float' = 0.4, match_score: 'float' = 0.5, chance_score: 'float' = 0.1, agreement_method: 'str' = 'count', verbose: 'bool' = False)
  Method: get_agreement_fraction(self, unit1=None, unit2=None)
    Docstring:
      None
  Method: get_best_unit_match1(self, unit1)
    Docstring:
      None
  Method: get_best_unit_match2(self, unit2)
    Docstring:
      None
  Method: get_matching(self)
    Docstring:
      None
  Method: get_matching_event_count(self, unit1, unit2)
    Docstring:
      None
  Method: get_matching_unit_list1(self, unit1)
    Docstring:
      None
  Method: get_matching_unit_list2(self, unit2)
    Docstring:
      None

Class: TemplateComparison
  Docstring:
    Compares units from different sessions based on template similarity
    
    Parameters
    ----------
    sorting_analyzer_1 : SortingAnalyzer
        The first SortingAnalyzer to get templates to compare.
    sorting_analyzer_2 : SortingAnalyzer
        The second SortingAnalyzer to get templates to compare.
    unit_ids1 : list, default: None
        List of units from sorting_analyzer_1 to compare.
    unit_ids2 : list, default: None
        List of units from sorting_analyzer_2 to compare.
    name1 : str, default: "sess1"
        Name of first session.
    name2 : str, default: "sess2"
        Name of second session.
    similarity_method : "cosine" | "l1" | "l2", default: "cosine"
        Method for the similarity matrix.
    support : "dense" | "union" | "intersection", default: "union"
        The support to compute the similarity matrix.
    num_shifts : int, default: 0
        Number of shifts to use to shift templates to maximize similarity.
    verbose : bool, default: False
        If True, output is verbose.
    chance_score : float, default: 0.3
         Minimum agreement score to for a possible match
    match_score : float, default: 0.7
        Minimum agreement score to match units
    
    
    Returns
    -------
    comparison : TemplateComparison
        The output TemplateComparison object.
  __init__(self, sorting_analyzer_1, sorting_analyzer_2, name1=None, name2=None, unit_ids1=None, unit_ids2=None, match_score=0.7, chance_score=0.3, similarity_method='cosine', support='union', num_shifts=0, verbose=False)

Class: compare_multiple_sorters
  Docstring:
    Compares multiple spike sorting outputs based on spike trains.
    
    - Pair-wise comparisons are made
    - An agreement graph is built based on the agreement score
    
    It allows to return a consensus-based sorting extractor with the `get_agreement_sorting()` method.
    
    Parameters
    ----------
    sorting_list : list
        List of sorting extractor objects to be compared
    name_list : list, default: None
        List of spike sorter names. If not given, sorters are named as "sorter0", "sorter1", "sorter2", etc.
    delta_time : float, default: 0.4
        Number of ms to consider coincident spikes
    match_score : float, default: 0.5
        Minimum agreement score to match units
    chance_score : float, default: 0.1
        Minimum agreement score to for a possible match
    agreement_method : "count" | "distance", default: "count"
        The method to compute agreement scores. The "count" method computes agreement scores from spike counts.
        The "distance" method computes agreement scores from spike time distance functions.
    n_jobs : int, default: -1
       Number of cores to use in parallel. Uses all available if -1
    spiketrain_mode : "union" | "intersection", default: "union"
        Mode to extract agreement spike trains:
            - "union" : spike trains are the union between the spike trains of the best matching two sorters
            - "intersection" : spike trains are the intersection between the spike trains of the
               best matching two sorters
    verbose : bool, default: False
        If True, output is verbose
    do_matching : bool, default: True
        If True, the comparison is done when the `MultiSortingComparison` is initialized
    
    Returns
    -------
    multi_sorting_comparison : MultiSortingComparison
        MultiSortingComparison object with the multiple sorter comparison
  __init__(self, sorting_list, name_list=None, delta_time=0.4, match_score=0.5, chance_score=0.1, agreement_method='count', n_jobs=-1, spiketrain_mode='union', verbose=False, do_matching=True)
  Method: get_agreement_sorting(self, minimum_agreement_count=1, minimum_agreement_count_only=False)
    Docstring:
      Returns AgreementSortingExtractor with units with a "minimum_matching" agreement.
      
      Parameters
      ----------
      minimum_agreement_count : int
          Minimum number of matches among sorters to include a unit.
      minimum_agreement_count_only : bool
          If True, only units with agreement == "minimum_matching" are included.
          If False, units with an agreement >= "minimum_matching" are included
      
      Returns
      -------
      agreement_sorting : AgreementSortingExtractor
          The output AgreementSortingExtractor
  Method: load_from_folder(folder_path)
    Docstring:
      None
  Method: save_to_folder(self, save_folder)
    Docstring:
      None

Class: compare_multiple_templates
  Docstring:
    Compares multiple waveform extractors using template similarity.
    
    - Pair-wise comparisons are made
    - An agreement graph is built based on the agreement score
    
    Parameters
    ----------
    waveform_list : list
        List of waveform extractor objects to be compared
    name_list : list, default: None
        List of session names. If not given, sorters are named as "sess0", "sess1", "sess2", etc.
    match_score : float, default: 0.8
        Minimum agreement score to match units
    chance_score : float, default: 0.3
        Minimum agreement score to for a possible match
    verbose : bool, default: False
        If True, output is verbose
    do_matching : bool, default: True
        If True, the comparison is done when the `MultiSortingComparison` is initialized
    support : "dense" | "union" | "intersection", default: "union"
        The support to compute the similarity matrix.
    num_shifts : int, default: 0
        Number of shifts to use to shift templates to maximize similarity.
    similarity_method : "cosine" | "l1" | "l2", default: "cosine"
        Method for the similarity matrix.
    
    Returns
    -------
    multi_template_comparison : MultiTemplateComparison
        MultiTemplateComparison object with the multiple template comparisons
  __init__(self, waveform_list, name_list=None, match_score=0.8, chance_score=0.3, verbose=False, similarity_method='cosine', support='union', num_shifts=0, do_matching=True)

Class: compare_sorter_to_ground_truth
  Docstring:
    Compares a sorter to a ground truth.
    
    This class can:
      * compute a "match between gt_sorting and tested_sorting
      * compute optionally the score label (TP, FN, CL, FP) for each spike
      * count by unit of GT the total of each (TP, FN, CL, FP) into a Dataframe
        GroundTruthComparison.count
      * compute the confusion matrix .get_confusion_matrix()
      * compute some performance metric with several strategy based on
        the count score by unit
      * count well detected units
      * count false positive detected units
      * count redundant units
      * count overmerged units
      * summary all this
    
    
    Parameters
    ----------
    gt_sorting : BaseSorting
        The first sorting for the comparison
    tested_sorting : BaseSorting
        The second sorting for the comparison
    gt_name : str, default: None
        The name of sorter 1
    tested_name : : str, default: None
        The name of sorter 2
    delta_time : float, default: 0.4
        Number of ms to consider coincident spikes.
        This means that two spikes are considered simultaneous if they are within `delta_time` of each other or
        mathematically abs(spike1_time - spike2_time) <= delta_time.
    match_score : float, default: 0.5
        Minimum agreement score to match units
    chance_score : float, default: 0.1
        Minimum agreement score to for a possible match
    redundant_score : float, default: 0.2
        Agreement score above which units are redundant
    overmerged_score : float, default: 0.2
        Agreement score above which units can be overmerged
    well_detected_score : float, default: 0.8
        Agreement score above which units are well detected
    exhaustive_gt : bool, default: False
        Tell if the ground true is "exhaustive" or not. In other world if the
        GT have all possible units. It allows more performance measurement.
        For instance, MEArec simulated dataset have exhaustive_gt=True
    match_mode : "hungarian" | "best", default: "hungarian"
        The method to match units
    agreement_method : "count" | "distance", default: "count"
        The method to compute agreement scores. The "count" method computes agreement scores from spike counts.
        The "distance" method computes agreement scores from spike time distance functions.
    compute_labels : bool, default: False
        If True, labels are computed at instantiation
    compute_misclassifications : bool, default: False
        If True, misclassifications are computed at instantiation
    verbose : bool, default: False
        If True, output is verbose
    
    Returns
    -------
    sorting_comparison : SortingComparison
        The SortingComparison object
  __init__(self, gt_sorting: 'BaseSorting', tested_sorting: 'BaseSorting', gt_name: 'str | None' = None, tested_name: 'str | None' = None, delta_time: 'float' = 0.4, match_score: 'float' = 0.5, well_detected_score: 'float' = 0.8, redundant_score: 'float' = 0.2, overmerged_score: 'float' = 0.2, chance_score: 'float' = 0.1, exhaustive_gt: 'bool' = False, agreement_method: 'str' = 'count', match_mode: 'str' = 'hungarian', compute_labels: 'bool' = False, compute_misclassifications: 'bool' = False, verbose: 'bool' = False)
  Method: count_bad_units(self)
    Docstring:
      See get_bad_units
  Method: count_false_positive_units(self, redundant_score=None)
    Docstring:
      See get_false_positive_units().
      
      Parameters
      ----------
      redundant_score : float | None, default: None
          The agreement score below which tested units
          are counted as "false positive"" (and not "redundant").
  Method: count_overmerged_units(self, overmerged_score=None)
    Docstring:
      See get_overmerged_units().
      
      Parameters
      ----------
      overmerged_score : float, default: None
          Tested units with 2 or more agreement scores above "overmerged_score"
          are counted as "overmerged".
  Method: count_redundant_units(self, redundant_score=None)
    Docstring:
      See get_redundant_units().
      
       Parameters
       ----------
       redundant_score : float, default: None
           The agreement score below which tested units
           are counted as "false positive"" (and not "redundant").
  Method: count_units_categories(self, well_detected_score=None, overmerged_score=None, redundant_score=None)
    Docstring:
      None
  Method: count_well_detected_units(self, well_detected_score)
    Docstring:
      Count how many well detected units.
      kwargs are the same as get_well_detected_units.
      
      Parameters
      ----------
      well_detected_score : float, default: None
          The agreement score above which tested units
          are counted as "well detected".
  Method: get_bad_units(self)
    Docstring:
      Return units list of "bad units".
      
      "bad units" are defined as units in tested that are not
      in the best match list of GT units.
      
      So it is the union of "false positive units" + "redundant units".
      
      Need exhaustive_gt=True
  Method: get_confusion_matrix(self)
    Docstring:
      Computes the confusion matrix.
      
      Returns
      -------
      confusion_matrix : pandas.DataFrame
          The confusion matrix
  Method: get_false_positive_units(self, redundant_score=None)
    Docstring:
      Return units list of "false positive units" from tested_sorting.
      
      "false positive units" are defined as units in tested that
      are not matched at all in GT units.
      
      Need exhaustive_gt=True
      
      Parameters
      ----------
      redundant_score : float, default: None
          The agreement score below which tested units
          are counted as "false positive"" (and not "redundant").
  Method: get_labels1(self, unit_id)
    Docstring:
      None
  Method: get_labels2(self, unit_id)
    Docstring:
      None
  Method: get_overmerged_units(self, overmerged_score=None)
    Docstring:
      Return "overmerged units"
      
      "overmerged units" are defined as units in tested
      that match more than one GT unit with an agreement score larger than overmerged_score.
      
      Parameters
      ----------
      overmerged_score : float, default: None
          Tested units with 2 or more agreement scores above "overmerged_score"
          are counted as "overmerged".
  Method: get_performance(self, method='by_unit', output='pandas')
    Docstring:
      Get performance rate with several method:
        * "raw_count" : just render the raw count table
        * "by_unit" : render perf as rate unit by unit of the GT
        * "pooled_with_average" : compute rate unit by unit and average
      
      Parameters
      ----------
      method : "by_unit" | "pooled_with_average", default: "by_unit"
          The method to compute performance
      output : "pandas" | "dict", default: "pandas"
          The output format
      
      Returns
      -------
      perf : pandas dataframe/series (or dict)
          dataframe/series (based on "output") with performance entries
  Method: get_redundant_units(self, redundant_score=None)
    Docstring:
      Return "redundant units"
      
      "redundant units" are defined as units in tested
      that match a GT units with a big agreement score
      but it is not the best match.
      In other world units in GT that detected twice or more.
      
      Parameters
      ----------
      redundant_score : float, default: None
          The agreement score above which tested units
          are counted as "redundant" (and not "false positive" ).
  Method: get_well_detected_units(self, well_detected_score=None)
    Docstring:
      Return units list of "well detected units" from tested_sorting.
      
      "well detected units" are defined as units in tested that
      are well matched to GT units.
      
      Parameters
      ----------
      well_detected_score : float, default: None
          The agreement score above which tested units
          are counted as "well detected".
  Method: print_performance(self, method='pooled_with_average')
    Docstring:
      Print performance with the selected method
      
      Parameters
      ----------
      method : "by_unit" | "pooled_with_average", default: "pooled_with_average"
          The method to compute performance
  Method: print_summary(self, well_detected_score=None, redundant_score=None, overmerged_score=None)
    Docstring:
      Print a global performance summary that depend on the context:
        * exhaustive= True/False
        * how many gt units (one or several)
      
      This summary mix several performance metrics.
      
      Parameters
      ----------
      well_detected_score : float, default: None
          The agreement score above which tested units
          are counted as "well detected".
      redundant_score : float, default: None
          The agreement score below which tested units
          are counted as "false positive"" (and not "redundant").
      overmerged_score : float, default: None
          Tested units with 2 or more agreement scores above "overmerged_score"
          are counted as "overmerged".

Function: compare_spike_trains(spiketrain1, spiketrain2, delta_frames=10)
  Docstring:
    Compares 2 spike trains.
    
    Note:
      * The first spiketrain is supposed to be the ground truth.
      * this implementation do not count a TP when more than one spike
        is present around the same time in spiketrain2.
    
    Parameters
    ----------
    spiketrain1, spiketrain2 : numpy.array
        Times of spikes for the 2 spike trains.
    
    Returns
    -------
    lab_st1, lab_st2 : numpy.array
        Label of score for each spike

Class: compare_templates
  Docstring:
    Compares units from different sessions based on template similarity
    
    Parameters
    ----------
    sorting_analyzer_1 : SortingAnalyzer
        The first SortingAnalyzer to get templates to compare.
    sorting_analyzer_2 : SortingAnalyzer
        The second SortingAnalyzer to get templates to compare.
    unit_ids1 : list, default: None
        List of units from sorting_analyzer_1 to compare.
    unit_ids2 : list, default: None
        List of units from sorting_analyzer_2 to compare.
    name1 : str, default: "sess1"
        Name of first session.
    name2 : str, default: "sess2"
        Name of second session.
    similarity_method : "cosine" | "l1" | "l2", default: "cosine"
        Method for the similarity matrix.
    support : "dense" | "union" | "intersection", default: "union"
        The support to compute the similarity matrix.
    num_shifts : int, default: 0
        Number of shifts to use to shift templates to maximize similarity.
    verbose : bool, default: False
        If True, output is verbose.
    chance_score : float, default: 0.3
         Minimum agreement score to for a possible match
    match_score : float, default: 0.7
        Minimum agreement score to match units
    
    
    Returns
    -------
    comparison : TemplateComparison
        The output TemplateComparison object.
  __init__(self, sorting_analyzer_1, sorting_analyzer_2, name1=None, name2=None, unit_ids1=None, unit_ids2=None, match_score=0.7, chance_score=0.3, similarity_method='cosine', support='union', num_shifts=0, verbose=False)

Class: compare_two_sorters
  Docstring:
    Compares two spike sorter outputs.
    
    - Spike trains are matched based on their agreement scores
    - Individual spikes are labelled as true positives (TP), false negatives (FN), false positives 1 (FP from spike
      train 1), false positives 2 (FP from spike train 2), misclassifications (CL)
    
    It also allows to get confusion matrix and agreement fraction, false positive fraction and
    false negative fraction.
    
    Parameters
    ----------
    sorting1 : BaseSorting
        The first sorting for the comparison
    sorting2 : BaseSorting
        The second sorting for the comparison
    sorting1_name : str, default: None
        The name of sorter 1
    sorting2_name : : str, default: None
        The name of sorter 2
    delta_time : float, default: 0.4
        Number of ms to consider coincident spikes
    match_score : float, default: 0.5
        Minimum agreement score to match units
    chance_score : float, default: 0.1
        Minimum agreement score to for a possible match
    agreement_method : "count" | "distance", default: "count"
        The method to compute agreement scores. The "count" method computes agreement scores from spike counts.
        The "distance" method computes agreement scores from spike time distance functions.
    verbose : bool, default: False
        If True, output is verbose
    
    Returns
    -------
    sorting_comparison : SortingComparison
        The SortingComparison object
  __init__(self, sorting1: 'BaseSorting', sorting2: 'BaseSorting', sorting1_name: 'str | None' = None, sorting2_name: 'str | None' = None, delta_time: 'float' = 0.4, match_score: 'float' = 0.5, chance_score: 'float' = 0.1, agreement_method: 'str' = 'count', verbose: 'bool' = False)
  Method: get_agreement_fraction(self, unit1=None, unit2=None)
    Docstring:
      None
  Method: get_best_unit_match1(self, unit1)
    Docstring:
      None
  Method: get_best_unit_match2(self, unit2)
    Docstring:
      None
  Method: get_matching(self)
    Docstring:
      None
  Method: get_matching_event_count(self, unit1, unit2)
    Docstring:
      None
  Method: get_matching_unit_list1(self, unit1)
    Docstring:
      None
  Method: get_matching_unit_list2(self, unit2)
    Docstring:
      None

Function: compute_agreement_score(num_matches: 'int', num1: 'int', num2: 'int') -> 'float'
  Docstring:
    Computes agreement score.
    
    Parameters
    ----------
    num_matches : int
        Number of matches
    num1 : int
        Number of events in spike train 1
    num2 : int
        Number of events in spike train 2
    
    Returns
    -------
    score : float
        Agreement score

Function: compute_performance(count_score)
  Docstring:
    This compute perf formula.
    this trick here is that it works both on pd.Series and pd.Dataframe
    line by line.
    This it is internally used by perf by psiketrain and poll_with_sum.
    
    https://en.wikipedia.org/wiki/Sensitivity_and_specificity
    
    Note :
      * we don't have TN because it do not make sens here.
      * "accuracy" = "tp_rate" because TN=0
      * "recall" = "sensitivity"

Function: count_match_spikes(times1, all_times2, delta_frames)
  Docstring:
    Computes matching spikes between one spike train and a list of others.
    
    Parameters
    ----------
    times1 : array
        Spike train 1 frames
    all_times2 : list of array
        List of spike trains from sorting 2
    
    Returns
    -------
    matching_events_count : list
        List of counts of matching events

Function: count_matching_events(times1, times2: 'np.ndarray | list', delta: 'int' = 10)
  Docstring:
    Counts matching events.
    
    Parameters
    ----------
    times1 : list
        List of spike train 1 frames
    times2 : list
        List of spike train 2 frames
    delta : int
        Number of frames for considering matching events
    
    Returns
    -------
    matching_count : int
        Number of matching events

Class: create_hybrid_spikes_recording
  Docstring:
    Class for creating a hybrid recording where additional spikes are added
    to already existing units.
    
    Parameters
    ----------
    wvf_extractor : WaveformExtractor
        The waveform extractor object of the existing recording.
    injected_sorting : BaseSorting | None
        Additional spikes to inject.
        If None, will generate it.
    max_injected_per_unit : int
        If injected_sorting=None, the max number of spikes per unit
        that is allowed to be injected.
    unit_ids : list[int] | None
        unit_ids to take in the wvf_extractor for spikes injection.
    injected_rate : float
        If injected_sorting=None, the max fraction of spikes per
        unit that is allowed to be injected.
    refractory_period_ms : float
        If injected_sorting=None, the injected spikes need to respect
        this refractory period.
    injected_sorting_folder : str | Path | None
        If given, the injected sorting is saved to this folder.
        It must be specified if injected_sorting is None or not serializable to file.
    
    Returns
    -------
    hybrid_spikes_recording : HybridSpikesRecording:
        The recording containing units with real and hybrid spikes.
  __init__(self, wvf_extractor, injected_sorting: 'Union[BaseSorting, None]' = None, unit_ids: 'Union[List[int], None]' = None, max_injected_per_unit: 'int' = 1000, injected_rate: 'float' = 0.05, refractory_period_ms: 'float' = 1.5, injected_sorting_folder: 'Union[str, Path, None]' = None) -> 'None'

Class: create_hybrid_units_recording
  Docstring:
    Class for creating a hybrid recording where additional units are added
    to an existing recording.
    
    Parameters
    ----------
    parent_recording : BaseRecording
        Existing recording to add on top of.
    templates : np.ndarray[n_units, n_samples, n_channels]
        Array containing the templates to inject for all the units.
    injected_sorting : BaseSorting | None:
        The sorting for the injected units.
        If None, will be generated using the following parameters.
    nbefore : list[int] | int | None
        Where is the center of the template for each unit?
        If None, will default to the highest peak.
    firing_rate : float
        The firing rate of the injected units (in Hz).
    amplitude_factor : np.ndarray | None:
        The amplitude factor for each spike.
        If None, will be generated as a gaussian centered at 1.0 and with an std of amplitude_std.
    amplitude_std : float
        The standard deviation of the amplitude (centered at 1.0).
    refractory_period_ms : float
        The refractory period of the injected spike train (in ms).
    injected_sorting_folder : str | Path | None
        If given, the injected sorting is saved to this folder.
        It must be specified if injected_sorting is None or not serialisable to file.
    seed : int, default: None
        Random seed for amplitude_factor
    
    Returns
    -------
    hybrid_units_recording : HybridUnitsRecording
        The recording containing real and hybrid units.
  __init__(self, parent_recording: 'BaseRecording', templates: 'np.ndarray', injected_sorting: 'Union[BaseSorting, None]' = None, nbefore: 'Union[List[int], int, None]' = None, firing_rate: 'float' = 10, amplitude_factor: 'Union[np.ndarray, None]' = None, amplitude_std: 'float' = 0.0, refractory_period_ms: 'float' = 2.0, injected_sorting_folder: 'Union[str, Path, None]' = None, seed=None)

Function: do_confusion_matrix(event_counts1, event_counts2, match_12, match_event_count)
  Docstring:
    Computes the confusion matrix between one ground truth sorting
    and another sorting.
    
    Parameters
    ----------
    event_counts1 : pd.Series
        Number of event per units 1
    event_counts2 : pd.Series
        Number of event per units 2
    match_12 : pd.Series
        Series of matching from sorting1 to sorting2.
        Can be the hungarian or best match.
    match_event_count : pd.DataFrame
        The match count matrix given by make_match_count_matrix
    
    Returns
    -------
    confusion_matrix : pd.DataFrame
        The confusion matrix
        index are units1 reordered
        columns are units2 redordered

Function: do_count_event(sorting)
  Docstring:
    Count event for each units in a sorting.
    
    Kept for backward compatibility sorting.count_num_spikes_per_unit() is doing the same.
    
    Parameters
    ----------
    sorting : BaseSorting
        A sorting extractor
    
    Returns
    -------
    event_count : pd.Series
        Nb of spike by units.

Function: do_count_score(event_counts1, event_counts2, match_12, match_event_count)
  Docstring:
    For each ground truth units count how many:
    "tp", "fn", "cl", "fp", "num_gt", "num_tested", "tested_id"
    
    Parameters
    ----------
    event_counts1 : pd.Series
        Number of event per units 1
    event_counts2 : pd.Series
        Number of event per units 2
    match_12 : pd.Series
        Series of matching from sorting1 to sorting2.
        Can be the hungarian or best match.
    match_event_count : pd.DataFrame
        The match count matrix given by make_match_count_matrix
    
    Returns
    -------
    count_score : pd.DataFrame
        A table with one line per GT units and columns
        are tp/fn/fp/...

Function: do_score_labels(sorting1, sorting2, delta_frames, unit_map12, label_misclassification=False)
  Docstring:
    Makes the labelling at spike level for each spike train:
      * TP: true positive
      * CL: classification error
      * FN: False negative
      * FP: False positive
      * TOT:
      * TOT_ST1:
      * TOT_ST2:
    
    Parameters
    ----------
    sorting1 : BaseSorting
        The ground truth sorting
    sorting2 : BaseSorting
        The tested sorting
    delta_frames : int
        Number of frames to consider spikes coincident
    unit_map12 : pd.Series
        Dict of matching from sorting1 to sorting2
    label_misclassification : bool
        If True, misclassification errors are labelled
    
    Returns
    -------
    labels_st1 : dict of lists of np.array of str
        Contain score labels for units of sorting 1 for each segment
    labels_st2 : dict of lists of np.array of str
        Contain score labels for units of sorting 2 for each segment

Function: make_agreement_scores(sorting1: 'BaseSorting', sorting2: 'BaseSorting', delta_frames: 'int', ensure_symmetry: 'bool' = True)
  Docstring:
    Make the agreement matrix.
    No threshold (min_score) is applied at this step.
    
    Note : this computation is symmetric by default.
    Inverting sorting1 and sorting2 give the transposed matrix.
    
    Parameters
    ----------
    sorting1 : BaseSorting
        The first sorting extractor
    sorting2 : BaseSorting
        The second sorting extractor
    delta_frames : int
        Number of frames to consider spikes coincident
    ensure_symmetry : bool, default: True
        If ensure_symmetry is True, then the algo is run two times by switching sorting1 and sorting2.
        And the minimum of the two results is taken.
    Returns
    -------
    agreement_scores : pd.DataFrame
        The agreement score matrix.

Function: make_best_match(agreement_scores, min_score) -> "'tuple[pd.Series, pd.Series]'"
  Docstring:
    Given an agreement matrix and a min_score threshold.
    return a dict a best match for each units independently of others.
    
    Note : this is symmetric.
    
    Parameters
    ----------
    agreement_scores : pd.DataFrame
    
    min_score : float
    
    
    Returns
    -------
    best_match_12 : pd.Series
    
    best_match_21 : pd.Series

Function: make_hungarian_match(agreement_scores, min_score)
  Docstring:
    Given an agreement matrix and a min_score threshold.
    return the "optimal" match with the "hungarian" algo.
    This use internally the scipy.optimize.linear_sum_assignment implementation.
    
    Parameters
    ----------
    agreement_scores: pd.DataFrame
    
    min_score : float
    
    
    Returns
    -------
    hungarian_match_12 : pd.Series
    
    hungarian_match_21 : pd.Series

Function: make_match_count_matrix(sorting1: 'BaseSorting', sorting2: 'BaseSorting', delta_frames: 'int', ensure_symmetry: 'bool' = False)
  Docstring:
    Computes a matrix representing the matches between two Sorting objects.
    
    Given two spike trains, this function finds matching spikes based on a temporal proximity criterion
    defined by `delta_frames`. The resulting matrix indicates the number of matches between units
    in `spike_frames_train1` and `spike_frames_train2` for each pair of units.
    
    Note that this algo is not symmetric and is biased with `sorting1` representing ground truth for the comparison
    
    Parameters
    ----------
    sorting1 : Sorting
        An array of integer frame numbers corresponding to spike times for the first train. Must be in ascending order.
    sorting2 : Sorting
        An array of integer frame numbers corresponding to spike times for the second train. Must be in ascending order.
    delta_frames : int
        The inclusive upper limit on the frame difference for which two spikes are considered matching. That is
        if `abs(spike_frames_train1[i] - spike_frames_train2[j]) <= delta_frames` then the spikes at
        `spike_frames_train1[i]` and `spike_frames_train2[j]` are considered matching.
    ensure_symmetry: bool, default False
        If ensure_symmetry=True, then the algo is run two times by switching sorting1 and sorting2.
        And the minimum of the two results is taken.
    Returns
    -------
    matching_matrix : pd.DataFrame
        A 2D pandas DataFrame of shape `(num_units_train1, num_units_train2)`. Each element `[i, j]` represents
        the count of matching spike pairs between unit `i` from `spike_frames_train1` and unit `j` from `spike_frames_train2`.
    
    Notes
    -----
    This algorithm identifies matching spikes between two ordered spike trains.
    By iterating through each spike in the first train, it compares them against spikes in the second train,
    determining matches based on the two spikes frames being within `delta_frames` of each other.
    
    To avoid redundant comparisons the algorithm maintains a reference, `second_train_search_start `,
    which signifies the minimal index in the second spike train that might match the upcoming spike
    in the first train.
    
    The logic can be summarized as follows:
    1. Iterate through each spike in the first train
    2. For each spike, find the first match in the second train.
    3. Save the index of the first match as the new `second_train_search_start `
    3. For each match, find as many matches as possible from the first match onwards.
    
    An important condition here is that the same spike is not matched twice. This is managed by keeping track
    of the last matched frame for each unit pair in `last_match_frame1` and `last_match_frame2`
    There are corner cases where a spike can be counted twice in the spiketrain 2 if there are bouts of bursting activity
    (below delta_frames) in the spiketrain 1. To ensure that the number of matches does not exceed the number of spikes,
    we apply a final clip.
    
    
    For more details on the rationale behind this approach, refer to the documentation of this module and/or
    the metrics section in SpikeForest documentation.

Function: make_possible_match(agreement_scores, min_score)
  Docstring:
    Given an agreement matrix and a min_score threshold.
    Return as a dict all possible match for each spiketrain in each side.
    
    Note : this is symmetric.
    
    Parameters
    ----------
    agreement_scores : pd.DataFrame
    
    min_score : float
    
    
    Returns
    -------
    best_match_12 : dict[NDArray]
    
    best_match_21 : dict[NDArray]
