nodes: 0, module; 1, function_definition; 2, function_name:decluster; 3, parameters; 4, block; 5, identifier:self; 6, identifier:trig_int; 7, default_parameter; 8, default_parameter; 9, expression_statement; 10, expression_statement; 11, for_statement; 12, if_statement; 13, expression_statement; 14, expression_statement; 15, expression_statement; 16, comment:# Trig_int must be converted from seconds to micro-seconds; 17, expression_statement; 18, comment:# Need to match both the time and the detection value; 19, expression_statement; 20, for_statement; 21, comment:# Convert this list into families; 22, expression_statement; 23, expression_statement; 24, for_statement; 25, expression_statement; 26, return_statement; 27, identifier:timing; 28, string; 29, identifier:metric; 30, string; 31, comment:"""
          De-cluster a Party of detections by enforcing a detection separation.
  
          De-clustering occurs between events detected by different (or the same)
          templates. If multiple detections occur within trig_int then the
          preferred detection will be determined by the metric argument. This
          can be either the average single-station correlation coefficient which
          is calculated as Detection.detect_val / Detection.no_chans, or the
          raw cross channel correlation sum which is simply Detection.detect_val.
  
          :type trig_int: float
          :param trig_int: Minimum detection separation in seconds.
          :type metric: str
          :param metric: What metric to sort peaks by. Either 'avg_cor' which
              takes the single station average correlation or 'cor_sum' which
              takes the total correlation sum across all channels.
          :type timing: str
          :param timing:
              Either 'detect' or 'origin' to decluster based on either the
              detection time or the origin time.
  
          .. Warning::
              Works in place on object, if you need to keep the original safe
              then run this on a copy of the object!
  
          .. rubric:: Example
  
          >>> party = Party().read()
          >>> len(party)
          4
          >>> declustered = party.decluster(20)
          >>> len(party)
          3
          """; 32, assignment; 33, identifier:fam; 34, attribute; 35, block; 36, comparison_operator:timing == 'detect'; 37, block; 38, elif_clause; 39, else_clause; 40, assignment; 41, assignment; 42, assignment; 43, assignment; 44, assignment; 45, identifier:ind; 46, identifier:peaks_out; 47, block; 48, assignment; 49, assignment; 50, identifier:template_name; 51, identifier:template_names; 52, block; 53, assignment; 54, identifier:self; 55, string_content:detect; 56, string_content:avg_cor; 57, identifier:all_detections; 58, list; 59, identifier:self; 60, identifier:families; 61, expression_statement; 62, identifier:timing; 63, string; 64, if_statement; 65, comparison_operator:timing == 'origin'; 66, block; 67, block; 68, identifier:min_det; 69, subscript; 70, identifier:detect_vals; 71, call; 72, identifier:detect_times; 73, call; 74, identifier:peaks_out; 75, call; 76, identifier:declustered_detections; 77, list; 78, expression_statement; 79, expression_statement; 80, expression_statement; 81, identifier:template_names; 82, call; 83, identifier:new_families; 84, list; 85, expression_statement; 86, expression_statement; 87, attribute; 88, identifier:new_families; 89, call; 90, string_content:detect; 91, comparison_operator:metric == 'avg_cor'; 92, block; 93, elif_clause; 94, else_clause; 95, identifier:timing; 96, string; 97, if_statement; 98, raise_statement; 99, call; 100, integer:0; 101, attribute; 102, argument_list; 103, attribute; 104, argument_list; 105, identifier:decluster; 106, argument_list; 107, assignment; 108, assignment; 109, call; 110, identifier:list; 111, argument_list; 112, assignment; 113, call; 114, identifier:self; 115, identifier:families; 116, attribute; 117, argument_list; 118, identifier:metric; 119, string; 120, expression_statement; 121, comparison_operator:metric == 'cor_sum'; 122, block; 123, block; 124, string_content:origin; 125, comparison_operator:metric == 'avg_cor'; 126, block; 127, elif_clause; 128, else_clause; 129, call; 130, identifier:sorted; 131, argument_list; 132, identifier:np; 133, identifier:array; 134, list_comprehension; 135, identifier:np; 136, identifier:array; 137, list_comprehension; 138, keyword_argument; 139, keyword_argument; 140, keyword_argument; 141, identifier:matching_time_indeces; 142, subscript; 143, identifier:matches; 144, subscript; 145, attribute; 146, argument_list; 147, call; 148, identifier:template; 149, subscript; 150, attribute; 151, argument_list; 152, identifier:all_detections; 153, identifier:extend; 154, attribute; 155, string_content:avg_cor; 156, assignment; 157, identifier:metric; 158, string; 159, expression_statement; 160, raise_statement; 161, identifier:metric; 162, string; 163, expression_statement; 164, comparison_operator:metric == 'cor_sum'; 165, block; 166, block; 167, identifier:MatchFilterError; 168, argument_list; 169, list_comprehension; 170, subscript; 171, for_in_clause; 172, call; 173, for_in_clause; 174, identifier:peaks; 175, identifier:detect_vals; 176, identifier:index; 177, identifier:detect_times; 178, identifier:trig_int; 179, binary_operator:trig_int * 10 ** 6; 180, call; 181, integer:0; 182, identifier:matching_time_indeces; 183, subscript; 184, identifier:declustered_detections; 185, identifier:append; 186, subscript; 187, identifier:set; 188, argument_list; 189, list_comprehension; 190, integer:0; 191, identifier:new_families; 192, identifier:append; 193, call; 194, identifier:fam; 195, identifier:detections; 196, identifier:detect_info; 197, list_comprehension; 198, string_content:cor_sum; 199, assignment; 200, call; 201, string_content:avg_cor; 202, assignment; 203, identifier:metric; 204, string; 205, expression_statement; 206, raise_statement; 207, string; 208, subscript; 209, for_in_clause; 210, identifier:d; 211, integer:1; 212, identifier:d; 213, identifier:detect_info; 214, identifier:_total_microsec; 215, argument_list; 216, identifier:d; 217, identifier:detect_info; 218, identifier:trig_int; 219, binary_operator:10 ** 6; 220, attribute; 221, argument_list; 222, subscript; 223, integer:0; 224, identifier:all_detections; 225, identifier:matches; 226, list_comprehension; 227, attribute; 228, for_in_clause; 229, if_clause; 230, identifier:Family; 231, argument_list; 232, tuple; 233, for_in_clause; 234, identifier:detect_info; 235, list_comprehension; 236, identifier:MatchFilterError; 237, argument_list; 238, identifier:detect_info; 239, list_comprehension; 240, string_content:cor_sum; 241, assignment; 242, call; 243, string_content:timing is not detect or origin; 244, identifier:d; 245, integer:0; 246, identifier:d; 247, identifier:detect_info; 248, attribute; 249, attribute; 250, integer:10; 251, integer:6; 252, identifier:np; 253, identifier:where; 254, comparison_operator:detect_times == ind[-1]; 255, call; 256, integer:0; 257, attribute; 258, for_in_clause; 259, identifier:fam; 260, identifier:template; 261, identifier:fam; 262, attribute; 263, comparison_operator:fam.template.name == template_name; 264, keyword_argument; 265, keyword_argument; 266, attribute; 267, binary_operator:d.detect_val / d.no_chans; 268, identifier:d; 269, identifier:all_detections; 270, tuple; 271, for_in_clause; 272, string; 273, tuple; 274, for_in_clause; 275, identifier:detect_info; 276, list_comprehension; 277, identifier:MatchFilterError; 278, argument_list; 279, subscript; 280, identifier:datetime; 281, identifier:min_det; 282, identifier:datetime; 283, identifier:detect_times; 284, subscript; 285, attribute; 286, argument_list; 287, identifier:d; 288, identifier:template_name; 289, identifier:d; 290, identifier:declustered_detections; 291, identifier:self; 292, identifier:families; 293, attribute; 294, identifier:template_name; 295, identifier:template; 296, identifier:template; 297, identifier:detections; 298, list_comprehension; 299, identifier:d; 300, identifier:detect_time; 301, attribute; 302, attribute; 303, attribute; 304, attribute; 305, identifier:d; 306, identifier:all_detections; 307, string_content:metric is not cor_sum or avg_cor; 308, attribute; 309, binary_operator:d.detect_val / d.no_chans; 310, identifier:d; 311, identifier:all_detections; 312, tuple; 313, for_in_clause; 314, string; 315, identifier:d; 316, integer:0; 317, identifier:ind; 318, unary_operator; 319, identifier:np; 320, identifier:where; 321, comparison_operator:detect_vals[matching_time_indeces] == ind[0]; 322, attribute; 323, identifier:name; 324, identifier:d; 325, for_in_clause; 326, if_clause; 327, identifier:d; 328, identifier:detect_val; 329, identifier:d; 330, identifier:no_chans; 331, identifier:d; 332, identifier:detect_time; 333, identifier:d; 334, identifier:detect_val; 335, call; 336, identifier:time; 337, attribute; 338, attribute; 339, attribute; 340, attribute; 341, identifier:d; 342, identifier:all_detections; 343, string_content:metric is not cor_sum or avg_cor; 344, integer:1; 345, subscript; 346, subscript; 347, identifier:fam; 348, identifier:template; 349, identifier:d; 350, identifier:declustered_detections; 351, comparison_operator:d.template_name == template_name; 352, identifier:_get_origin; 353, argument_list; 354, identifier:d; 355, identifier:detect_val; 356, identifier:d; 357, identifier:no_chans; 358, call; 359, identifier:time; 360, identifier:d; 361, identifier:detect_val; 362, identifier:detect_vals; 363, identifier:matching_time_indeces; 364, identifier:ind; 365, integer:0; 366, attribute; 367, identifier:template_name; 368, attribute; 369, identifier:_get_origin; 370, argument_list; 371, identifier:d; 372, identifier:template_name; 373, identifier:d; 374, identifier:event; 375, attribute; 376, identifier:d; 377, identifier:event
code: def decluster(self, trig_int, timing='detect', metric='avg_cor'):
          """
          De-cluster a Party of detections by enforcing a detection separation.
  
          De-clustering occurs between events detected by different (or the same)
          templates. If multiple detections occur within trig_int then the
          preferred detection will be determined by the metric argument. This
          can be either the average single-station correlation coefficient which
          is calculated as Detection.detect_val / Detection.no_chans, or the
          raw cross channel correlation sum which is simply Detection.detect_val.
  
          :type trig_int: float
          :param trig_int: Minimum detection separation in seconds.
          :type metric: str
          :param metric: What metric to sort peaks by. Either 'avg_cor' which
              takes the single station average correlation or 'cor_sum' which
              takes the total correlation sum across all channels.
          :type timing: str
          :param timing:
              Either 'detect' or 'origin' to decluster based on either the
              detection time or the origin time.
  
          .. Warning::
              Works in place on object, if you need to keep the original safe
              then run this on a copy of the object!
  
          .. rubric:: Example
  
          >>> party = Party().read()
          >>> len(party)
          4
          >>> declustered = party.decluster(20)
          >>> len(party)
          3
          """
          all_detections = []
          for fam in self.families:
              all_detections.extend(fam.detections)
          if timing == 'detect':
              if metric == 'avg_cor':
                  detect_info = [(d.detect_time, d.detect_val / d.no_chans)
                                 for d in all_detections]
              elif metric == 'cor_sum':
                  detect_info = [(d.detect_time, d.detect_val)
                                 for d in all_detections]
              else:
                  raise MatchFilterError('metric is not cor_sum or avg_cor')
          elif timing == 'origin':
              if metric == 'avg_cor':
                  detect_info = [(_get_origin(d.event).time,
                                  d.detect_val / d.no_chans)
                                 for d in all_detections]
              elif metric == 'cor_sum':
                  detect_info = [(_get_origin(d.event).time, d.detect_val)
                                 for d in all_detections]
              else:
                  raise MatchFilterError('metric is not cor_sum or avg_cor')
          else:
              raise MatchFilterError('timing is not detect or origin')
          min_det = sorted([d[0] for d in detect_info])[0]
          detect_vals = np.array([d[1] for d in detect_info])
          detect_times = np.array([
              _total_microsec(d[0].datetime, min_det.datetime)
              for d in detect_info])
          # Trig_int must be converted from seconds to micro-seconds
          peaks_out = decluster(
              peaks=detect_vals, index=detect_times, trig_int=trig_int * 10 ** 6)
          # Need to match both the time and the detection value
          declustered_detections = []
          for ind in peaks_out:
              matching_time_indeces = np.where(detect_times == ind[-1])[0]
              matches = matching_time_indeces[
                  np.where(detect_vals[matching_time_indeces] == ind[0])[0][0]]
              declustered_detections.append(all_detections[matches])
          # Convert this list into families
          template_names = list(set([d.template_name
                                     for d in declustered_detections]))
          new_families = []
          for template_name in template_names:
              template = [fam.template for fam in self.families
                          if fam.template.name == template_name][0]
              new_families.append(Family(
                  template=template,
                  detections=[d for d in declustered_detections
                              if d.template_name == template_name]))
          self.families = new_families
          return self