Exemple #1
0
 def test_hlog(self):
     hlpos = trans.hlog(_xpos)
     hlneg = trans.hlog(_xneg)
     assert_almost_equal((hlpos[-1] - _ymax) / _ymax, 0, decimal=2)
     assert_almost_equal(hlpos, -hlneg[::-1])  # check symmetry
     # test that values get larger as b decreases
     hlpos10 = trans.hlog(_xpos, b=10)
     self.assertTrue(np.all(hlpos10 >= hlpos))
     # check that converges to tlog for large values
     tlpos = trans.tlog(_xpos)
     i = np.where(_xpos > 1e4)[0]
     tlpos_large = tlpos[i]
     hlpos_large = hlpos10[i]
     d = (hlpos_large - tlpos_large) / hlpos_large
     assert_almost_equal(d, np.zeros(len(d)), decimal=2)
     # test spline option
     transformation = Transformation(transform='hlog', direction='forward')
     result1 = transformation(_xall, use_spln=True)
     result2 = transformation(_xall, use_spln=False)
     d = (result1 - result2) / result1
     assert_almost_equal(d, np.zeros(len(d)), decimal=2)
    def transform(self, transform, direction='forward', share_transform=True,
                  channels=None, return_all=True, auto_range=True,
                  use_spln=True, get_transformer=False, ID=None,
                  apply_now=True,
                  args=(), **kwargs):
        '''
        Apply transform to each Measurement in the Collection.

        Return a new Collection with transformed data.

        {_containers_held_in_memory_warning}

        Parameters
        ----------
        {FCMeasurement_transform_pars}
        ID : hashable | None
            ID for the resulting collection. If None is passed, the original ID is used.

        Returns
        -------
        new : FCCollection
            New collection containing the transformed measurements.
        transformer : Transformation
            The Transformation applied to the measurements.
            Only returned if get_transformer=True & share_transform=True.

        Examples
        --------
        {FCMeasurement_transform_examples}
        '''
        new = self.copy()
        if share_transform:
            channel_meta = self.values()[0].channels
            channel_names = self.values()[0].channel_names
            if channels is None:
                channels = list(channel_names)
            else:
                channels = to_list(channels)
            ## create transformer
            if isinstance(transform, Transformation):
                transformer = transform
            else:
                if auto_range:  # determine transformation range
                    if 'd' in kwargs:
                        warnings.warn('Encountered both auto_range=True and user-specified range '
                                      'value in parameter d.\n '
                                      'Range value specified in parameter d is used.')
                    else:
                        # the -1 below because the channel numbers begin from 1 instead of 0 (this is fragile code)
                        ranges = [float(r['$PnR']) for i, r in channel_meta.iterrows() if
                                  channel_names[i - 1] in channels]

                        if not np.allclose(ranges, ranges[0]):
                            raise Exception('Not all specified channels have the same '
                                            'data range, therefore they cannot be '
                                            'transformed together.')

                        if transform in {'hlog', 'tlog', 'hlog_inv', 'tlog_inv'}:
                            # Hacky fix to make sure that 'd' is provided only
                            # for hlog / tlog transformations
                            kwargs['d'] = np.log10(ranges[0])
                transformer = Transformation(transform, direction, args, **kwargs)
                if use_spln:
                    xmax = self.apply(lambda x: x[channels].max().max(), applyto='data').max().max()
                    xmin = self.apply(lambda x: x[channels].min().min(), applyto='data').min().min()
                    transformer.set_spline(xmin, xmax)
            ## transform all measurements     
            for k, v in new.iteritems():
                new[k] = v.transform(transformer, channels=channels, return_all=return_all,
                                     use_spln=use_spln, apply_now=apply_now)
        else:
            for k, v in new.iteritems():
                new[k] = v.transform(transform, direction=direction, channels=channels,
                                     return_all=return_all, auto_range=auto_range,
                                     get_transformer=False,
                                     use_spln=use_spln, apply_now=apply_now, args=args, **kwargs)
        if ID is not None:
            new.ID = ID
        if share_transform and get_transformer:
            return new, transformer
        else:
            return new
    def transform(self, transform, direction='forward',
                  channels=None, return_all=True, auto_range=True,
                  use_spln=True, get_transformer=False, ID=None,
                  apply_now=True,
                  args=(), **kwargs):
        """
        Applies a transformation to the specified channels.

        The transformation parameters are shared between all transformed channels.
        If different parameters need to be applied to different channels,
        use several calls to `transform`.

        Parameters
        ----------
        {FCMeasurement_transform_pars}
        ID : hashable | None
            ID for the resulting collection. If None is passed, the original ID is used.

        Returns
        -------
        new : FCMeasurement
            New measurement containing the transformed data.
        transformer : Transformation
            The Transformation applied to the input measurement.
            Only returned if get_transformer=True.

        Examples
        --------
        {FCMeasurement_transform_examples}
        """
        # Create new measurement
        new = self.copy()
        data = new.data

        channels = to_list(channels)
        if channels is None:
            channels = data.columns
        ## create transformer
        if isinstance(transform, Transformation):
            transformer = transform
        else:
            if auto_range:  # determine transformation range
                if 'd' in kwargs:
                    warnings.warn(
                        'Encountered both auto_range=True and user-specified range value in '
                        'parameter d.\n Range value specified in parameter d is used.')
                else:
                    channel_meta = self.channels
                    # the -1 below because the channel numbers begin from 1 instead of 0
                    # (this is fragile code)
                    ranges = [float(r['$PnR']) for i, r in channel_meta.iterrows() if
                              self.channel_names[i - 1] in channels]
                    if not np.allclose(ranges, ranges[0]):
                        raise Exception("""Not all specified channels have the same data range,
                            therefore they cannot be transformed together.\n
                            HINT: Try transforming one channel at a time.
                            You'll need to provide the name of the channel in the transform.""")

                    if transform in {'hlog', 'tlog', 'hlog_inv', 'tlog_inv'}:
                        # Hacky fix to make sure that 'd' is provided only
                        # for hlog / tlog transformations
                        kwargs['d'] = np.log10(ranges[0])
            transformer = Transformation(transform, direction, args, **kwargs)
        ## create new data
        transformed = transformer(data[channels], use_spln)
        if return_all:
            new_data = data
        else:
            new_data = data.filter(channels)
        new_data[channels] = transformed
        ## update new Measurement
        new.data = new_data

        if ID is not None:
            new.ID = ID
        if get_transformer:
            return new, transformer
        else:
            return new
    def transform(self, transform, direction='forward', share_transform=True,
                  channels=None, return_all=True, auto_range=True,
                  use_spln=True, get_transformer=False, ID=None,
                  apply_now=True,
                  args=(), **kwargs):
        '''
        Apply transform to each Measurement in the Collection.

        Return a new Collection with transformed data.

        {_containers_held_in_memory_warning}

        Parameters
        ----------
        {FCMeasurement_transform_pars}
        ID : hashable | None
            ID for the resulting collection. If None is passed, the original ID is used.

        Returns
        -------
        new : FCCollection
            New collection containing the transformed measurements.
        transformer : Transformation
            The Transformation applied to the measurements.
            Only returned if get_transformer=True & share_transform=True.

        Examples
        --------
        {FCMeasurement_transform_examples}
        '''
        new = self.copy()
        if share_transform:
            channel_meta = self.values()[0].channels
            channel_names = self.values()[0].channel_names
            if channels is None:
                channels = list(channel_names)
            else:
                channels = to_list(channels)
            ## create transformer
            if isinstance(transform, Transformation):
                transformer = transform
            else:
                if auto_range:  # determine transformation range
                    if 'd' in kwargs:
                        warnings.warn('Encountered both auto_range=True and user-specified range '
                                      'value in parameter d.\n '
                                      'Range value specified in parameter d is used.')
                    else:
                        # the -1 below because the channel numbers begin from 1 instead of 0 (this is fragile code)
                        ranges = [float(r['$PnR']) for i, r in channel_meta.iterrows() if
                                  channel_names[i - 1] in channels]

                        if not np.allclose(ranges, ranges[0]):
                            raise Exception('Not all specified channels have the same '
                                            'data range, therefore they cannot be '
                                            'transformed together.')
                        kwargs['d'] = np.log10(ranges[0])
                transformer = Transformation(transform, direction, args, **kwargs)
                if use_spln:
                    xmax = self.apply(lambda x: x[channels].max().max(), applyto='data').max().max()
                    xmin = self.apply(lambda x: x[channels].min().min(), applyto='data').min().min()
                    transformer.set_spline(xmin, xmax)
            ## transform all measurements     
            for k, v in new.iteritems():
                new[k] = v.transform(transformer, channels=channels, return_all=return_all,
                                     use_spln=use_spln, apply_now=apply_now)
        else:
            for k, v in new.iteritems():
                new[k] = v.transform(transform, direction=direction, channels=channels,
                                     return_all=return_all, auto_range=auto_range,
                                     get_transformer=False,
                                     use_spln=use_spln, apply_now=apply_now, args=args, **kwargs)
        if ID is not None:
            new.ID = ID
        if share_transform and get_transformer:
            return new, transformer
        else:
            return new