def METHOD_NAME(self, points, progress=False):
    """Xform data.
    Parameters
    ----------
    points :        (N, 3) numpy array | pandas.DataFrame
                    Points to xform. DataFrame must have x/y/z columns.
    progress :      bool
                    Whether to show a progress bar.
    Returns
    -------
    pointsxf :      (N, 3) numpy array
                    Transformed points. Points that failed to transform will
                    be ``np.nan``.
    """
    if isinstance(points, pd.DataFrame):
        # Make sure x/y/z columns are present
        if np.any([c not in points for c in ['x', 'y', 'z']]):
            raise ValueError('points DataFrame must have x/y/z columns.')
        points = points[['x', 'y', 'z']].values
    if not isinstance(points, np.ndarray) or points.ndim != 2 or points.shape[1] != 3:
        raise TypeError('`points` must be numpy array of shape (N, 3) or '
                        'pandas DataFrame with x/y/z columns')
    # An [x, y, z] array for Java to write into
    q = jpype.JArray(jpype.JFloat, 1)([0, 0, 0])
    # It looks like we have to xform one point at a time
    xf = []
    for p in config.tqdm(points,
                         disable=not progress,
                         leave=False,
                         desc='Xforming'):
        # Xform this point
        self.transform.apply(p, q)
        # Keep track of new coordinates before moving to the next
        xf.append(list(q))
    return np.array(xf)