docs: def evaluate(self, reference_event_list, estimated_event_list, evaluated_length_seconds=None):
          """Evaluate file pair (reference and estimated)
  
          Parameters
          ----------
  
          reference_event_list : list of dict or dcase_util.containers.MetaDataContainer
              Reference event list.
  
          estimated_event_list : list of dict or dcase_util.containers.MetaDataContainer
              Estimated event list.
  
          evaluated_length_seconds : float, optional
              Evaluated length. If none given, maximum offset is used.
              Default value None
  
          Returns
          -------
          self
  
          """
  
          # Make sure input is dcase_util.containers.MetaDataContainer
          if not isinstance(reference_event_list, dcase_util.containers.MetaDataContainer):
              reference_event_list = dcase_util.containers.MetaDataContainer(reference_event_list)
  
          if not isinstance(estimated_event_list, dcase_util.containers.MetaDataContainer):
              estimated_event_list = dcase_util.containers.MetaDataContainer(estimated_event_list)
  
          # Check that input event list have event only from one file
          reference_files = reference_event_list.unique_files
          if len(reference_files) > 1:
              raise ValueError(
                  "reference_event_list contains events from multiple files. Evaluate only file by file."
              )
  
          estimated_files = estimated_event_list.unique_files
          if len(estimated_files) > 1:
              raise ValueError(
                  "estimated_event_list contains events from multiple files. Evaluate only file by file."
              )
  
          # Evaluate only valid events
          valid_reference_event_list = dcase_util.containers.MetaDataContainer()
          for item in reference_event_list:
              if 'event_onset' in item and 'event_offset' in item and 'event_label' in item:
                  valid_reference_event_list.append(item)
  
              elif 'onset' in item and 'offset' in item and 'event_label' in item:
                  valid_reference_event_list.append(item)
  
          reference_event_list = valid_reference_event_list
  
          valid_estimated_event_list = dcase_util.containers.MetaDataContainer()
          for item in estimated_event_list:
              if 'event_onset' in item and 'event_offset' in item and 'event_label' in item:
                  valid_estimated_event_list.append(item)
  
              elif 'onset' in item and 'offset' in item and 'event_label' in item:
                  valid_estimated_event_list.append(item)
  
          estimated_event_list = valid_estimated_event_list
  
          # Convert event list into frame-based representation
          reference_event_roll = util.event_list_to_event_roll(
              source_event_list=reference_event_list,
              event_label_list=self.event_label_list,
              time_resolution=self.time_resolution
          )
  
          estimated_event_roll = util.event_list_to_event_roll(
              source_event_list=estimated_event_list,
              event_label_list=self.event_label_list,
              time_resolution=self.time_resolution
          )
  
          if evaluated_length_seconds is None:
              evaluated_length_seconds = max(reference_event_list.max_offset, estimated_event_list.max_offset)
              evaluated_length_segments = int(math.ceil(evaluated_length_seconds * 1 / float(self.time_resolution)))
  
          else:
              evaluated_length_segments = int(math.ceil(evaluated_length_seconds * 1 / float(self.time_resolution)))
  
          self.evaluated_length_seconds += evaluated_length_seconds
          self.evaluated_files += 1
  
          reference_event_roll, estimated_event_roll = util.match_event_roll_lengths(
              reference_event_roll,
              estimated_event_roll,
              evaluated_length_segments
          )
  
          # Compute segment-based overall metrics
          for segment_id in range(0, reference_event_roll.shape[0]):
              annotated_segment = reference_event_roll[segment_id, :]
              system_segment = estimated_event_roll[segment_id, :]
  
              Ntp = sum(system_segment + annotated_segment > 1)
              Ntn = sum(system_segment + annotated_segment == 0)
              Nfp = sum(system_segment - annotated_segment > 0)
              Nfn = sum(annotated_segment - system_segment > 0)
  
              Nref = sum(annotated_segment)
              Nsys = sum(system_segment)
  
              S = min(Nref, Nsys) - Ntp
              D = max(0, Nref - Nsys)
              I = max(0, Nsys - Nref)
  
              self.overall['Ntp'] += Ntp
              self.overall['Ntn'] += Ntn
              self.overall['Nfp'] += Nfp
              self.overall['Nfn'] += Nfn
              self.overall['Nref'] += Nref
              self.overall['Nsys'] += Nsys
              self.overall['S'] += S
              self.overall['D'] += D
              self.overall['I'] += I
  
          # Compute segment-based class-wise metrics
          for class_id, class_label in enumerate(self.event_label_list):
              annotated_segment = reference_event_roll[:, class_id]
              system_segment = estimated_event_roll[:, class_id]
  
              Ntp = sum(system_segment + annotated_segment > 1)
              Ntn = sum(system_segment + annotated_segment == 0)
              Nfp = sum(system_segment - annotated_segment > 0)
              Nfn = sum(annotated_segment - system_segment > 0)
  
              Nref = sum(annotated_segment)
              Nsys = sum(system_segment)
  
              self.class_wise[class_label]['Ntp'] += Ntp
              self.class_wise[class_label]['Ntn'] += Ntn
              self.class_wise[class_label]['Nfp'] += Nfp
              self.class_wise[class_label]['Nfn'] += Nfn
              self.class_wise[class_label]['Nref'] += Nref
              self.class_wise[class_label]['Nsys'] += Nsys
  
          return self