Пример #1
0
def polarityReversal(timeData: TimeData,
                     reversal: Dict[str, bool],
                     inplace: bool = True) -> TimeData:
    """Multiply the data by -1 (polarity reversal)
    
    Parameters
    ----------
    timeData : TimeData
        timeData to normalise
    reversal : Dict[str, bool]
        Keys are channels and values are boolean flags for reversing
    inplace : bool, optional
        Whether to manipulate the data inplace

    Returns
    -------
    TimeData
        Normalised time data
    """
    if not inplace:
        timeData = timeData.copy()
    timeData.data = polarityReversalData(timeData.data, reversal)
    timeData.addComment(
        "Polarity reversal with parameters: {}".format(reversal))
    return timeData
Пример #2
0
def interpolateToSecond(timeData: TimeData, inplace: bool = True) -> TimeData:
    """Interpolate data to be on the second

    Some formats of time data (e.g. SPAM) do not start on the second with their sampling. This method interpolates so that sampling starts on the second and improves interoperability with other recording formats. 

    Parameters
    ----------
    timeData : TimeData
        Time data to interpolate onto the second
    inplace :  bool, optional
        Whether to do the interpolation inplace or not. Default is True.
    
    Returns
    -------
    TimeData
        Time data interpolated to start on the second
    """
    startTimeInterp, numSamplesInterp, dataInterp = interpolateToSecondData(
        timeData.data, timeData.sampleFreq, timeData.startTime
    )
    if not inplace:
        timeData = timeData.copy()
    timeData.numSamples = numSamplesInterp
    timeData.startTime = startTimeInterp
    # calculate end timeEnd
    timeData.stopTime = timeData.startTime + timedelta(
        seconds=(1.0 / timeData.sampleFreq) * (timeData.numSamples - 1)
    )
    timeData.data = dataInterp
    timeData.addComment(
        "Time data interpolated to nearest second. New start time {}, new end time {}, new number of samples {} ".format(
            timeData.startTime, timeData.stopTime, timeData.numSamples
        )
    )
    return timeData
Пример #3
0
def resample(timeData: TimeData, resampFreq: float, inplace: bool = True) -> TimeData:
    """Resample time data
    
    Parameters
    ----------
    timeData : TimeData
        timeData to filter
    resampFreq : float
        The frequency to resample to
    inplace : bool, optional
        Whether to manipulate the data inplace        

    Returns
    -------
    TimeData
        Filtered time data
    """
    origFreq = timeData.sampleFreq
    if not inplace:
        timeData = timeData.copy()
    timeData.data = resampleData(timeData.data, timeData.sampleFreq, resampFreq)
    # update the time info
    timeData.sampleFreq = resampFreq
    timeData.numSamples = timeData.data[timeData.chans[0]].size
    timeData.stopTime = timeData.startTime + timedelta(
        seconds=(1.0 / timeData.sampleFreq) * (timeData.numSamples - 1)
    )
    timeData.addComment(
        "Time data resampled from {:.6f} Hz to {:.6f} Hz".format(origFreq, resampFreq)
    )
    return timeData
Пример #4
0
def bandPass(
    timeData: TimeData, cutoffLow: float, cutoffHigh: float, inplace: bool = True
) -> TimeData:
    """Bandpass butterworth filter for time data
    
    Parameters
    ----------
    timeData : TimeData
        timeData to filter
    cutoff : float
        Cutoff frequency in Hz
    inplace : bool, optional
        Whether to manipulate the data inplace        

    Returns
    -------
    TimeData
        Filtered time data
    """
    if not inplace:
        timeData = timeData.copy()
    timeData.data = bandPassData(
        timeData.data, timeData.sampleFreq, cutoffLow, cutoffHigh
    )
    timeData.addComment(
        "Band pass filter applied with cutoffs {} Hz and {} Hz".format(
            cutoffLow, cutoffHigh
        )
    )
    return timeData
Пример #5
0
def normalise(timeData: TimeData, inplace: bool = True) -> TimeData:
    """Normalise time data
    
    Parameters
    ----------
    timeData : TimeData
        timeData to normalise
    inplace : bool, optional
        Whether to manipulate the data inplace

    Returns
    -------
    TimeData
        Normalised time data
    """
    if not inplace:
        timeData = timeData.copy()
    timeData.data = normaliseData(timeData.data)
    timeData.addComment("Data normalised")
    return timeData
Пример #6
0
def scale(timeData: TimeData,
          scalars: Dict[str, bool],
          inplace: bool = True) -> TimeData:
    """Scale the data by an arbitrary amount
    
    Parameters
    ----------
    timeData : TimeData
        timeData to normalise
    scalars : Dict[str, float]
        Keys are channels and values are boolean flags for reversing
    inplace : bool, optional
        Whether to manipulate the data inplace

    Returns
    -------
    TimeData
        Normalised time data
    """
    if not inplace:
        timeData = timeData.copy()
    timeData.data = scaleData(timeData.data, scalars)
    timeData.addComment("Time data scaled with scalars: {}".format(scalars))
    return timeData
Пример #7
0
def notchFilter(timeData: TimeData, notch: float, inplace: bool = True) -> TimeData:
    """Bandpass butterworth filter for time data
    
    Parameters
    ----------
    timeData : TimeData
        timeData to filter
    notch : float
        Frequency to notch filter in Hz
    inplace : bool, optional
        Whether to manipulate the data inplace        

    Returns
    -------
    TimeData
        Filtered time data
    """
    if not inplace:
        timeData = timeData.copy()
    timeData.data = notchFilterData(
        timeData.data, timeData.sampleFreq, notch, notch / 5.0
    )
    timeData.addComment("Notch filter applied at {} Hz".format(notch))
    return timeData
Пример #8
0
    def calibrate(
        self,
        timeData: TimeData,
        sensor: Dict[str, str],
        serial: Dict[str, int],
        chopper: Dict[str, bool],
    ) -> TimeData:
        """Calibrate time data

        For each channel in timeData, searches for a matching calibration file based on sensor type, serial number and chopper. If a calibration file is found, the channel is calibrated using the data in the file. If useTheoretical is False and no file is found, the data is not calibrated

        todo:
        If no calibration file is found and the channel is a magnetic data channel, a theoretical function can be used
    
        Parameters
        ----------
        timeData : TimeData
            TimeData object
        sensor : Dict
            Dictionary of sensor information with channels as the key and sensor as the value (sensor is a string)
        serial :
            Dictionary of serial information with channels as the key and sensor as the value (serial is a number)
        chopper :
            Dictionary of chopper information with channels as the key and sensor as the value (chopper is a bool)

        Returns
        -------
        timeData : TimeData
            Calibration TimeData object
        """
        calIO = CalibrationIO()
        # iterate over data
        for chan in timeData.chans:
            # output some info
            self.printText("Calibrating channel {}".format(chan))
            # try and find calibration file
            calFile, calFormat = self.getCalFile(sensor[chan], serial[chan],
                                                 chopper[chan])
            if calFile == "":
                # no file found
                if self.useTheoretical and isMagnetic(chan):
                    # use theoretical
                    calData = self.getTheoreticalCalData(sensor[chan])
                    timeData.data[chan] = self.calibrateChan(
                        timeData.data[chan], timeData.sampleFreq, calData)
                    timeData.addComment(
                        "Channel {} calibrated with theoretical calibration function"
                        .format(chan))
                    continue
                else:
                    self.printText(
                        "No Calibration data found - channel will not be calibrated"
                    )
                    timeData.addComment(
                        "Channel {} not calibrated".format(chan))
                    continue  # nothing to do

            # else file found
            # no need to separately apply static gain, already included in cal data
            calIO.refresh(calFile,
                          calFormat,
                          chopper=chopper[chan],
                          extend=self.extend)
            calData = calIO.read()
            self.printText(
                "Calibration file found for sensor {}, serial number {}, chopper {}: {}"
                .format(sensor[chan], serial[chan], chopper[chan], calFile))
            self.printText("Format: {}".format(calFormat))
            self.printText(
                "Static gain correction of {} applied to calibration data".
                format(calData.staticGain))
            # calibrate time data
            timeData.data[chan] = self.calibrateChan(timeData.data[chan],
                                                     timeData.sampleFreq,
                                                     calData)
            timeData.addComment(
                "Channel {} calibrated with calibration data from file {}".
                format(chan, calFile))
        # return calibrated time data
        return timeData