class_docstr: Encodes each NoteSequence example and emits the results in a tf.Example.
class_docstr_tok: ["Encodes","each","NoteSequence","example","and","emits","the","results","in","a","tf.Example","."]
code: def _process_ns(self, ns):
      if self._filters:
          if ns.total_time > self._filters["max_total_time"]:
              logging.info(
                  "Skipping %s: total_time=%f", ns.id, ns.total_time
              )
              beam_metrics.counter(
                  "ExtractExamplesDoFn", "filtered-too-long"
              ).inc()
              return
          if len(ns.notes) > self._filters["max_num_notes"]:
              logging.info(
                  "Skipping %s: num_notes=%d", ns.id, len(ns.notes)
              )
              beam_metrics.counter(
                  "ExtractExamplesDoFn", "filtered-too-many-notes"
              ).inc()
              return
  
          try:
              qns = note_seq.quantize_note_sequence(
                  ns, steps_per_quarter=16
              )
          except (
              note_seq.BadTimeSignatureError,
              note_seq.NonIntegerStepsPerBarError,
              note_seq.NegativeTimeError,
          ):
              beam_metrics.counter(
                  "ExtractExamplesDoFn", "quantize-failed"
              ).inc()
              return
  
          vels = set()
          metric_positions = set()
          drums_only = True
          for note in qns.notes:
              drums_only &= note.is_drum
              if (
                  self._filters["is_drum"] is None
                  or note.is_drum == self._filters["is_drum"]
              ) and note.velocity > 0:
                  vels.add(note.velocity)
                  metric_positions.add(note.quantized_start_step % 16)
  
          if len(vels) < self._filters["min_velocities"]:
              beam_metrics.counter(
                  "ExtractExamplesDoFn", "filtered-min-velocities"
              ).inc()
              return
          if (
              len(metric_positions)
              < self._filters["min_metric_positions"]
          ):
              beam_metrics.counter(
                  "ExtractExamplesDoFn", "filtered-min-metric-positions"
              ).inc()
              return
          if self._filters["drums_only"] and not drums_only:
              beam_metrics.counter(
                  "ExtractExamplesDoFn", "filtered-drums-only"
              ).inc()
              return
  
      beam_metrics.counter(
          "ExtractExamplesDoFn", "unfiltered-sequences"
      ).inc()
      logging.info("Converting %s to tensors", ns.id)
      extracted_examples = self._config.data_converter.to_tensors(ns)
      if not extracted_examples.outputs:
          beam_metrics.counter(
              "ExtractExamplesDoFn", "empty-extractions"
          ).inc()
          return
      beam_metrics.counter(
          "ExtractExamplesDoFn", "extracted-examples"
      ).inc(len(extracted_examples.outputs))
      for _, outputs, controls, _ in zip(*extracted_examples):
          if controls.size:
              example_ns = self._config.data_converter.from_tensors(
                  [outputs], [controls]
              )[0]
          else:
              example_ns = self._config.data_converter.from_tensors(
                  [outputs]
              )[0]
          # Try to re-encode.
          # TODO(adarob): For now we filter and count examples that cannot be
          # re-extracted, but ultimately the converter should filter these or avoid
          # producing them all together.
          reextracted_examples = self._config.data_converter.to_tensors(
              example_ns
          ).inputs
          assert len(reextracted_examples) <= 1
          if not reextracted_examples:
              logging.warning(
                  "Extracted example NoteSequence does not reproduce example. "
                  "Skipping: %s",
                  example_ns,
              )
              beam_metrics.counter(
                  "ExtractExamplesDoFn", "empty-reextraction"
              ).inc()
              continue
          # Extra checks if the code returns multiple segments.
          # TODO(fjord): should probably make this recursive for cases with more
          # than 1 level of hierarchy.
          if isinstance(outputs, list):
              if len(outputs) != len(reextracted_examples[0]):
                  logging.warning(
                      "Re-extracted example tensor has different number of segments. "
                      "ID: %s. original %d, reextracted %d. Skipping.",
                      ns.id,
                      len(outputs),
                      len(reextracted_examples[0]),
                  )
                  beam_metrics.counter(
                      "ExtractExamplesDoFn",
                      "different-reextraction-count",
                  ).inc()
                  continue
              for i in range(len(outputs)):
                  if not np.array_equal(
                      reextracted_examples[0][i], outputs[i]
                  ):
                      logging.warning(
                          "Re-extracted example tensor does not equal original example. "
                          "ID: %s. Index %d. NoteSequence: %s",
                          ns.id,
                          i,
                          example_ns,
                      )
                      beam_metrics.counter(
                          "ExtractExamplesDoFn",
                          "different-reextraction",
                      ).inc()
          yield example_ns, ns.id
  
file_path: magenta/magenta/models/music_vae/preprocess_tfrecord.py
imports: import typing
  from absl import app
  from absl import flags
  from absl import logging
  import apache_beam
  from apache_beam import typehints
  from apache_beam.metrics import Metrics
  from magenta.models.music_vae import configs
  import note_seq
  from note_seq.sequences_lib import split_note_sequence_on_time_changes
  import numpy
label_desc: Use image node_id 2 for calling the ExtractExamplesDoFn obj's underlying member method code with example usage: obj._process_ns(ns) without return types