code: def _filter_and_separate_computations(
      computations: metric_types.MetricComputations,
  ) -> MetricComputations:
      """Filters duplicate computations and separates non-derived and derived.
  
      All metrics are based on either direct computations using combiners or are
      based on the results of one or more other computations. This code separates
      the three types of computations so that only the combiner based computations
      are passed to the main combiner call and the remainder are processed after
      those combiners have run. Filtering is required because
      DerivedMetricComputations and CrossSliceMetricComputations typically include
      copies of the MetricComputations that they depend on in order to avoid having
      to pre-construct and pass around all the dependencies at the time the metrics
      are constructed. Instead, each derived metric creates a version of the metric
      it depends on and then this code de-dups computations that are identical so
      only one gets computed.
  
      Args:
        computations: Computations.
  
      Returns:
        Tuple of (metric computations, derived metric computations, cross slice
        metric computations, CI derived metric computations).
      """
      non_derived_computations = []
      processed_non_derived_computations = {}
      derived_computations = []
      processed_derived_computations = {}
      cross_slice_computations = []
      processed_cross_slice_computations = {}
      ci_derived_computations = []
      processed_ci_derived_computations = {}
      # The order of the computations matters (i.e. one computation may depend on
      # another). While there shouldn't be any differences in matching computations
      # the implemented hash is only based on combiner/result names and the keys. To
      # ensure we don't move a metric ahead of its dependencies (see b/205314632) we
      # will return the first computation added when there are duplicates.
      for c in computations:
          if isinstance(c, metric_types.MetricComputation):
              if c not in processed_non_derived_computations:
                  processed_non_derived_computations[c] = len(
                      non_derived_computations
                  )
                  non_derived_computations.append(c)
          # CIDerivedMetricComputation is inherited from DerivedMetricComputation, so
          # order of elif's matter here.
          elif isinstance(c, metric_types.CIDerivedMetricComputation):
              if c not in processed_ci_derived_computations:
                  processed_ci_derived_computations[c] = len(
                      ci_derived_computations
                  )
                  ci_derived_computations.append(c)
          elif isinstance(c, metric_types.DerivedMetricComputation):
              if c not in processed_derived_computations:
                  processed_derived_computations[c] = len(
                      derived_computations
                  )
                  derived_computations.append(c)
          elif isinstance(c, metric_types.CrossSliceMetricComputation):
              if c not in processed_cross_slice_computations:
                  processed_cross_slice_computations[c] = len(
                      cross_slice_computations
                  )
                  cross_slice_computations.append(c)
          else:
              raise TypeError(
                  "Unsupported metric computation type: {}".format(c)
              )
      return MetricComputations(
          non_derived_computations=non_derived_computations,
          derived_computations=derived_computations,
          cross_slice_computations=cross_slice_computations,
          ci_derived_computations=ci_derived_computations,
      )
  
imports: import copy
  import datetime
  import itertools
  import numbers
  from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Optional, Tuple, Type, TypeVar, Union
  import apache_beam
  import numpy
  from tensorflow_model_analysis import constants
  from tensorflow_model_analysis.api import types
  from tensorflow_model_analysis.evaluators import counter_util
  from tensorflow_model_analysis.evaluators import eval_saved_model_util
  from tensorflow_model_analysis.evaluators import evaluator
  from tensorflow_model_analysis.evaluators import jackknife
  from tensorflow_model_analysis.evaluators import keras_util
  from tensorflow_model_analysis.evaluators import metrics_validator
  from tensorflow_model_analysis.evaluators import poisson_bootstrap
  from tensorflow_model_analysis.extractors import slice_key_extractor
  from tensorflow_model_analysis.metrics import metric_specs
  from tensorflow_model_analysis.metrics import metric_types
  from tensorflow_model_analysis.metrics import metric_util
  from tensorflow_model_analysis.proto import config_pb2
  from tensorflow_model_analysis.slicer import slicer_lib
  from tensorflow_model_analysis.utils import model_util
  from tensorflow_model_analysis.utils import util
  from tensorflow_metadata.proto.v0 import schema_pb2
label_desc: Use image node_id 2 for calling a global function with example usage: _filter_and_separate_computations(computations) and returns: MetricComputations