Exemplo n.º 1
0
 def test_linear_interp(self):
     """PiecewisePolynomial1DFit: Test underlying 1st-order interpolator."""
     x = np.sort(np.random.rand(100)) * 4. - 2.5
     y = np.random.randn(100)
     interp = PiecewisePolynomial1DFit(max_degree=1)
     interp.fit(x, y)
     assert_almost_equal(interp(x), y, decimal=10)
     assert_almost_equal(_linear_interp(x, y, x), y, decimal=10)
     assert_almost_equal(interp(self.x),
                         _linear_interp(x, y, self.x),
                         decimal=10)
Exemplo n.º 2
0
 def test_fit_eval(self):
     """PiecewisePolynomial1DFit: Basic function fitting and evaluation."""
     interp = PiecewisePolynomial1DFit(max_degree=3)
     self.assertRaises(NotFittedError, interp, self.x)
     self.assertRaises(ValueError, interp.fit, [0, 0], [1, 2])
     interp.fit(self.x[::2], self.y[::2])
     y = interp(self.x)
     assert_almost_equal(y[5:-5], self.y[5:-5], decimal=10)
     # Fit a single data point
     interp.fit(self.x[0], self.y[0])
     y = interp(self.x)
     assert_equal(y, np.tile(self.y[0], self.x.shape))
Exemplo n.º 3
0
 def test_stepwise_interp(self):
     """PiecewisePolynomial1DFit: Test underlying zeroth-order interpolator."""
     x = np.sort(np.random.rand(100)) * 4. - 2.5
     y = np.random.randn(100)
     interp = PiecewisePolynomial1DFit(max_degree=0)
     interp.fit(x, y)
     assert_almost_equal(interp(x), y, decimal=10)
     assert_almost_equal(interp(x + 1e-15), y, decimal=10)
     assert_almost_equal(interp(x - 1e-15), y, decimal=10)
     assert_almost_equal(_stepwise_interp(x, y, x), y, decimal=10)
     assert_almost_equal(interp(self.x),
                         _stepwise_interp(x, y, self.x),
                         decimal=10)
Exemplo n.º 4
0
 def test_fit_eval(self):
     """PiecewisePolynomial1DFit: Basic function fitting and evaluation using data from a known function."""
     # Ignore test if SciPy version is below 0.7.0
     try:
         import scipy.interpolate
         scipy.interpolate.PiecewisePolynomial
     except AttributeError:
         return
     interp = PiecewisePolynomial1DFit(max_degree=3)
     self.assertRaises(NotFittedError, interp, self.x)
     self.assertRaises(ValueError, interp.fit, [0, 0], [1, 2])
     interp.fit(self.x[::2], self.y[::2])
     y = interp(self.x)
     assert_almost_equal(y[5:-5], self.y[5:-5], decimal=10)
     # Fit a single data point
     interp.fit(self.x[0], self.y[0])
     y = interp(self.x)
     assert_equal(y, np.tile(self.y[0], self.x.shape))
Exemplo n.º 5
0
     names += ' | ' + src['OName']
 ra, dec = atca_cat[src['Name']].radec() if use_atca else \
     (katpoint.deg2rad(src['_RAJ2000']), katpoint.deg2rad(src['_DEJ2000']))
 tags_ra_dec = katpoint.construct_radec_target(
     ra, dec).add_tags('J2000 ' + src['Type']).description
 # Extract polarisation data for the current source from pol table
 pol_data = pol_table[pol_table['Name'] == src['Name']]
 pol_freqs_MHz = katpoint.lightspeed / (0.01 * pol_data['lambda']) / 1e6
 pol_percent = pol_data['Pol']
 # Remove duplicate frequencies and fit linear interpolator to data as function of frequency
 pol_freq, pol_perc = [], []
 for freq in np.unique(pol_freqs_MHz):
     freqfind = (pol_freqs_MHz == freq)
     pol_freq.append(freq)
     pol_perc.append(pol_percent[freqfind].mean())
 pol_interp = PiecewisePolynomial1DFit(max_degree=1).fit(pol_freq, pol_perc)
 # Look up source name in 1Jy catalogue and extract its flux density model
 flux_target = flux_cat['1Jy ' + src['Name']]
 if flux_target is None:
     flux_target = flux_cat['1Jy ' + src['Name'][:7]]
 flux_str = flux_target.flux_model.description if flux_target is not None else ''
 target_description = ', '.join((names, tags_ra_dec, flux_str))
 target = katpoint.Target(target_description)
 # Evaluate polarised flux at expected centre frequency and filter on that
 pol_flux = target.flux_density(freq_MHz) * pol_interp(freq_MHz) / 100.
 if pol_flux < polflux_limit:
     print('%s skipped: polarised flux @ %d MHz: %.2f < %.2f' %
           (src['Name'], freq_MHz, pol_flux, polflux_limit))
     continue
 src_strings.append(target_description + '\n')
 print(
Exemplo n.º 6
0
    def get(self, name, select=False, extract=True, **kwargs):
        """Sensor values interpolated to correlator data timestamps.

        Time selection is disabled by default, as this is a more advanced data
        extraction method typically called by library routines that want to
        operate on the full array of sensor values. For additional allowed
        parameters when extracting categorical data, see the docstring for
        :func:`sensor_to_categorical`.

        Parameters
        ----------
        name : string
            Sensor name
        select : {False, True}, optional
            True if preset time selection will be applied to returned data
        extract : {True, False}, optional
            True if sensor data should be extracted from HDF5 file and cached
        categorical : {None, True, False}, optional
            Interpret sensor data as categorical or numerical (by default, data
            of type float is numerical and of any other type is categorical)
        interp_degree : int, optional
            Polynomial degree for interpolation of numerical data (default = 1)
        kwargs : dict, optional
            Additional parameters are passed to :func:`sensor_to_categorical`

        Returns
        -------
        data : array or :class:`CategoricalData` or :class:`SensorData` object
            If extraction is disabled, this will be a :class:`SensorData` object
            for uncached sensors. If selection is enabled, this will be a 1-D
            array of values, one per selected timestamp. If selection is
            disabled, this will be a 1-D array of values (of the same length as
            the :attr:`timestamps` attribute) for numerical data, and a
            :class:`CategoricalData` object for categorical data.

        Raises
        ------
        KeyError
            If sensor name was not found in cache and did not match virtual template

        """
        try:
            # First try to load the actual sensor data from cache (remember to call base class here!)
            sensor_data = super(SensorCache, self).__getitem__(name)
        except KeyError:
            # Otherwise, iterate through virtual sensor templates and look for a match
            for pattern, create_sensor in self.virtual.iteritems():
                # Expand variable names enclosed in braces to the relevant regular expression
                pattern = re.sub(
                    '({[a-zA-Z_]\w*})',
                    lambda m: '(?P<' + m.group(0)[1:-1] + '>[^//]+)', pattern)
                match = re.match(pattern, name)
                if match:
                    # Call sensor creation function with extracted variables from sensor name
                    sensor_data = create_sensor(self, name,
                                                **match.groupdict())
                    break
            else:
                raise KeyError(
                    "Unknown sensor '%s' (does not match actual name or virtual template)"
                    % (name, ))
        # If this is the first time this sensor is accessed, extract its data and store it in cache, if enabled
        if isinstance(sensor_data, SensorData) and extract:
            # Look up properties associated with this specific sensor
            self.props[name] = props = self.props.get(name, {})
            # Look up properties associated with this class of sensor
            for key, val in self.props.iteritems():
                if key[0] == '*' and name.endswith(key[1:]):
                    props.update(val)
            # Any properties passed directly to this method takes precedence
            props.update(kwargs)
            # Clean up sensor data if non-empty
            if len(sensor_data) > 0:
                # Sort sensor events in chronological order and discard duplicates and unreadable sensor values
                sensor_data = remove_duplicates(sensor_data)
                # Explicitly cast status to string type, as k7_augment produced sensors with integer statuses
                sensor_data.data = np.atleast_1d(sensor_data[
                    sensor_data['status'].astype('|S7') != 'failure'])
            if len(sensor_data) == 0:
                sensor_data = dummy_sensor_data(
                    name,
                    value=props.get('initial_value'),
                    dtype=sensor_data.dtype)
                logger.warning(
                    "No usable data found for sensor '%s' - replaced with dummy data (%r)"
                    % (name, sensor_data['value'][0]))
            # If this is the first time any sensor is accessed, obtain all data timestamps via indexer
            self.timestamps = self.timestamps[:] if not isinstance(
                self.timestamps, np.ndarray) else self.timestamps
            # Determine if sensor produces categorical or numerical data (by default, float data are non-categorical)
            categ = props.get('categorical',
                              not np.issubdtype(sensor_data.dtype, np.float))
            props['categorical'] = categ
            if categ:
                sensor_data = sensor_to_categorical(sensor_data['timestamp'],
                                                    sensor_data['value'],
                                                    self.timestamps,
                                                    self.dump_period, **props)
            else:
                # Interpolate numerical data onto data timestamps (fallback option is linear interpolation)
                props['interp_degree'] = interp_degree = props.get(
                    'interp_degree', 1)
                sensor_timestamps = sensor_data['timestamp']
                # Warn if sensor data will be extrapolated to start or end of data set with potentially bogus results
                if interp_degree > 0 and len(sensor_timestamps) > 1:
                    if sensor_timestamps[0] > self.timestamps[0]:
                        logger.warning((
                            "First data point for sensor '%s' only arrives %g seconds into data set"
                            % (name, sensor_timestamps[0] - self.timestamps[0])
                        ) + " - extrapolation may lead to ridiculous values")
                    if sensor_timestamps[-1] < self.timestamps[-1]:
                        logger.warning((
                            "Last data point for sensor '%s' arrives %g seconds before end of data set"
                            %
                            (name, self.timestamps[-1] - sensor_timestamps[-1])
                        ) + " - extrapolation may lead to ridiculous values")
                if PiecewisePolynomial1DFit is not None:
                    interp = PiecewisePolynomial1DFit(max_degree=interp_degree)
                    interp.fit(sensor_timestamps, sensor_data['value'])
                    sensor_data = interp(self.timestamps)
                else:
                    if interp_degree != 1:
                        logger.warning(
                            'Requested sensor interpolation with polynomial degree '
                            + str(interp_degree) +
                            ' but scikits.fitting not installed - falling back to linear interpolation'
                        )
                    sensor_data = _safe_linear_interp(sensor_timestamps,
                                                      sensor_data['value'],
                                                      self.timestamps)
            self[name] = sensor_data
        return sensor_data[self.keep] if select else sensor_data