Пример #1
0
    def getPhysicalSamples(self, **kwargs):
        """Get ascii data scaled to physical values
        
        Warnings
        --------
        No scaling happens in getPhysicalSamples. Ascii data is assumed to be properly scaled to mV for magnetic channels and mV/km for electric channels (i.e. field units)

        Parameters
        ----------
        chans : List[str]
            List of channels to return if not all are required
        startSample : int
            First sample to return
        endSample : int
            Last sample to return
        remaverage : bool
            Remove average from the data
        remzeros : bool
            Remove zeroes from the data
        remnans: bool
            Remove NanNs from the data

        Returns
        -------
        TimeData
            Time data object
        """
        options = self.parseGetDataKeywords(kwargs)
        timeData = self.getUnscaledSamples(
            chans=options["chans"],
            startSample=options["startSample"],
            endSample=options["endSample"],
        )

        # no further scaling applied to ascii data
        for chan in options["chans"]:
            # if remove zeros - False by default
            if options["remzeros"]:
                timeData.data[chan] = removeZerosSingle(timeData.data[chan])
            # if remove nans - False by default
            if options["remnans"]:
                timeData.data[chan] = removeNansSingle(timeData.data[chan])
            # remove the average from the data - True by default
            # do this after all scaling and removing nans and zeros
            if options["remaverage"]:
                timeData.data[chan] = timeData.data[chan] - np.average(
                    timeData.data[chan]
                )

        timeData.addComment(
            "Remove zeros: {}, remove nans: {}, remove average: {}".format(
                options["remzeros"], options["remnans"], options["remaverage"]
            )
        )
        return timeData
Пример #2
0
    def getPhysicalSamples(self, **kwargs) -> TimeData:
        """Get data scaled to physical values

        Parameters
        ----------
        chans : List[str]
            List of channels to return if not all are required
        startSample : int
            First sample to return
        endSample : int
            Last sample to return
        remaverage : bool
            Remove average from the data
        remzeros : bool
            Remove zeroes from the data
        remnans: bool
            Remove NanNs from the data

        Returns
        -------
        TimeData
            Time data object
        """
        options = self.parseGetDataKeywords(kwargs)
        # get data
        timeData = self.getUnscaledSamples(
            chans=options["chans"],
            startSample=options["startSample"],
            endSample=options["endSample"],
        )
        # need to remove the gain
        for chan in options["chans"]:
            # remove the gain
            timeData.data[
                chan] = 1.0 * timeData.data[chan] / self.getChanGain1(chan)
            timeData.addComment(
                "Scaling channel {} with scalar {} to give mV".format(
                    chan, 1.0 / self.getChanGain1(chan)))

            # divide by distance in km
            if chan == "Ex":
                # multiply by 1000/self.getChanDx same as dividing by dist in km
                timeData.data[
                    chan] = 1000 * timeData.data[chan] / self.getChanDx(chan)
                timeData.addComment(
                    "Dividing channel {} by electrode distance {} km to give mV/km"
                    .format(chan,
                            self.getChanDx(chan) / 1000.0))
            if chan == "Ey":
                # multiply by 1000/self.getChanDy same as dividing by dist in km
                timeData.data[
                    chan] = 1000 * timeData.data[chan] / self.getChanDy(chan)
                timeData.addComment(
                    "Dividing channel {} by electrode distance {} km to give mV/km"
                    .format(chan,
                            self.getChanDy(chan) / 1000.0))

            # if remove zeros - False by default
            if options["remzeros"]:
                timeData.data[chan] = removeZerosSingle(timeData.data[chan])
            # if remove nans - False by default
            if options["remnans"]:
                timeData.data[chan] = removeNansSingle(timeData.data[chan])
            # remove the average from the data - True by default
            if options["remaverage"]:
                timeData.data[chan] = timeData.data[chan] - np.average(
                    timeData.data[chan])

        # add comments
        timeData.addComment(
            "The required Phoneix scaling to field units is still unverified. This is experimental and use cautiously."
        )
        timeData.addComment(
            "Remove zeros: {}, remove nans: {}, remove average: {}".format(
                options["remzeros"], options["remnans"],
                options["remaverage"]))
        return timeData
Пример #3
0
    def getPhysicalSamples(self, **kwargs):
        r"""Get data scaled to physical values
        
        Depending on the data format, the scalings required to convert to field physical units is different. The method in the base DataReader class covers ATS and internal file format.

        resistics will always provide physical samples in field units. That means

        - Electrical channels in mV/km
        - Magnetic channels in mV
        - To get magnetic fields in nT, calibration needs to be performed
        
        If the channel header scaling_applied is set to True, no scaling of the unscaled data is done. This is to cover the internal data format where all scalings may already have been applied.

        Notes
        -----
        The raw data units for ATS data are in counts. To get data in field units, ATS data is first multipled by the least significat bit (lsb) defined in the header files,

        .. math::  
        
            data = data * lsb,
        
        giving data in mV. The lsb includes the gain removal, so no separate gain removal needs to be performed.
        
        For electrical channels, there is additional step of dividing by the electrode spacing, which is provided in metres. The extra factor of a 1000 is to convert this to km to give mV/km for electric channels
        
        .. math::   
            
            data = \frac{1000 * data}{electrodeSpacing}
        
        Finally, to get magnetic channels in nT, the magnetic channels need to be calibrated.

        Parameters
        ----------
        chans : List[str]
            List of channels to return if not all are required
        startSample : int
            First sample to return
        endSample : int
            Last sample to return
        remaverage : bool
            Remove average from the data
        remzeros : bool
            Remove zeroes from the data
        remnans: bool
            Remove NanNs from the data

        Returns
        -------
        TimeData
            Time data object
        """
        options = self.parseGetDataKeywords(kwargs)
        timeData = self.getUnscaledSamples(
            chans=options["chans"],
            startSample=options["startSample"],
            endSample=options["endSample"],
        )
        # multiply each chan by least significant bit of chan
        for chan in options["chans"]:
            if not self.getChanScalingApplied(chan):
                # apply LSB to give data in mV
                timeData.data[chan] = timeData.data[chan] * self.getChanLSB(
                    chan)
                timeData.addComment(
                    "Scaling channel {} with scalar {} to give mV".format(
                        chan, self.getChanLSB(chan)))

                # divide by the distance - this should only be for the electric channels
                # again, this might already be applied
                if chan == "Ex":
                    # multiply by 1000/self.getChanDx same as dividing by dist in km
                    timeData.data[chan] = (1000 * timeData.data[chan] /
                                           self.getChanDx(chan))
                    timeData.addComment(
                        "Dividing channel {} by electrode distance {} km to give mV/km"
                        .format(chan,
                                self.getChanDx(chan) / 1000.0))
                if chan == "Ey":
                    # multiply by 1000/self.getChanDy same as dividing by dist in km
                    timeData.data[chan] = (1000 * timeData.data[chan] /
                                           self.getChanDy(chan))
                    timeData.addComment(
                        "Dividing channel {} by electrode distance {} km to give mV/km"
                        .format(chan,
                                self.getChanDy(chan) / 1000.0))

            # if remove zeros - False by default
            if options["remzeros"]:
                timeData.data[chan] = removeZerosSingle(timeData.data[chan])
            # if remove nans - False by default
            if options["remnans"]:
                timeData.data[chan] = removeNansSingle(timeData.data[chan])
            # remove the average from the data - True by default
            # do this after all scaling and removing nans and zeros
            if options["remaverage"]:
                timeData.data[chan] = timeData.data[chan] - np.average(
                    timeData.data[chan])

        timeData.addComment(
            "Remove zeros: {}, remove nans: {}, remove average: {}".format(
                options["remzeros"], options["remnans"],
                options["remaverage"]))
        return timeData
Пример #4
0
    def getPhysicalSamples(self, **kwargs):
        """Get data scaled to physical values
        
        resistics uses field units, meaning physical samples will return the following:

        - Electrical channels in mV/km
        - Magnetic channels in mV
        - To get magnetic fields in nT, calibration needs to be performed

        Notes
        -----
        The method getUnscaledSamples multiplies the raw data by the ts_lsb converting it to mV. Because gain is removed when getting the unscaledSamples and all channel data is in mV, the only calculation that has to be done is to divide by the dipole lengths (east-west spacing and north-south spacing).
        
        To get magnetic fields in nT, they have to be calibrated.

        Parameters
        ----------
        chans : List[str]
            List of channels to return if not all are required
        startSample : int
            First sample to return
        endSample : int
            Last sample to return
        remaverage : bool
            Remove average from the data
        remzeros : bool
            Remove zeroes from the data
        remnans: bool
            Remove NanNs from the data

        Returns
        -------
        TimeData
            Time data object
        """
        # initialise chans, startSample and endSample with the whole dataset
        options = self.parseGetDataKeywords(kwargs)
        # get data
        timeData = self.getUnscaledSamples(
            chans=options["chans"],
            startSample=options["startSample"],
            endSample=options["endSample"],
        )
        # Scalars are applied in getUnscaledSamples to convert to mV - this is for ease of calculation and because each data file in the run might have a separate scaling
        # all that is left is to divide by the dipole length in km and remove the average
        for chan in options["chans"]:
            if chan == "Ex":
                # multiply by 1000/self.getChanDx same as dividing by dist in km
                timeData.data[
                    chan] = 1000 * timeData.data[chan] / self.getChanDx(chan)
                timeData.addComment(
                    "Dividing channel {} by electrode distance {} km to give mV/km"
                    .format(chan,
                            self.getChanDx(chan) / 1000.0))
            if chan == "Ey":
                # multiply by 1000/self.getChanDy same as dividing by dist in km
                timeData.data[
                    chan] = 1000 * timeData.data[chan] / self.getChanDy(chan)
                timeData.addComment(
                    "Dividing channel {} by electrode distance {} km to give mV/km"
                    .format(chan,
                            self.getChanDy(chan) / 1000.0))

            # if remove zeros - False by default
            if options["remzeros"]:
                timeData.data[chan] = removeZerosSingle(timeData.data[chan])
            # if remove nans - False by default
            if options["remnans"]:
                timeData.data[chan] = removeNansSingle(timeData.data[chan])
            # remove the average from the data - True by default
            if options["remaverage"]:
                timeData.data[chan] = timeData.data[chan] - np.average(
                    timeData.data[chan])

        # add comments
        timeData.addComment(
            "Remove zeros: {}, remove nans: {}, remove average: {}".format(
                options["remzeros"], options["remnans"],
                options["remaverage"]))
        return timeData
Пример #5
0
    def getPhysicalSamples(self, **kwargs):
        """Get data scaled to physical values
        
        resistics uses field units, meaning physical samples will return the following:

        - Electrical channels in mV/km
        - Magnetic channels in mV
        - To get magnetic fields in nT, calibration needs to be performed

        Notes
        -----
        Once Lemi B423 data is scaled (which optionally happens in getUnscaledSamples), the magnetic channels is in mV with gain applied and the electric channels is uV (microvolts). Therefore:
        
        - Electric channels need to divided by 1000 along with dipole length division in km (east-west spacing and north-south spacing) to return mV/km.
        - Magnetic channels need to be divided by the internal gain value which should be set in the headers
        
        To get magnetic fields in nT, they have to be calibrated.

        Parameters
        ----------
        chans : List[str]
            List of channels to return if not all are required
        startSample : int
            First sample to return
        endSample : int
            Last sample to return
        remaverage : bool
            Remove average from the data
        remzeros : bool
            Remove zeroes from the data
        remnans: bool
            Remove NanNs from the data

        Returns
        -------
        TimeData
            Time data object
        """
        # initialise chans, startSample and endSample with the whole dataset
        options = self.parseGetDataKeywords(kwargs)
        # get unscaled data but with gain scalings applied
        timeData = self.getUnscaledSamples(
            chans=options["chans"],
            startSample=options["startSample"],
            endSample=options["endSample"],
            scale=True,
        )
        # convert to field units and divide by dipole lengths
        for chan in options["chans"]:
            if isElectric(chan):
                timeData.data[chan] = timeData.data[chan] / 1000.0
                timeData.addComment(
                    "Dividing channel {} by 1000 to convert microvolt to millivolt"
                    .format(chan))
            if isMagnetic(chan):
                timeData.data[chan] = timeData.data[chan] / self.getChanGain1(
                    chan)
                timeData.addComment(
                    "Removing gain of {} from channel {}".format(
                        self.getChanGain1(chan), chan))
            if chan == "Ex":
                # multiply by 1000/self.getChanDx same as dividing by dist in km
                timeData.data[chan] = (1000.0 * timeData.data[chan] /
                                       self.getChanDx(chan))
                timeData.addComment(
                    "Dividing channel {} by electrode distance {} km to give mV/km"
                    .format(chan,
                            self.getChanDx(chan) / 1000.0))
            if chan == "Ey":
                # multiply by 1000/self.getChanDy same as dividing by dist in km
                timeData.data[
                    chan] = 1000 * timeData.data[chan] / self.getChanDy(chan)
                timeData.addComment(
                    "Dividing channel {} by electrode distance {:.6f} km to give mV/km"
                    .format(chan,
                            self.getChanDy(chan) / 1000.0))

            # if remove zeros - False by default
            if options["remzeros"]:
                timeData.data[chan] = removeZerosSingle(timeData.data[chan])
            # if remove nans - False by default
            if options["remnans"]:
                timeData.data[chan] = removeNansSingle(timeData.data[chan])
            # remove the average from the data - True by default
            if options["remaverage"]:
                timeData.data[chan] = timeData.data[chan] - np.average(
                    timeData.data[chan])

        # add comments
        timeData.addComment(
            "Remove zeros: {}, remove nans: {}, remove average: {}".format(
                options["remzeros"], options["remnans"],
                options["remaverage"]))
        return timeData