docs: def chop(self, *args, at={}, parent=None, verbose=True) -> wt_collection.Collection:
          """Divide the dataset into its lower-dimensionality components.
  
          Parameters
          ----------
          axis : str or int (args)
              Axes of the returned data objects. Strings refer to the names of
              axes in this object, integers refer to their index. Provide multiple
              axes to return multidimensional data objects.
          at : dict (optional)
              Choice of position along an axis. Keys are axis names, values are lists
              ``[position, input units]``. If exact position does not exist,
              the closest valid position is used.
          parent : WrightTools Collection instance (optional)
              Collection to place the new "chop" collection within. Default is
              None (new parent).
          verbose : bool (optional)
              Toggle talkback. Default is True.
  
          Returns
          -------
          WrightTools Collection
              Collection of chopped data objects.
  
          Examples
          --------
          >>> data.axis_names
          ['d2', 'w1', 'w2']
  
          Get all w1 wigners.
  
          >>> datas = data.chop('d2', 'w1')
          >>> len(datas)
          51
  
          Get 2D frequency at d2=0 fs.
  
          >>> datas = data.chop('w1', 'w2', at={'d2': [0, 'fs']})
          >>> len(datas)
          0
          >>> datas[0].axis_names
          ['w1', 'w2']
          >>> datas[0].d2[:]
          0.
  
          See Also
          --------
          collapse
              Collapse the dataset along one axis.
          split
              Split the dataset while maintaining its dimensionality.
          """
          from ._axis import operators, operator_to_identifier
  
          # parse args
          args = list(args)
          for i, arg in enumerate(args):
              if isinstance(arg, int):
                  args[i] = self._axes[arg].natural_name
              elif isinstance(arg, str):
                  # same normalization that occurs in the natural_name @property
                  arg = arg.strip()
                  for op in operators:
                      arg = arg.replace(op, operator_to_identifier[op])
                  args[i] = wt_kit.string2identifier(arg)
  
          # normalize the at keys to the natural name
          for k in [ak for ak in at.keys() if type(ak) == str]:
              for op in operators:
                  if op in k:
                      nk = k.replace(op, operator_to_identifier[op])
                      at[nk] = at[k]
                      at.pop(k)
                      k = nk
  
          # get output collection
          out = wt_collection.Collection(name="chop", parent=parent)
          # get output shape
          kept = args + [ak for ak in at.keys() if type(ak) == str]
          kept_axes = [self._axes[self.axis_names.index(a)] for a in kept]
          removed_axes = [a for a in self._axes if a not in kept_axes]
          removed_shape = wt_kit.joint_shape(*removed_axes)
          if removed_shape == ():
              removed_shape = (1,) * self.ndim
          removed_shape = list(removed_shape)
          for i in at.keys():
              if type(i) == int:
                  removed_shape[i] = 1
          removed_shape = tuple(removed_shape)
          # iterate
          i = 0
          for idx in np.ndindex(removed_shape):
              idx = np.array(idx, dtype=object)
              idx[np.array(removed_shape) == 1] = slice(None)
              for axis, point in at.items():
                  if type(axis) == int:
                      idx[axis] = point
                      continue
                  point, units = point
                  destination_units = self._axes[self.axis_names.index(axis)].units
                  point = wt_units.converter(point, units, destination_units)
                  axis_index = self.axis_names.index(axis)
                  axis = self._axes[axis_index]
                  idx_index = np.array(axis.shape) > 1
                  if np.sum(idx_index) > 1:
                      raise wt_exceptions.MultidimensionalAxisError("chop", axis.natural_name)
                  idx_index = list(idx_index).index(True)
                  idx[idx_index] = np.argmin(np.abs(axis[tuple(idx)] - point))
              data = out.create_data(name="chop%03i" % i)
              for v in self.variables:
                  kwargs = {}
                  kwargs["name"] = v.natural_name
                  kwargs["values"] = v[idx]
                  kwargs["units"] = v.units
                  kwargs["label"] = v.label
                  kwargs.update(v.attrs)
                  data.create_variable(**kwargs)
              for c in self.channels:
                  kwargs = {}
                  kwargs["name"] = c.natural_name
                  kwargs["values"] = c[idx]
                  kwargs["units"] = c.units
                  kwargs["label"] = c.label
                  kwargs["signed"] = c.signed
                  kwargs.update(c.attrs)
                  data.create_channel(**kwargs)
              new_axes = [a.expression for a in kept_axes if a.expression not in at.keys()]
              new_axis_units = [a.units for a in kept_axes if a.expression not in at.keys()]
              data.transform(*new_axes)
              for const in self.constant_expressions:
                  data.create_constant(const, verbose=False)
              for ax in self.axis_expressions:
                  if ax not in new_axes:
                      data.create_constant(ax, verbose=False)
              for j, units in enumerate(new_axis_units):
                  data.axes[j].convert(units)
              i += 1
          out.flush()
          # return
          if verbose:
              print("chopped data into %d piece(s)" % len(out), "in", new_axes)
          return out