# spacepy.pycdf.istp.VarBundle

class spacepy.pycdf.istp.VarBundle(source, name=None)

  Collective handling of ISTP-compliant variable and its dependencies.

  Representation of an ISTP-compliant variable bundled together with its dependencies to enable aggregate operations. Normally used to copy a subset of data from one CDF or SpaceData to another by chaining operations, or to load just the relevant data from a CDF into a `SpaceData`.

  `VarBundle` operates on a single variable within a file or SpaceData and its various dependencies, uncertainties, labels, etc. That variable can be specified one of two ways. An open CDF file or SpaceData can be passed as the first parameter, and the name of a variable within it as the second parameter. Or, for CDF files, a `Var` can be passed as the only parameter, implicitly defining the input file (the CDF containing that variable).

  Unusual or indecipherable error messages may indicate an ISTP compliance issue; see `VariableChecks` for some checks.

  Parameters:
    source `CDF`, `SpaceData`, or `Var`

      SpaceData or open CDF containing the variable to process, or the CDF variable itself.

    name `str`

      Name of the variable within `source` to process (“main variable”).

  See also

  `datamodel.fromCDF`
  `pycdf.CDF.copy`

  Notes

  If using `SpaceData` input, the contents are assumed to be ISTP compliant. In particular, the following attributes of the enclosed `dmarray` are used (italics denotes required):

  > - DEPEND_0, DEPEND_1, etc.

  > - LABL_PTR_0, LABL_PTR_1, etc.

  > - DELTA_PLUS_VAR, DELTA_MINUS_VAR

  > - VALIDMIN, VALIDMAX, FILLVAL

  Examples

      >>> import spacepy.pycdf
      >>> import spacepy.pycdf.istp
      >>> #https://rbsp-ect.newmexicoconsortium.org/data_pub/rbspa/hope/level3/pitchangle/2012/
      >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
      >>> infile['FPDU']
      <Var:
      CDF_FLOAT [3228, 11, 72]
      >
      >>> infile['FPDU'].attrs
      <zAttrList:
      CATDESC: HOPE differential proton flux [CDF_CHAR]
      DEPEND_0: Epoch_Ion [CDF_CHAR]
      DEPEND_1: PITCH_ANGLE [CDF_CHAR]
      DEPEND_2: HOPE_ENERGY_Ion [CDF_CHAR]
      ...
      >
      >>> b = spacepy.pycdf.istp.VarBundle(infile['FPDU'])
      >>> b = spacepy.pycdf.istp.VarBundle(infile, 'FPDU')  # Equivalent
      >>> outfile = spacepy.pycdf.CDF('output.cdf', create=True)
      >>> b.slice(1, 2, single=True).output(outfile)
      <VarBundle:
      FPDU: CDF_FLOAT [3228, 72]
      Epoch_Ion: CDF_EPOCH [3228]
          Epoch_Ion_DELTA: CDF_REAL4 [3228]
      PITCH_ANGLE: CDF_FLOAT ---
          Pitch_LABL: CDF_CHAR*5 ---
      HOPE_ENERGY_Ion: CDF_FLOAT [3228, 72]
          ENERGY_Ion_DELTA: CDF_FLOAT [3228, 72]
          Energy_LABL: CDF_CHAR*3 [72] NRV
      >
      >>> outfile['FPDU']
      <Var:
      CDF_FLOAT [3228, 72]
      >
      >>> outfile['FPDU'].attrs
      <zAttrList:
      CATDESC: HOPE differential proton flux [CDF_CHAR]
      DEPEND_0: Epoch_Ion [CDF_CHAR]
      DEPEND_1: HOPE_ENERGY_Ion [CDF_CHAR]
      ...
      >
      >>> outfile.close()
      >>> infile.close()

  `mean`(dim) | Take the mean of a dimension.
  `operations`() | Operations of this bundle
  `output`(output[, suffix]) | Output the variables as modified
  `slice`(dim[, start, stop, step, single]) | Slice on a single dimension
  `sum`(dim) | Sum across a dimension.
  `toSpaceData`([suffix]) | Return variables, as modified.
  `variables`() | Description of variable output from the bundle

  mean(dim)

    Take the mean of a dimension.

    Take mean of the main variable of the bundle across the given dimension. That dimension disappears from the output and dependencies (including their uncertainties) are assumed to be constant across the summed dimension. The uncertainty of the main variable, if any, is appropriately propagated.

    Invalid values are excluded fromthe mean. This does not work well for variables that define multiple VALIDMIN/VALIDMAX based on position within a dimension; the smallest VALIDMIN/largest VALIDMAX rather than the position-specific value.

    Averaging occurs after slicing, to allow averaging of a subset of a dimension. A single element slice (which removes the dimension) is incompatible with averaging over that dimension.

    There is not currently a way to “undo” a mean; create a new bundle instead.

    Parameters:
      dim int

        CDF dimension to average. This is the dimension as specified in the CDF (0-base for RV variables, 1-base for NRV) and does not change with successive slicing or summing. This must be a positive number (no support for e.g. -1 for last dimension.)

    Returns:
      VarBundle

        This bundle, for method chaining. This is not a copy: the original object is updated.

    Examples

    See the `VarBundle` examples for creating output.

        >>> import spacepy.pycdf
        >>> import spacepy.pycdf.istp
        >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
        >>> b = spacepy.pycdf.istp.VarBundle(infile['Counts_P'])
        >>> #Average over dimension 1 (pitch angle)
        >>> b.mean(1)
        >>> #Get a new bundle (without the previous sum)
        >>> b = spacepy.pycdf.istp.VarBundle(infile['Counts_P'])
        >>> #Average over first 10 elements of dimension 2 (energy bins)
        >>> b.slice(2, 0, 10).mean(2)
        >>> infile.close()

  output(output, suffix=None)

    Output the variables as modified

    Parameters:
      output `CDF`, `SpaceData`

        Output container to receive the new data, may be an open CDF file or a SpaceData.

      suffix str

        Suffix to append to the name of any variables that are changed for the output. This allows the output to contain multiple variables derived from the same input variable. The main variable and its DELTA variables will always have the suffix applied. Any dependencies will have the suffix applied only if they have changed from the input CDF (e.g. from slicing.)

    Returns:
      VarBundle

        This bundle, for method chaining.

    See also

    `toSpaceData`

    Examples

        >>> import spacepy.pycdf
        >>> import spacepy.pycdf.istp
        >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
        >>> b = spacepy.pycdf.istp.VarBundle(infile['FPDU'])
        >>> outfile = spacepy.pycdf.CDF('output.cdf', create=True)
        >>> #Output the low energy half in one variable
        >>> b.slice(2, 0, 36).output(outfile, suffix='_LoE')
        >>> #And the high energy half in another variable
        >>> b.slice(2, 36, 72).output(outfile, suffix='_HiE')
        >>> outfile.close()
        >>> infile.close()

  operations()

    Operations of this bundle

    Provides information describing the operations this bundle would perform.

    Returns:
      list

        Each element is a tuple: first element is a string with the name of the operation (i.e. method of `VarBundle`), next is also a tuple of positional arguments, and finally a dict of keyword arguments.

    Examples

        >>> import spacepy.pycdf
        >>> import spacepy.pycdf.istp
        >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
        >>> b = spacepy.pycdf.istp.VarBundle(infile['FPDU'])
        >>> b.slice(1, 2, single=True).operations()
          [('slice', (1, 2), {'single': True})]
        >>> #Apply same operations to a different variable
        >>> b2 = spacepy.pycdf.istp.VarBundle(infile['FEDU'])
        >>> for op, args, kwargs in b2.operations():
        ...     getattr(b2, op)(*args, **kwargs)

  slice(dim, start=None, stop=None, step=None, single=False)

    Slice on a single dimension

    Selects subset of a dimension to include in the output. Slicing is done with reference to the dimensions of the main variable and the corresponding dimensions of all other variables are sliced similarly. The first non-record dimension of the variable is always 1; 0 is the record dimension (and is ignored for NRV variables). Multiple slices can be applied to select subsets of multiple dimensions; however, if one dimension is indexed multiple times, only the last one in the chain takes effect.

    Interpretation of the slice parameters is like normal Python slicing, including the ability to use negative values, etc.

    Passing in only a dimension “resets” the slice to include the entire dimension.

    Parameters:
      dim int

        CDF dimension to slice on. This is the dimension as specified in the CDF (0-base for RV variables, 1-base for NRV) and does not change with successive slicing. Each dimension can only be sliced once.

      single bool

        Treat `start` as a single index and return only that index (reducing dimensionality of the data by one.)

      start int

        Index of first element of `dim` to include in the output. This can also be a sequence of indices to include, in which case `stop` and `step` must not be specified. This can be substantially slower than specifying `stop` and `step`.

      stop int

        Index of first element of `dim` to exclude from the output.

      step int

        Increment between elements to include in the output.

    Returns:
      VarBundle

        This bundle, for method chaining. This is not a copy: the original object is updated.

    Examples

    See the `VarBundle` examples for creating output from the slices.

        >>> import spacepy.pycdf
        >>> import spacepy.pycdf.istp
        >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
        >>> b = spacepy.pycdf.istp.VarBundle(infile['FPDU'])
        >>> #Select index 2 from axis 1
        >>> b.slice(1, 2, single=True)
        >>> #Select from index 5 to end for axis 2, keeping index 2 from axis 1
        >>> b.slice(2, 5)
        >>> #Select 10 through 15 on axis 2, but all of axis 1
        >>> b.slice(1).slice(2, 10, 15)
        >>> #Select just record 5 and 10
        >>> b.slice(2).slice(0, [5, 10])
        >>> infile.close()

  sum(dim)

    Sum across a dimension.

    Total the main variable of the bundle across the given dimension. That dimension disappears from the output and dependencies (including their uncertainties) are assumed to be constant across the summed dimension. The uncertainty of the main variable, if any, is appropriately propagated (quadrature sum.)

    An invalid value for any element summed over will result in a fill value on the output. This does not work well for variables that define multiple VALIDMIN/VALIDMAX based on position within a dimension; the smallest VALIDMIN/largest VALIDMAX rather than the position-specific value.

    Summing occurs after slicing, to allow summing of a subset of a dimension. A single element slice (which removes the dimension) is incompatible with summing over that dimension.

    There is not currently a way to “undo” a sum; create a new bundle instead.

    Parameters:
      dim int

        CDF dimension to total. This is the dimension as specified in the CDF (0-base for RV variables, 1-base for NRV) and does not change with successive slicing or summing. This must be a positive number (no support for e.g. -1 for last dimension.)

    Returns:
      VarBundle

        This bundle, for method chaining. This is not a copy: the original object is updated.

    Examples

    See the `VarBundle` examples for creating output.

        >>> import spacepy.pycdf
        >>> import spacepy.pycdf.istp
        >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
        >>> b = spacepy.pycdf.istp.VarBundle(infile['Counts_P'])
        >>> #Total over dimension 1 (pitch angle)
        >>> b.sum(1)
        >>> #Get a new bundle (without the previous sum)
        >>> b = spacepy.pycdf.istp.VarBundle(infile['Counts_P'])
        >>> #Total over first 10 elements of dimension 2 (energy bins)
        >>> b.slice(2, 0, 10).sum(2)
        >>> infile.close()

  toSpaceData(suffix=None)

    Return variables, as modified.

    Convenience function to call `output()` on a new `SpaceData` and return it.

    Parameters:
      suffix str

        Appended to the name of variables changed on output; see `output()` for details.

    Returns:
      `datamodel.SpaceData`

        Data read from input and processed according to the defined operations.

    See also

    `output`

    Examples

        >>> import spacepy.pycdf
        >>> import spacepy.pycdf.istp
        >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
        >>> b = spacepy.pycdf.istp.VarBundle(infile['FPDU'])
        >>> data = b.slice(1, 2, single=True).toSpaceData()
        >>> infile.close()
        >>> data.tree()
        +
        |____ENERGY_Ion_DELTA
        |____Energy_LABL
        |____Epoch_Ion
        |____Epoch_Ion_DELTA
        |____FPDU
        |____HOPE_ENERGY_Ion

  variables()

    Description of variable output from the bundle

    Provides information describing the variables output from the bundle

    Returns:
      list

        Each element is a list-of-tuples. The list corresponds to a dimension of the master var: first the master var itself, then the uncertainties and labels associated with each dimension. Each element of these sublists is then a tuple of variable name and shape on the output (itself a tuple). If a variable isn’t included in the output (sliced away), its shape will be `None`.

    Examples

        >>> import spacepy.pycdf
        >>> import spacepy.pycdf.istp
        >>> infile = spacepy.pycdf.CDF('rbspa_rel04_ect-hope-PA-L3_20121201_v7.1.0.cdf')
        >>> b = spacepy.pycdf.istp.VarBundle(infile['FPDU'])
        >>> b.slice(1, 2, single=True).variables()
        [[('FPDU', (100, 72))],
         [('Epoch_Ion', (100,)), ('Epoch_Ion_DELTA', (100,))],
         [('PITCH_ANGLE', None), ('Pitch_LABL', None)],
         [('HOPE_ENERGY_Ion', (100, 72)),
          ('ENERGY_Ion_DELTA', (100, 72)),
          ('Energy_LABL', (72,))]]