code: def compress_outs(op, not_required, inputs):
      """
      Helpful function that gets a Scan op, a list of indices indicating
      which outputs are not required anymore and should be removed, and
      a list of inputs to the apply node corresponding to the scan op and
      produces the list of inputs and outputs and the info dictionary where
      the indicated outputs are eliminated. Note that eliminating an output
      means removing its inputs from the inner function and from the
      node inputs, and changing the dictionary.
  
      """
      from pytensor.scan.op import ScanInfo
  
      op_info = op.info
      info = ScanInfo(
          n_seqs=op_info.n_seqs,
          mit_mot_in_slices=(),
          mit_mot_out_slices=(),
          mit_sot_in_slices=(),
          sit_sot_in_slices=(),
          n_nit_sot=0,
          n_shared_outs=0,
          n_non_seqs=0,
          as_while=op_info.as_while,
      )
  
      op_inputs = op.inner_inputs[: op_info.n_seqs]
      op_outputs = []
      node_inputs = inputs[: op_info.n_seqs + 1]
      map_old_new = OrderedDict()
  
      offset = 0
      ni_offset = op_info.n_seqs + 1
      i_offset = op_info.n_seqs
      o_offset = 0
      curr_pos = 0
      for idx in range(op_info.n_mit_mot):
          if offset + idx not in not_required:
              map_old_new[offset + idx] = curr_pos
              curr_pos += 1
              info = dataclasses.replace(
                  info,
                  mit_mot_in_slices=info.mit_mot_in_slices
                  + (op_info.mit_mot_in_slices[idx],),
                  mit_mot_out_slices=info.mit_mot_out_slices
                  + (op_info.mit_mot_out_slices[idx],),
              )
              # input taps
              for jdx in op_info.mit_mot_in_slices[idx]:
                  op_inputs += [op.inner_inputs[i_offset]]
                  i_offset += 1
              # output taps
              for jdx in op_info.mit_mot_out_slices[idx]:
                  op_outputs += [op.inner_outputs[o_offset]]
                  o_offset += 1
              # node inputs
              node_inputs += [inputs[ni_offset + idx]]
          else:
              o_offset += len(op_info.mit_mot_out_slices[idx])
              i_offset += len(op_info.mit_mot_in_slices[idx])
  
      offset += op_info.n_mit_mot
      ni_offset += op_info.n_mit_mot
  
      for idx in range(op_info.n_mit_sot):
          if offset + idx not in not_required:
              map_old_new[offset + idx] = curr_pos
              curr_pos += 1
              info = dataclasses.replace(
                  info,
                  mit_sot_in_slices=info.mit_sot_in_slices
                  + (op_info.mit_sot_in_slices[idx],),
              )
              # input taps
              for jdx in op_info.mit_sot_in_slices[idx]:
                  op_inputs += [op.inner_inputs[i_offset]]
                  i_offset += 1
              # output taps
              op_outputs += [op.inner_outputs[o_offset]]
              o_offset += 1
              # node inputs
              node_inputs += [inputs[ni_offset + idx]]
          else:
              o_offset += 1
              i_offset += len(op_info.mit_sot_in_slices[idx])
  
      offset += op_info.n_mit_sot
      ni_offset += op_info.n_mit_sot
      for idx in range(op_info.n_sit_sot):
          if offset + idx not in not_required:
              map_old_new[offset + idx] = curr_pos
              curr_pos += 1
              info = dataclasses.replace(
                  info,
                  sit_sot_in_slices=info.sit_sot_in_slices
                  + (op_info.sit_sot_in_slices[idx],),
              )
              # input taps
              op_inputs += [op.inner_inputs[i_offset]]
              i_offset += 1
              # output taps
              op_outputs += [op.inner_outputs[o_offset]]
              o_offset += 1
              # node inputs
              node_inputs += [inputs[ni_offset + idx]]
          else:
              o_offset += 1
              i_offset += 1
  
      offset += op_info.n_sit_sot
      ni_offset += op_info.n_sit_sot
      nit_sot_ins = []
      for idx in range(op_info.n_nit_sot):
          if offset + idx not in not_required:
              map_old_new[offset + idx] = curr_pos
              curr_pos += 1
              info = dataclasses.replace(
                  info, n_nit_sot=info.n_nit_sot + 1
              )
              op_outputs += [op.inner_outputs[o_offset]]
              o_offset += 1
              nit_sot_ins += [
                  inputs[ni_offset + idx + op_info.n_shared_outs]
              ]
          else:
              o_offset += 1
  
      offset += op_info.n_nit_sot
      shared_ins = []
      for idx in range(op_info.n_shared_outs):
          if offset + idx not in not_required:
              map_old_new[offset + idx] = curr_pos
              curr_pos += 1
              info = dataclasses.replace(
                  info, n_shared_outs=info.n_shared_outs + 1
              )
              op_outputs += [op.inner_outputs[o_offset]]
              o_offset += 1
              op_inputs += [op.inner_inputs[i_offset]]
              i_offset += 1
              shared_ins += [inputs[ni_offset + idx]]
          else:
              o_offset += 1
              i_offset += 1
      node_inputs += shared_ins
      node_inputs += nit_sot_ins
      # other stuff
      op_inputs += op.inner_inputs[i_offset:]
      info = dataclasses.replace(
          info, n_non_seqs=len(op.inner_inputs[i_offset:])
      )
      node_inputs += inputs[
          ni_offset + op_info.n_shared_outs + op_info.n_nit_sot :
      ]
      if op_info.as_while:
          op_outputs += [op.inner_outputs[o_offset]]
          map_old_new[o_offset] = len(op_outputs) - 1
          # map_old_new[len(op_outputs)-1] = o_offset
  
      return (op_inputs, op_outputs, info, node_inputs, map_old_new)
  
imports: import copy
  import dataclasses
  import logging
  from collections import OrderedDict, namedtuple
  from collections.abc import Sequence
  from itertools import chain
  from typing import TYPE_CHECKING, Callable, Optional, Union
  from typing import cast
  import numpy
  from pytensor import scalar
  from pytensor import tensor
  from pytensor.compile.profiling import ProfileStats
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Constant, Variable, equal_computations, graph_inputs
  from pytensor.graph.op import get_test_value
  from pytensor.graph.replace import clone_replace
  from pytensor.graph.type import HasDataType
  from pytensor.graph.utils import TestValueError
  from pytensor.tensor.basic import AllocEmpty, cast
  from pytensor.tensor.subtensor import set_subtensor
  from pytensor.tensor.variable import TensorConstant
label_desc: Use image node_id 5 for calling a global function with example usage: compress_outs(op, not_required, inputs) and returns: op_inputs,  op_outputs,  info,  node_inputs,  map_old_new