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