Пример #1
0
 def _hilbert(self, data):
     pci1 = fft.fft2(fft.fftshift(np.float32(data)))
     pci2 = fft.ifftshift(pci1) * self.filter1
     fpci0 = fft.ifftshift(fft.ifft2(fft.fftshift(pci2)))
     fpci = np.imag(fpci0)
     result = fpci
     return result
Пример #2
0
 def _hilbert(self, data):
     pci1 = fft.fft2(fft.fftshift(np.float32(data)))
     pci2 = fft.ifftshift(pci1)*self.filter1
     fpci0 = fft.ifftshift(fft.ifft2(fft.fftshift(pci2)))
     fpci = np.imag(fpci0)
     result = fpci
     return result
Пример #3
0
 def _paganin(self, data):
     pci1 = fft.fft2(np.float32(data))
     pci2 = fft.fftshift(pci1) / self.filtercomplex
     fpci = np.abs(fft.ifft2(pci2))
     result = -0.5 * self.parameters['Ratio'] * np.log(
         fpci + self.parameters['increment'])
     return result
Пример #4
0
 def _paganin(self, data):
     pci1 = fft.fft2(np.float32(data))
     pci2 = fft.fftshift(pci1) / self.filtercomplex
     fpci = np.abs(fft.ifft2(pci2))
     result = -0.5 * self.parameters['Ratio'] * np.log(
         fpci + self.parameters['increment'])
     return result
Пример #5
0
 def _fine_search(self, sino, raw_cor):
     (Nrow, Ncol) = sino.shape
     centerfliplr = (Ncol + 1.0) / 2.0 - 1.0
     # Use to shift the sino2 to the raw CoR
     shiftsino = np.int16(2 * (raw_cor - centerfliplr))
     sino2 = np.roll(np.fliplr(sino[1:]), shiftsino, axis=1)
     lefttake = 0
     righttake = Ncol - 1
     search_rad = self.parameters['search_radius']
     if raw_cor <= centerfliplr:
         lefttake = np.ceil(search_rad + 1)
         righttake = np.floor(2 * raw_cor - search_rad - 1)
     else:
         lefttake = np.ceil(raw_cor - (Ncol - 1 - raw_cor) + search_rad + 1)
         righttake = np.floor(Ncol - 1 - search_rad - 1)
     Ncol1 = righttake - lefttake + 1
     mask = self._create_mask(2 * Nrow - 1, Ncol1,
                              0.5 * self.parameters['ratio'] * Ncol)
     numshift = np.int16((2 * search_rad + 1.0) / self.parameters['step'])
     listshift = np.linspace(-search_rad, search_rad, num=numshift)
     listmetric = np.zeros(len(listshift), dtype=np.float32)
     num1 = 0
     for i in listshift:
         logging.debug("list shift %d", i)
         sino2a = ndi.interpolation.shift(sino2, (0, i), prefilter=False)
         sinojoin = np.vstack((sino, sino2a))
         listmetric[num1] = np.sum(
             np.abs(
                 fft.fftshift(fft.fft2(
                     sinojoin[:, lefttake:righttake + 1]))) * mask)
         num1 = num1 + 1
     minpos = np.argmin(listmetric)
     rotcenter = raw_cor + listshift[minpos] / 2.0
     return rotcenter, listmetric
Пример #6
0
    def _coarse_search(self, sino):
        # search minsearch to maxsearch in 1 pixel steps
        smin, smax = self.parameters['search_area']
        (Nrow, Ncol) = sino.shape
        centre_fliplr = (Ncol - 1.0) / 2.0
        # check angles here to determine if a sinogram should be chopped off.
        # Copy the sinogram and flip left right, the purpose is to make a full
        # [0;2Pi] sinogram
        sino2 = np.fliplr(sino[1:])
        # This image is used for compensating the shift of sino2
        compensateimage = np.zeros((Nrow - 1, Ncol), dtype=np.float32)
        # Start coarse search in which the shift step is 1
        compensateimage[:] = np.flipud(sino)[1:]
        start_shift = self._get_start_shift(centre_fliplr) * 2
        list_shift = np.arange(smin, smax + 1) * 2 - start_shift
        list_metric = np.zeros(len(list_shift), dtype=np.float32)
        mask = self._create_mask(2 * Nrow - 1, Ncol,
                                 0.5 * self.parameters['ratio'] * Ncol)

        count = 0
        for i in list_shift:
            sino2a = np.roll(sino2, i, axis=1)
            if i >= 0:
                sino2a[:, 0:i] = compensateimage[:, 0:i]
            else:
                sino2a[:, i:] = compensateimage[:, i:]
            fft_out = fft.fft2(np.vstack((sino, sino2a)))
            temp = np.sum(np.abs(fft.fftshift(fft_out)) * mask)
            list_metric[count] = temp
            count += 1
        minpos = np.argmin(list_metric)
        rot_centre = centre_fliplr + list_shift[minpos] / 2.0
        return rot_centre, list_metric
Пример #7
0
def simcheck(data, nphases):
    norients = data.shape[0]//nphases       # need to use integer divide

    # check user input before proceeding
    assert nphases*norients == data.shape[0]

    newshape = norients, nphases, data.shape[-2], data.shape[-1]

    # FT data only along spatial dimensions
    ft_data = fftshift(
                fftn(ifftshift(
                    data, axes=(1, 2)),
                 axes=(1, 2)),
            axes=(1, 2))
    # average only along phase, **not** orientation
    # This should be the equivalent of the FT of the average image per each
    # phase (i.e it should be symmetric as the phases will have averaged out)
    ft_data_avg = ft_data.reshape(newshape).mean(1)
    # Do the same, but take the absolute value before averaging, in this case
    # the signal should add up because the phase has been removed
    ft_data_avg_abs = np.abs(ft_data).reshape(newshape).mean(1)
    # Take the difference of the average power and the power of the average
    ft_data_diff = ft_data_avg_abs-abs(ft_data_avg)

    return ft_data_diff, ft_data_avg_abs, ft_data_avg
Пример #8
0
 def _coarse_search(self, sino, list_shift):
     # search minsearch to maxsearch in 1 pixel steps
     list_metric = np.zeros(len(list_shift), dtype=np.float32)
     (Nrow, Ncol) = sino.shape
     # check angles to determine if a sinogram should be chopped off.
     # Copy the sinogram and flip left right, to make a full [0:2Pi] sino
     sino2 = np.fliplr(sino[1:])
     # This image is used for compensating the shift of sino2
     compensateimage = np.zeros((Nrow - 1, Ncol), dtype=np.float32)
     # Start coarse search in which the shift step is 1
     compensateimage[:] = np.flipud(sino)[1:]
     mask = self._create_mask(2 * Nrow - 1, Ncol,
                              0.5 * self.parameters['ratio'] * Ncol)
     count = 0
     for i in list_shift:
         sino2a = np.roll(sino2, i, axis=1)
         if i >= 0:
             sino2a[:, 0:i] = compensateimage[:, 0:i]
         else:
             sino2a[:, i:] = compensateimage[:, i:]
         list_metric[count] = np.sum(
             np.abs(fft.fftshift(fft.fft2(np.vstack(
                 (sino, sino2a))))) * mask)
         count += 1
     return list_metric
Пример #9
0
 def _fine_search(self, sino, raw_cor):
     (Nrow, Ncol) = sino.shape
     centerfliplr = (Ncol + 1.0)/2.0-1.0
     # Use to shift the sino2 to the raw CoR
     shiftsino = np.int16(2*(raw_cor-centerfliplr))
     sino2 = np.roll(np.fliplr(sino[1:]), shiftsino, axis=1)
     lefttake = 0
     righttake = Ncol-1
     search_rad = self.parameters['search_radius']
     if raw_cor <= centerfliplr:
         lefttake = np.ceil(search_rad+1)
         righttake = np.floor(2*raw_cor-search_rad-1)
     else:
         lefttake = np.ceil(raw_cor-(Ncol-1-raw_cor)+search_rad+1)
         righttake = np.floor(Ncol-1-search_rad-1)
     Ncol1 = righttake-lefttake + 1
     mask = self._create_mask(2*Nrow-1, Ncol1,
                              0.5*self.parameters['ratio']*Ncol)
     numshift = np.int16((2*search_rad+1.0)/self.parameters['step'])
     listshift = np.linspace(-search_rad, search_rad, num=numshift)
     listmetric = np.zeros(len(listshift), dtype=np.float32)
     num1 = 0
     for i in listshift:
         logging.debug("list shift %d", i)
         sino2a = ndi.interpolation.shift(sino2, (0, i), prefilter=False)
         sinojoin = np.vstack((sino, sino2a))
         listmetric[num1] = np.sum(np.abs(fft.fftshift(
             fft.fft2(sinojoin[:, lefttake:righttake + 1])))*mask)
         num1 = num1 + 1
     minpos = np.argmin(listmetric)
     rotcenter = raw_cor + listshift[minpos]/2.0
     return rotcenter, listmetric
Пример #10
0
    def _coarse_search(self, sino):
        # search minsearch to maxsearch in 1 pixel steps
        smin, smax = self.parameters['search_area']
        logging.debug("SMIN and SMAX %d %d", smin, smax)
        (Nrow, Ncol) = sino.shape
        centre_fliplr = (Ncol - 1.0)/2.0
        # check angles here to determine if a sinogram should be chopped off.
        # Copy the sinogram and flip left right, the purpose is to make a full
        # [0;2Pi] sinogram
        sino2 = np.fliplr(sino[1:])
        # This image is used for compensating the shift of sino2
        compensateimage = np.zeros((Nrow-1, Ncol), dtype=np.float32)
        # Start coarse search in which the shift step is 1
        compensateimage[:] = sino[-1]
        start_shift = self._get_start_shift(centre_fliplr)*2
        list_shift = np.arange(smin, smax + 1)*2 - start_shift
        logging.debug("%s", list_shift)
        list_metric = np.zeros(len(list_shift), dtype=np.float32)
        mask = self._create_mask(2*Nrow-1, Ncol,
                                 0.5*self.parameters['ratio']*Ncol)

        count = 0
        for i in list_shift:
            logging.debug("list shift %d", i)
            sino2a = np.roll(sino2, i, axis=1)
            if i >= 0:
                sino2a[:, 0:i] = compensateimage[:, 0:i]
            else:
                sino2a[:, i:] = compensateimage[:, i:]
            list_metric[count] = np.sum(
                np.abs(fft.fftshift(fft.fft2(np.vstack((sino, sino2a)))))*mask)
            count += 1
        minpos = np.argmin(list_metric)
        rot_centre = centre_fliplr + list_shift[minpos]/2.0
        return rot_centre, list_metric
Пример #11
0
def FT_1D(ls, P, axis=-1):
    """
    Fourier transform the complex linear polarization spectrum 
    P(lambda^2) to obtain the Faraday dispersion function F(phi).
    The function uses the FFT to approximate the continuous 
    Fourier transform of a discretely sampled function.
    
       FT: F(phi) = integral[ P(ls) exp(-2*i*phi*ls) dls]
       IFT: P(ls) = integral[ F(phi) exp(2*i*phi*ls) dphi]
       
    Function returns phi and F, which approximate F(phi).
    
    Parameters
    ----------
    ls  : array_like
        regularly sampled array of lambda_squared.
        ls is assumed to be regularly spaced, i.e.
        ls = ls0 + Dls * np.arange(N)
    P   : array_like
        Complex linear polarization spectrum.
    axis : int
        axis along which to perform fourier transform.

    Returns
    -------
    phi : ndarray
        Faraday depth of the calculated Faraday dispersion function.
    F   : ndarray
        Complex Faraday dispersion function.
    """
    assert ls.ndim == 1
    assert P.shape[axis] == ls.shape[0]
    N = int(len(ls))
    if N % 2 != 0:
        raise ValueError("number of samples must be even")

    ls = ls / np.pi
    Dls = ls[1] - ls[0]
    Dphi = 1. / (N * Dls)
    ls0 = ls[int(N / 2)]

    phi = Dphi * (np.arange(N) - N / 2)

    shape = np.ones(P.ndim, dtype=int)
    shape[axis] = N

    phase = np.ones(N)
    phase[1::2] = -1
    phase = phase.reshape(shape)

    #     F = Dls * fft.fft(P * phase, axis=axis)
    F = Dls * fft.fftshift(fft.fft(P, axis=axis), axes=axis)  #*np.pi

    F *= phase
    F *= np.exp(-2j * np.pi * ls0 * phi.reshape(shape))
    F *= np.exp(-1j * np.pi * N / 2)

    return phi, F
Пример #12
0
    def process_frames(self, data):
        sino = data[0]
        sino2 = np.fliplr(sino[1:])
        (Nrow, Ncol) = sino.shape
        mask = self._create_mask(
            2*Nrow-1, Ncol, 0.5*self.parameters['ratio']*Ncol)

        FT1 = fft.fftshift(fft.fft2(np.vstack((sino, sino2))))
        sino = fft.ifft2(fft.ifftshift(FT1 - FT1*mask))
        return sino[0:Nrow].real
Пример #13
0
def sampling_op_forward(image, mask_as_image):
    """ Sampling operator
    
    :param image: Assumed to be an array with shape [N,N]
    :param mask_as_image: 
    :param mask_as_image: Mask of shape [N,N] where middle of the image 
                          corresponds to zero frequency. Values should be 0,1 or
                          True/False.
    :return: An array with shape [N,N] where some of the data have been zeroed out.
    """
    N = max(image.shape)
    fourier_coeff = fftw.fftshift(fftw.fft2(image)) / N
    fourier_coeff_zero = np.multiply(mask_as_image, fourier_coeff)
    return fourier_coeff_zero
Пример #14
0
def spectral_whitening(tr,
                       smooth=None,
                       filter=None,
                       waterlevel=1e-8,
                       mask_again=True):
    """
    Apply spectral whitening to data

    Data is divided by its smoothed (Default: None) amplitude spectrum.

    :param tr: trace to manipulate
    :param smooth: length of smoothing window in Hz
        (default None -> no smoothing)
    :param filter: filter spectrum with bandpass after whitening
        (tuple with min and max frequency)
    :param waterlevel: waterlevel relative to mean of spectrum
    :param mask_again: weather to mask array after this operation again and
        set the corresponding data to 0

    :return: whitened data
    """
    sr = tr.stats.sampling_rate
    data = tr.data
    data = _fill_array(data, fill_value=0)
    mask = np.ma.getmask(data)
    nfft = next_fast_len(len(data))
    spec = fft(data, nfft)
    spec_ampl = np.abs(spec)
    spec_ampl /= np.max(spec_ampl)
    if smooth:
        smooth = int(smooth * nfft / sr)
        spec_ampl = ifftshift(smooth_func(fftshift(spec_ampl), smooth))
    # save guard against division by 0
    spec_ampl[spec_ampl < waterlevel] = waterlevel
    spec /= spec_ampl
    if filter is not None:
        spec *= _filter_resp(*filter, sr=sr, N=len(spec), whole=True)[1]
    ret = np.real(ifft(spec, nfft)[:len(data)])
    if mask_again:
        ret = _fill_array(ret, mask=mask, fill_value=0)
    tr.data = ret
    return tr
 def _coarse_search(self, sino, list_shift):
     # search minsearch to maxsearch in 1 pixel steps
     list_metric = np.zeros(len(list_shift), dtype=np.float32)
     (Nrow, Ncol) = sino.shape
     # check angles to determine if a sinogram should be chopped off.
     # Copy the sinogram and flip left right, to make a full [0:2Pi] sino
     sino2 = np.fliplr(sino[1:])
     # This image is used for compensating the shift of sino2
     compensateimage = np.zeros((Nrow-1, Ncol), dtype=np.float32)
     # Start coarse search in which the shift step is 1
     compensateimage[:] = np.flipud(sino)[1:]
     mask = self._create_mask(2*Nrow-1, Ncol,
                              0.5*self.parameters['ratio']*Ncol)
     count = 0
     for i in list_shift:
         sino2a = np.roll(sino2, i, axis=1)
         if i >= 0:
             sino2a[:, 0:i] = compensateimage[:, 0:i]
         else:
             sino2a[:, i:] = compensateimage[:, i:]
         list_metric[count] = np.sum(
             np.abs(fft.fftshift(fft.fft2(np.vstack((sino, sino2a)))))*mask)
         count += 1
     return list_metric
Пример #16
0
    def plot(self):
        try:
            self.plotErrorLabel.setText('')

            plot_groups = []

            # Read Groups
            defined_groups = str(self.groupsTextEdit.toPlainText()).replace(
                '\n', '').replace(' ', '').split(';')
            defined_groups = defined_groups[0:-1]

            # Parse each group as if defining a constraint group (recylcing code from PINTS)
            for group in defined_groups:
                group_info = group.split(',')
                group_name = group_info[0]
                group_members = group_info[1:]

                new_group = CSTGroup('', group_name, group_members, 0, 0)

                plot_groups.append(new_group)

            # Gather plotting variables
            sfactor = float(self.sfactorInput.text())
            pfactor = np.deg2rad(float(self.pfactorInput.text()))
            VSHIFT = float(self.VSHIFTInput.text())
            HSHIFT = float(self.HSHIFTInput.text())
            FT1 = int(self.ft1Input.text())
            lb = float(self.lbInput.text())

            b0 = float(self.b0Input.text())
            dwell_time = float(self.dwellTimeInput.text())
            acq_time = int(self.nInput.text()) * dwell_time
            fs = 1 / dwell_time
            t = np.arange(0, acq_time, dwell_time)

            tableau10 = [(31, 119, 180), (255, 127, 14), (44, 160, 44),
                         (214, 39, 40), (148, 103, 189), (140, 86, 75),
                         (227, 119, 194), (127, 127, 127), (188, 189, 34),
                         (23, 190, 207)]

            for i in range(len(tableau10)):
                r, g, b = tableau10[i]
                tableau10[i] = (r / 255., g / 255., b / 255.)

            # Calculate Summed Spectra
            fit_spec_sum = []
            fit_fid_sum = []
            for metabolite in self.fit_out.metabolites_list:
                fid = self.fit_out.metabolites[metabolite].getFID(
                    0, b0, t, 0, 1, pfactor, 0, lb)
                if not (self.extrap0CheckBox.isChecked()):
                    fid = fid[FT1:]
                spec = fftw.fftshift(fftw.fft(fid))

                n = np.size(fid)
                f = np.arange(+n // 2, -n // 2, -1) * (fs / n) * (1 / b0)
                fit_f = -f

                # fit_f, spec = self.fit_out.metabolites[metabolite].getSpec(0, b0, t, 0, 1, pfactor, 0, lb, fs)
                fit_fid_sum.append(fid)
                fit_spec_sum.append(spec)
            fit_fid_sum = np.sum(np.array(fit_fid_sum), axis=0)
            fit_spec_sum = np.real(np.sum(np.array(fit_spec_sum), axis=0))

            # Calculate In-Vivo Spectra
            invivo_dat_temp = copy.copy(self.invivo_dat)
            invivo_dat_temp.signal = invivo_dat_temp.signal[
                0:np.size(t)] * np.exp(1j * pfactor) * np.exp(-sp.pi * lb * t)
            if not (self.extrap0CheckBox.isChecked()):
                invivo_dat_temp.signal = invivo_dat_temp.signal[FT1:]
            else:
                invivo_dat_temp.signal = np.hstack(
                    (fit_fid_sum[0:FT1], invivo_dat_temp.signal[FT1:]))
            invivo_f, invivo_spec = invivo_dat_temp.getSpec()
            invivo_spec = np.real(invivo_spec)

            # Calculate Fitted Spectra
            fit_spec = []
            fit_spec_names = []
            for group in plot_groups:
                group_spec = []
                for member in group.members:
                    fid = self.fit_out.metabolites[member].getFID(
                        0, b0, t, 0, 1, pfactor, 0, lb)
                    if not (self.extrap0CheckBox.isChecked()):
                        fid = fid[FT1:]
                    spec = fftw.fftshift(fftw.fft(fid))

                    n = np.size(fid)
                    f = np.arange(+n // 2, -n // 2, -1) * (fs / n) * (1 / b0)
                    fit_f = -f
                    # fit_f, spec = self.fit_out.metabolites[member].getSpec(0, b0, t, 0, 1, pfactor, 0, lb, fs)
                    group_spec.append(spec)
                group_spec = np.real(np.sum(np.array(group_spec), axis=0))
                fit_spec.append(group_spec)
                fit_spec_names.append(group.name)

            plt.figure(1)
            plt.clf()

            ax = plt.subplot(111)
            ax.spines['top'].set_visible(False)
            ax.spines['bottom'].set_visible(True)
            ax.spines['right'].set_visible(False)
            ax.spines['left'].set_visible(False)
            ax.get_xaxis().tick_bottom()
            ax.get_yaxis().set_visible(False)
            plt.xlim(5, 0)

            for i, spec in enumerate(fit_spec):
                plt.plot(
                    np.array(-fit_f) + sfactor,
                    np.real(fit_spec[-(i + 1)]) -
                    i * VSHIFT * np.amax(np.real(fit_spec_sum)),
                    color=tableau10[-((i) % np.size(tableau10, axis=0) + 1)],
                    lw=1.5,
                    alpha=0.8)
                ax.text(5, -i * VSHIFT * np.amax(np.real(fit_spec_sum)),
                        fit_spec_names[-(i + 1)])

            print(np.size(fit_f), np.size(fit_spec_sum), np.size(invivo_spec))

            plt.plot(
                np.array(-fit_f) + sfactor,
                (np.real(fit_spec_sum) - np.roll(
                    np.real(invivo_spec)[0:np.size(fit_f)], int(HSHIFT))) +
                np.amax(np.real(invivo_spec)) +
                3.0 * VSHIFT * np.amax(np.real(invivo_spec)),
                color=tableau10[2],
                lw=1.5,
                alpha=0.8)
            plt.plot(
                np.array(-fit_f) + sfactor,
                np.roll(np.real(invivo_spec)[0:np.size(fit_f)], int(HSHIFT)) +
                1.5 * VSHIFT * np.amax(np.real(invivo_spec)),
                color=tableau10[0],
                lw=1.5)
            plt.plot(np.array(-fit_f) + sfactor,
                     np.real(fit_spec_sum) +
                     1.5 * VSHIFT * np.amax(np.real(invivo_spec)),
                     color=tableau10[1],
                     lw=1.5,
                     alpha=0.8)

            plt.xlabel('ppm')

            self.canvas[0].draw()

        except Exception as e:
            self.plotErrorLabel.setText(
                '>> ERROR: ' + str(e) +
                '\n>> Could not plot. Please try again.')
Пример #17
0
def cifftn(data,axes):
    '''Centered ifft'''
    return fftpack.fftshift(fftpack.ifftn(fftpack.ifftshift(data,axes),axes=axes))
Пример #18
0
def fold(fh1,
         dtype,
         samplerate,
         fedge,
         fedge_at_top,
         nchan,
         nt,
         ntint,
         nskip,
         ngate,
         ntbin,
         ntw,
         dm,
         fref,
         phasepol,
         dedisperse='incoherent',
         do_waterfall=True,
         do_foldspec=True,
         verbose=True,
         progress_interval=100,
         comm=None):
    """FFT GMRT data, fold by phase/time and make a waterfall series

    Parameters
    ----------
    fh1 : file handle
        handle to file holding voltage timeseries
    dtype : numpy dtype or '4bit' or '1bit'
        way the data are stored in the file
    samplerate : float
        rate at which samples were originally taken and thus double the
        band width (frequency units)
    fedge : float
        edge of the frequency band (frequency units)
    fedge_at_top: bool
        whether edge is at top (True) or bottom (False)
    nchan : int
        number of frequency channels for FFT
    nt, ntint : int
        total number nt of sets, each containing ntint samples in each file
        hence, total # of samples is nt*ntint, with each sample containing
        a single polarisation
    nskip : int
        number of records (nchan*ntint*2 for phased data w/ np.int8 real,imag)
    ngate, ntbin : int
        number of phase and time bins to use for folded spectrum
        ntbin should be an integer fraction of nt
    ntw : int
        number of time samples to combine for waterfall (does not have to be
        integer fraction of nt)
    dm : float
        dispersion measure of pulsar, used to correct for ism delay
        (column number density)
    fref: float
        reference frequency for dispersion measure
    phasepol : callable
        function that returns the pulsar phase for time in seconds relative to
        start of part of the file that is read (i.e., ignoring nhead)
    dedisperse : None or string
        None, 'incoherent', 'coherent', 'by-channel'
    do_waterfall, do_foldspec : bool
        whether to construct waterfall, folded spectrum (default: True)
    verbose : bool
        whether to give some progress information (default: True)
    progress_interval : int
        Ping every progress_interval sets
    comm : MPI communicator (default: None)
    """
    if comm is None:
        rank = 0
        size = 1
    else:
        rank = comm.rank
        size = comm.size

    # initialize folded spectrum and waterfall
    foldspec2 = np.zeros((nchan, ngate, ntbin))
    nwsize = nt * ntint // ntw
    waterfall = np.zeros((nchan, nwsize))

    # size in bytes of records read from file (simple for ARO: 1 byte/sample)
    # double since we need to get ntint samples after FFT
    itemsize = {np.int8: 2}[dtype]
    recsize = nchan * ntint * itemsize

    if verbose:
        print('Reading from {}'.format(fh1))

    if nskip > 0:
        if verbose:
            print('Skipping {0} {1}-byte records'.format(nskip, recsize))
        if size == 1:
            fh1.seek(nskip * recsize)

    foldspec = np.zeros((nchan, ngate, ntbin), dtype=np.int)
    icount = np.zeros((nchan, ngate, ntbin), dtype=np.int)

    dt1 = (1. / samplerate).to(u.s)
    # but include 2*nchan real-valued samples used for each FFT
    # (or, equivalently, real and imag for channels)
    dtsample = nchan * 2 * dt1
    tstart = dt1 * nskip * recsize

    # pre-calculate time delay due to dispersion in coarse channels
    freq = fftshift(fftfreq(nchan, 2. * dt1.value)) * u.Hz
    freq = (fedge - (freq - freq[0]) if fedge_at_top else fedge +
            (freq - freq[0]))
    # [::2] sets frequency channels to numerical recipes ordering
    dt = (dispersion_delay_constant * dm * (1. / freq**2 - 1. / fref**2)).to(
        u.s).value
    # if dedisperse in {'coherent', 'by-channel'}:
    #     # pre-calculate required turns due to dispersion
    #     fcoh = (fedge - fftfreq(nchan*ntint, 2.*dt1)
    #             if fedge_at_top
    #             else
    #             fedge + fftfreq(nchan*ntint, 2.*dt1))
    #     # set frequency relative to which dispersion is coherently corrected
    #     if dedisperse == 'coherent':
    #         _fref = fref
    #     else:
    #         _fref = np.repeat(freq.value, ntint) * freq.unit
    #     # (check via eq. 5.21 and following in
    #     # Lorimer & Kramer, Handbook of Pulsar Astrono
    #     dang = (dispersion_delay_constant * dm * fcoh *
    #             (1./_fref-1./fcoh)**2) * 360. * u.deg
    #     # order of frequencies is r[0], r[1],i[1],...r[n-1],i[n-1],r[n]
    #     # for 0 and n need only real part, but for 1...n-1 need real, imag
    #     # so just get shifts for r[1], r[2], ..., r[n-1]
    #     dang = dang.to(u.rad).value[1:-1:2]
    #     dd_coh = np.exp(dang * 1j).conj().astype(np.complex64)

    for j in xrange(rank, nt, size):
        if verbose and j % progress_interval == 0:
            print('Doing {:6d}/{:6d}; time={:18.12f}'.format(
                j + 1, nt,
                (tstart + dtsample * j * ntint).value))  # time since start

        # just in case numbers were set wrong -- break if file ends
        # better keep at least the work done
        try:
            if size > 1:
                fh1.seek((nskip + j) * recsize)
            # data just a series of byte pairs, of real and imag
            raw = fromfile(fh1, dtype, recsize)
        except (EOFError, IOError) as exc:
            print("Hit {}; writing pgm's".format(exc))
            break
        if verbose == 'very':
            print("Read {} items".format(raw.size), end="")

        vals = raw.astype(np.float32).view(np.complex64).squeeze()
        # if dedisperse in {'coherent', 'by-channel'}:
        #     fine = rfft(vals, axis=0, overwrite_x=True, **_fftargs)
        #     fine_cmplx = fine[1:-1].view(np.complex64)
        #     fine_cmplx *= dd_coh  # this overwrites parts of fine, as intended
        #     vals = irfft(fine, axis=0, overwrite_x=True, **_fftargs)
        #     if verbose == 'very':
        #         print("... dedispersed", end="")

        chan = vals.reshape(-1, nchan)
        if verbose == 'very':
            print("... power", end="")
        power = chan.real**2 + chan.imag**2

        # current sample positions in stream
        isr = j * ntint + np.arange(ntint)

        if do_waterfall:
            # loop over corresponding positions in waterfall
            for iw in xrange(isr[0] // ntw, isr[-1] // ntw + 1):
                if iw < nwsize:  # add sum of corresponding samples
                    waterfall[:, iw] += np.sum(power[isr // ntw == iw], axis=0)
            if verbose == 'very':
                print("... waterfall", end="")

        if do_foldspec:
            tsample = (tstart + isr * dtsample).value  # times since start

            ibin = j * ntbin // nt  # bin in the time series: 0..ntbin-1

            for k in xrange(nchan):
                if dedisperse == 'coherent':
                    t = tsample  # already dedispersed
                else:
                    t = tsample - dt[k]  # dedispersed times

                phase = phasepol(t)  # corresponding PSR phases
                iphase = np.remainder(phase * ngate, ngate).astype(np.int)
                # sum and count samples by phase bin
                foldspec[k, :, ibin] += np.bincount(iphase, power[:, k], ngate)
                icount[k, :, ibin] += np.bincount(iphase, None, ngate)

            if verbose == 'very':
                print("... folded", end="")

            if 0:  #done in gmrt.py (j+1)*ntbin//nt > ibin:  # last addition to bin?
                # get normalised flux in each bin (where any were added)
                nonzero = icount > 0
                nfoldspec = np.where(nonzero, foldspec / icount, 0.)
                # subtract phase average and store
                nfoldspec -= np.where(
                    nonzero,
                    np.sum(nfoldspec, 1, keepdims=True) /
                    np.sum(nonzero, 1, keepdims=True), 0)
                foldspec2[:, :, ibin] = nfoldspec
                # reset for next iteration
                foldspec *= 0
                icount *= 0
                if verbose == 'very':
                    print("... added", end="")
        if verbose == 'very':
            print("... done")

    if verbose:
        print('read {0:6d} out of {1:6d}'.format(j + 1, nt))

    if 0:  # done in gmrt.py do_waterfall:
        nonzero = waterfall == 0.
        waterfall -= np.where(
            nonzero,
            np.sum(waterfall, 1, keepdims=True) /
            np.sum(nonzero, 1, keepdims=True), 0.)

    return foldspec, icount, waterfall
Пример #19
0
def fold(fh1, dtype, samplerate, fedge, fedge_at_top, nchan,
         nt, ntint, nskip, ngate, ntbin, ntw, dm, fref, phasepol,
         dedisperse='incoherent',
         do_waterfall=True, do_foldspec=True, verbose=True,
         progress_interval=100, comm=None):
    """FFT GMRT data, fold by phase/time and make a waterfall series

    Parameters
    ----------
    fh1 : file handle
        handle to file holding voltage timeseries
    dtype : numpy dtype or '4bit' or '1bit'
        way the data are stored in the file
    samplerate : float
        rate at which samples were originally taken and thus double the
        band width (frequency units)
    fedge : float
        edge of the frequency band (frequency units)
    fedge_at_top: bool
        whether edge is at top (True) or bottom (False)
    nchan : int
        number of frequency channels for FFT
    nt, ntint : int
        total number nt of sets, each containing ntint samples in each file
        hence, total # of samples is nt*ntint, with each sample containing
        a single polarisation
    nskip : int
        number of records (nchan*ntint*2 for phased data w/ np.int8 real,imag)
    ngate, ntbin : int
        number of phase and time bins to use for folded spectrum
        ntbin should be an integer fraction of nt
    ntw : int
        number of time samples to combine for waterfall (does not have to be
        integer fraction of nt)
    dm : float
        dispersion measure of pulsar, used to correct for ism delay
        (column number density)
    fref: float
        reference frequency for dispersion measure
    phasepol : callable
        function that returns the pulsar phase for time in seconds relative to
        start of part of the file that is read (i.e., ignoring nhead)
    dedisperse : None or string
        None, 'incoherent', 'coherent', 'by-channel'
    do_waterfall, do_foldspec : bool
        whether to construct waterfall, folded spectrum (default: True)
    verbose : bool
        whether to give some progress information (default: True)
    progress_interval : int
        Ping every progress_interval sets
    comm : MPI communicator (default: None)
    """
    if comm is None:
        rank = 0
        size = 1
    else:
        rank = comm.rank
        size = comm.size

    # initialize folded spectrum and waterfall
    foldspec2 = np.zeros((nchan, ngate, ntbin))
    nwsize = nt*ntint//ntw
    waterfall = np.zeros((nchan, nwsize))

    # size in bytes of records read from file (simple for ARO: 1 byte/sample)
    # double since we need to get ntint samples after FFT
    itemsize = {np.int8: 2}[dtype]
    recsize = nchan*ntint*itemsize

    if verbose:
        print('Reading from {}'.format(fh1))

    if nskip > 0:
        if verbose:
            print('Skipping {0} {1}-byte records'.format(nskip, recsize))
        if size == 1:
            fh1.seek(nskip * recsize)

    foldspec = np.zeros((nchan, ngate, ntbin), dtype=np.int)
    icount = np.zeros((nchan, ngate, ntbin), dtype=np.int)

    dt1 = (1./samplerate).to(u.s)
    # but include 2*nchan real-valued samples used for each FFT
    # (or, equivalently, real and imag for channels)
    dtsample = nchan * 2 * dt1
    tstart = dt1 * nskip * recsize

    # pre-calculate time delay due to dispersion in coarse channels
    freq = fftshift(fftfreq(nchan, 2.*dt1.value)) * u.Hz
    freq = (fedge - (freq-freq[0])
            if fedge_at_top
            else fedge + (freq-freq[0]))
    # [::2] sets frequency channels to numerical recipes ordering
    dt = (dispersion_delay_constant * dm *
          (1./freq**2 - 1./fref**2)).to(u.s).value
    # if dedisperse in {'coherent', 'by-channel'}:
    #     # pre-calculate required turns due to dispersion
    #     fcoh = (fedge - fftfreq(nchan*ntint, 2.*dt1)
    #             if fedge_at_top
    #             else
    #             fedge + fftfreq(nchan*ntint, 2.*dt1))
    #     # set frequency relative to which dispersion is coherently corrected
    #     if dedisperse == 'coherent':
    #         _fref = fref
    #     else:
    #         _fref = np.repeat(freq.value, ntint) * freq.unit
    #     # (check via eq. 5.21 and following in
    #     # Lorimer & Kramer, Handbook of Pulsar Astrono
    #     dang = (dispersion_delay_constant * dm * fcoh *
    #             (1./_fref-1./fcoh)**2) * 360. * u.deg
    #     # order of frequencies is r[0], r[1],i[1],...r[n-1],i[n-1],r[n]
    #     # for 0 and n need only real part, but for 1...n-1 need real, imag
    #     # so just get shifts for r[1], r[2], ..., r[n-1]
    #     dang = dang.to(u.rad).value[1:-1:2]
    #     dd_coh = np.exp(dang * 1j).conj().astype(np.complex64)

    for j in xrange(rank, nt, size):
        if verbose and j % progress_interval == 0:
            print('Doing {:6d}/{:6d}; time={:18.12f}'.format(
                j+1, nt, (tstart+dtsample*j*ntint).value))   # time since start

        # just in case numbers were set wrong -- break if file ends
        # better keep at least the work done
        try:
            if size > 1:
                fh1.seek((nskip + j) * recsize)
            # data just a series of byte pairs, of real and imag
            raw = fromfile(fh1, dtype, recsize)
        except(EOFError, IOError) as exc:
            print("Hit {}; writing pgm's".format(exc))
            break
        if verbose == 'very':
            print("Read {} items".format(raw.size), end="")

        vals = raw.astype(np.float32).view(np.complex64).squeeze()
        # if dedisperse in {'coherent', 'by-channel'}:
        #     fine = rfft(vals, axis=0, overwrite_x=True, **_fftargs)
        #     fine_cmplx = fine[1:-1].view(np.complex64)
        #     fine_cmplx *= dd_coh  # this overwrites parts of fine, as intended
        #     vals = irfft(fine, axis=0, overwrite_x=True, **_fftargs)
        #     if verbose == 'very':
        #         print("... dedispersed", end="")

        chan = vals.reshape(-1, nchan)
        if verbose == 'very':
            print("... power", end="")
        power = chan.real**2+chan.imag**2

        # current sample positions in stream
        isr = j*ntint + np.arange(ntint)

        if do_waterfall:
            # loop over corresponding positions in waterfall
            for iw in xrange(isr[0]//ntw, isr[-1]//ntw + 1):
                if iw < nwsize:  # add sum of corresponding samples
                    waterfall[:,iw] += np.sum(power[isr//ntw == iw],
                                              axis=0)
            if verbose == 'very':
                print("... waterfall", end="")

        if do_foldspec:
            tsample = (tstart + isr*dtsample).value  # times since start

            ibin = j*ntbin//nt  # bin in the time series: 0..ntbin-1

            for k in xrange(nchan):
                if dedisperse == 'coherent':
                    t = tsample  # already dedispersed
                else:
                    t = tsample - dt[k]  # dedispersed times

                phase = phasepol(t)  # corresponding PSR phases
                iphase = np.remainder(phase*ngate,
                                      ngate).astype(np.int)
                # sum and count samples by phase bin
                foldspec[k,:,ibin] += np.bincount(iphase, power[:,k], ngate)
                icount[k,:,ibin] += np.bincount(iphase, None, ngate)

            if verbose == 'very':
                print("... folded", end="")

            if 0: #done in gmrt.py (j+1)*ntbin//nt > ibin:  # last addition to bin?
                # get normalised flux in each bin (where any were added)
                nonzero = icount > 0
                nfoldspec = np.where(nonzero, foldspec/icount, 0.)
                # subtract phase average and store
                nfoldspec -= np.where(nonzero,
                                      np.sum(nfoldspec, 1, keepdims=True) /
                                      np.sum(nonzero, 1, keepdims=True), 0)
                foldspec2[:,:,ibin] = nfoldspec
                # reset for next iteration
                foldspec *= 0
                icount *= 0
                if verbose == 'very':
                    print("... added", end="")
        if verbose == 'very':
            print("... done")

    if verbose:
        print('read {0:6d} out of {1:6d}'.format(j+1, nt))

    if 0: # done in gmrt.py do_waterfall:
        nonzero = waterfall == 0.
        waterfall -= np.where(nonzero,
                              np.sum(waterfall, 1, keepdims=True) /
                              np.sum(nonzero, 1, keepdims=True), 0.)

    return foldspec, icount, waterfall
Пример #20
0
 def fftshift(self, a, axes=None):
     return scipy_fft.fftshift(a, axes=axes)
Пример #21
0
def fold(file1, samplerate, fmid, nchan,
         nt, ntint, nhead, ngate, ntbin, ntw, dm, fref, phasepol,
         coherent=False, do_waterfall=True, do_foldspec=True, verbose=True,
         progress_interval=100):
    """FFT Effelsberg data, fold by phase/time and make a waterfall series

    Parameters
    ----------
    file1 : string
        name of the file holding voltage timeseries
    samplerate : float
        rate at which samples were originally taken and thus band width
        (frequency units))
    fmid : float
        mid point of the frequency band (frequency units)
    nchan : int
        number of frequency channels for FFT
    nt, ntint : int
        total number nt of sets, each containing ntint samples in each file
        hence, total # of samples is nt*(2*ntint), with each sample containing
        real,imag for two polarisations
    nhead : int
        number of bytes to skip before reading (usually 4096 for Effelsberg)
    ngate, ntbin : int
        number of phase and time bins to use for folded spectrum
        ntbin should be an integer fraction of nt
    ntw : int
        number of time samples to combine for waterfall (does not have to be
        integer fraction of nt)
    dm : float
        dispersion measure of pulsar, used to correct for ism delay
        (column number density)
    fref: float
        reference frequency for dispersion measure
    phasepol : callable
        function that returns the pulsar phase for time in seconds relative to
        start of part of the file that is read (i.e., ignoring nhead)
    do_waterfall, do_foldspec : bool
        whether to construct waterfall, folded spectrum (default: True)
    verbose : bool
        whether to give some progress information (default: True)
    progress_interval : int
        Ping every progress_interval sets
    """

    # initialize folded spectrum and waterfall
    foldspec2 = np.zeros((nchan, ngate, ntbin))
    nwsize = nt*ntint//ntw
    waterfall = np.zeros((nchan, nwsize))

    # size in bytes of records read from file (each nchan contains 4 bytes:
    # real,imag for 2 polarisations).
    recsize = 4*nchan*ntint
    if verbose:
        print('Reading from {}'.format(file1))

    myopen = gzip.open if '.gz' in file1 else open
    with myopen(file1, 'rb', recsize) as fh1:

        if nhead > 0:
            if verbose:
                print('Skipping {0} bytes'.format(nhead))
            fh1.seek(nhead)

        foldspec = np.zeros((nchan, ngate))
        icount = np.zeros((nchan, ngate))

        # gosh, fftpack has everything; used to calculate with:
        # fband / nchan * (np.mod(np.arange(nchan)+nchan/2, nchan)-nchan/2)
        if coherent:
            # pre-calculate required turns due to dispersion
            fcoh = (fmid +
                    fftfreq(nchan*ntint, (1./samplerate).to(u.s).value) * u.Hz)
            # (check via eq. 5.21 and following in
            # Lorimer & Kramer, Handbook of Pulsar Astrono
            dang = (dispersion_delay_constant * dm * fcoh *
                    (1./fref-1./fcoh)**2) * 360. * u.deg
            dedisperse = np.exp(dang.to(u.rad).value * 1j
                                ).conj().astype(np.complex64)
        else:
            # pre-calculate time delay due to dispersion
            freq = fmid + fftfreq(nchan, (1./samplerate).to(u.s).value) * u.Hz
            dt = (dispersion_delay_constant * dm *
                  (1./freq**2 - 1./fref**2)).to(u.s).value

        dtsample = (nchan/samplerate).to(u.s).value

        for j in xrange(nt):
            if verbose and (j+1) % progress_interval == 0:
                print('Doing {:6d}/{:6d}; time={:18.12f}'.format(
                    j+1, nt, dtsample*j*ntint))   # equivalent time since start

            # just in case numbers were set wrong -- break if file ends
            # better keep at least the work done
            try:
                # data stored as series of two two-byte complex numbers,
                # one for each polarization
                raw = np.fromstring(fh1.read(recsize),
                                    dtype=np.int8).reshape(-1,2,2)
            except:
                break

            # use view for fast conversion from float to complex
            vals = raw.astype(np.float32).view(np.complex64).squeeze()
            # vals[i_int * i_block, i_pol]
            if coherent:
                fine = fft(vals, axis=0, overwrite_x=True, **_fftargs)
                fine *= dedisperse[:,np.newaxis]
                vals = ifft(fine, axis=0, overwrite_x=True, **_fftargs)

            chan = fft(vals.reshape(-1, nchan, 2), axis=1, overwrite_x=True,
                       **_fftargs)
            # chan[i_int, i_block, i_pol]
            power = np.sum(chan.real**2+chan.imag**2, axis=-1)

            # current sample positions in stream
            isr = j*ntint + np.arange(ntint)

            if do_waterfall:
                # loop over corresponding positions in waterfall
                for iw in xrange(isr[0]//ntw, isr[-1]//ntw + 1):
                    if iw < nwsize:  # add sum of corresponding samples
                        waterfall[:,iw] += np.sum(power[isr//ntw == iw],
                                                  axis=0)

            if do_foldspec:
                tsample = dtsample*isr  # times since start

                for k in xrange(nchan):
                    if coherent:
                        t = tsample  # already dedispersed
                    else:
                        t = tsample - dt[k]  # dedispersed times
                    phase = phasepol(t)  # corresponding PSR phases
                    iphase = np.remainder(phase*ngate,
                                          ngate).astype(np.int)
                    # sum and count samples by phase bin
                    foldspec[k] += np.bincount(iphase, power[:,k], ngate)
                    icount[k] += np.bincount(iphase, None, ngate)

                ibin = j*ntbin//nt  # bin in the time series: 0..ntbin-1
                if (j+1)*ntbin//nt > ibin:  # last addition to bin?
                    # get normalised flux in each bin (where any were added)
                    nonzero = icount > 0
                    nfoldspec = np.where(nonzero, foldspec/icount, 0.)
                    # subtract phase average and store
                    nfoldspec -= np.where(nonzero,
                                          np.sum(nfoldspec, 1, keepdims=True) /
                                          np.sum(nonzero, 1, keepdims=True), 0)
                    foldspec2[:,:,ibin] = nfoldspec
                    # reset for next iteration
                    foldspec *= 0
                    icount *= 0

    if verbose:
        print('read {0:6d} out of {1:6d}'.format(j+1, nt))

    if do_foldspec:
        # swap two halfs in frequency, so that freq increases monotonically
        foldspec2 = fftshift(foldspec2, axes=0)

    if do_waterfall:
        nonzero = waterfall == 0.
        waterfall -= np.where(nonzero,
                              np.sum(waterfall, 1, keepdims=True) /
                              np.sum(nonzero, 1, keepdims=True), 0.)
        # swap two halfs in frequency, so that freq increases monotonically
        waterfall = fftshift(waterfall, axes=0)

    return foldspec2, waterfall