Beispiel #1
0
 def evalfreq(self, t):
     """Return the freq at time t, computed with this polyco entry"""
     dt = (data2longdouble(t) - self.tmid.value) * MIN_PER_DAY
     s = data2longdouble(0.0)
     for i in range(1, self.ncoeff):
         s += data2longdouble(i) * self.coeffs[i] * dt**(i - 1)
     freq = self.f0 + s / 60.0
     return freq
Beispiel #2
0
 def __init__(self, tmid, mjdspan, rph_int, rph_frac, f0, ncoeff, coeffs):
     self.tmid = data2longdouble(tmid) * u.day
     self.mjdspan = data2longdouble(mjdspan / MIN_PER_DAY) * u.day
     self.tstart = self.tmid - (self.mjdspan / 2)
     self.tstop = self.tmid + (self.mjdspan / 2)
     self.f0 = data2longdouble(f0)
     self.ncoeff = ncoeff
     self.rphase = Phase(rph_int, rph_frac)
     self.coeffs = data2longdouble(coeffs)
Beispiel #3
0
 def evalfreqderiv(self, t):
     """Return the frequency derivative at time t."""
     dt = (data2longdouble(t) - self.tmid.value) * MIN_PER_DAY
     s = data2longdouble(0.0)
     for i in range(2, self.ncoeff):
         # Change to long double
         s += (data2longdouble(i) * data2longdouble(i - 1) *
               self.coeffs[i] * dt**(i - 2))
     freqd = s / (60.0 * 60.0)
     return freqd
Beispiel #4
0
    def evalabsphase(self, t):
        """Return the phase at time t, computed with this polyco entry"""
        dt = (data2longdouble(t) - self.tmid.value) * data2longdouble(1440.0)
        # Compute polynomial by factoring out the dt's
        phase = Phase(self.coeffs[self.ncoeff -
                                  1])  # Compute phase using two long double
        for i in range(self.ncoeff - 2, -1, -1):
            pI = Phase(dt * phase.int)
            pF = Phase(dt * phase.frac)
            c = Phase(self.coeffs[i])
            phase = pI + pF + c

        # Add DC term
        phase += self.rphase + Phase(dt * 60.0 * self.f0)
        return phase
Beispiel #5
0
    def eval_spin_freq(self, t):
        """
        Polyco evaluate spin frequency for a time array.

        Parameters
        ---------
        t: numpy.ndarray or a single number.
           An time array in MJD. Time sample should be in order

        Returns
        ---------
        out: numpy array of long double frequencies in Hz
             Polyco evaluated spin frequency at time t.

        FREQ(Hz) = F0 + (1/60)*(COEFF(2) + 2*DT*COEFF(3) + 3*DT^2*COEFF(4) + ...)
        """
        if not isinstance(t, np.ndarray) and not isinstance(t, list):
            t = np.array([t])

        entryIndex = self.find_entry(t)
        poly_result = data2longdouble(np.zeros(len(t)))

        dt = (data2longdouble(t) -
              self.polycoTable[entryIndex]["tmid"]) * MIN_PER_DAY

        for ii, (tt, eidx) in enumerate(zip(dt, entryIndex)):
            coeffs = self.polycoTable["entry"][eidx].coeffs
            coeffs = data2longdouble(range(len(coeffs))) * coeffs
            coeffs = coeffs[::-1][:-1]
            poly_result[ii] = np.polyval(coeffs, tt)
        spinFreq = np.array([
            self.polycoTable["entry"][eidx].f0 +
            poly_result[ii] / data2longdouble(60.0)
            for ii, eidx in zip(range(len(t)), entryIndex)
        ])

        return spinFreq
Beispiel #6
0
 def __init__(self, tmid, mjdspan, rphaseInt, rphaseFrac, f0, ncoeff,
              coeffs, obs):
     self.tmid = tmid * u.day
     self.mjdspan = mjdspan * u.day
     self.tstart = data2longdouble(
         self.tmid) - data2longdouble(self.mjdspan) / 2.0
     self.tstop = data2longdouble(
         self.tmid) + data2longdouble(self.mjdspan) / 2.0
     self.rphase = Phase(rphaseInt, rphaseFrac)
     self.f0 = data2longdouble(f0)
     self.ncoeff = ncoeff
     self.coeffs = data2longdouble(coeffs)
     self.obs = obs
Beispiel #7
0
    def generate_polycos(
        self,
        model,
        mjdStart,
        mjdEnd,
        obs,
        segLength,
        ncoeff,
        obsFreq,
        maxha=12.0,
        method="TEMPO",
        numNodes=20,
    ):
        """
        Generate the polyco data.

        Parameters
        ----------
        model : TimingModel
            TimingModel to generate the Polycos with parameters
            setup.

        mjdStart : float / numpy longdouble
            Start time of polycos in mjd

        mjdEnd : float / numpy longdouble
            Ending time of polycos in mjd

        obs : str
            Observatory code

        segLength : int
            Length of polyco segement [minutes]

        ncoeff : int
            Number of coefficents

        obsFreq : float
            Observing frequency [MHz]

        maxha : float optional. Default 12.0
            Maximum hour angle. Only 12.0 is supported for now.

        method : string optional ["TEMPO", "TEMPO2", ...] Default TEMPO
            Method to generate polycos. Only the TEMPO method is supported for now.

        numNodes : int optional. Default 20
            Number of nodes for fitting. It cannot be less then the number of
            coefficents.

        Return
        ---------
        A polyco table.
        """
        mjdStart = data2longdouble(mjdStart)
        mjdEnd = data2longdouble(mjdEnd)
        segLength = int(segLength)
        obsFreq = float(obsFreq)

        # Use the planetary ephemeris specified in the model, if available.
        if model.EPHEM.value is not None:
            ephem = model.EPHEM.value
        else:
            log.info(
                "No ephemeris specified in model, using DE421 to generate polycos"
            )
            ephem = "DE421"

        if maxha != 12.0:
            raise ValueError("Maximum hour angle != 12.0 is not supported.")

        # Make sure the number of nodes is bigger than number of coeffs.
        if numNodes < ncoeff:
            numNodes = ncoeff + 1

        mjdSpan = data2longdouble(segLength / MIN_PER_DAY)
        # Generate "nice" MJDs for consistency with what tempo2 does
        tmids = np.arange(
            int(mjdStart * 24) * 60,
            int(mjdEnd * 24) * 60 + segLength, segLength)
        tmids = data2longdouble(tmids) / MIN_PER_DAY

        # generate the ploynomial coefficents
        if method == "TEMPO":
            entryList = []
            # Using tempo1 method to create polycos
            # If you want to disable the progress bar, add disable=True to the tqdm() call.
            for tmid in tqdm(tmids):
                tStart = tmid - mjdSpan / 2
                tStop = tmid + mjdSpan / 2
                nodes = np.linspace(tStart, tStop, numNodes)

                toaMid = toa.get_TOAs_list(
                    [
                        toa.TOA((np.modf(tmid)[1], np.modf(tmid)[0]),
                                obs=obs,
                                freq=obsFreq)
                    ],
                    ephem=ephem,
                )

                refPhase = model.phase(toaMid, abs_phase=True)

                # Create node toas(Time sample using TOA class)
                toaList = [
                    toa.TOA(
                        (np.modf(toaNode)[1], np.modf(toaNode)[0]),
                        obs=obs,
                        freq=obsFreq,
                    ) for toaNode in nodes
                ]

                toas = toa.get_TOAs_list(toaList, ephem=ephem)

                ph = model.phase(toas, abs_phase=True)
                dt = (nodes - tmid) * MIN_PER_DAY
                rdcPhase = ph - refPhase
                rdcPhase = rdcPhase.int - (dt * model.F0.value *
                                           60.0) + rdcPhase.frac
                dtd = dt.astype(float)  # Truncate to double
                rdcPhased = rdcPhase.astype(float)
                coeffs = np.polyfit(dtd, rdcPhased, ncoeff - 1)[::-1]

                date, hms = Time(tmid, format="mjd", scale="utc").iso.split()
                yy, mm, dd = date.split("-")
                date = dd + "-" + MONTHS[int(mm) - 1] + "-" + yy[-2:]
                hms = float(hms.replace(":", ""))

                entry = PolycoEntry(
                    tmid,
                    segLength,
                    refPhase.int,
                    refPhase.frac,
                    model.F0.value,
                    ncoeff,
                    coeffs,
                )

                entry_dict = OrderedDict()
                entry_dict["psr"] = model.PSR.value
                entry_dict["date"] = date
                entry_dict["utc"] = hms
                entry_dict["tmid"] = tmid
                entry_dict["dm"] = model.DM.value
                entry_dict["doppler"] = 0.0
                entry_dict["logrms"] = 0.0
                entry_dict["mjd_span"] = segLength
                entry_dict["t_start"] = entry.tstart
                entry_dict["t_stop"] = entry.tstop
                entry_dict["obs"] = obs
                entry_dict["obsfreq"] = obsFreq

                if model.is_binary:
                    binphase = model.orbital_phase(toaMid, radians=False)[0]
                    entry_dict["binary_phase"] = binphase
                    b = model.get_components_by_category()["pulsar_system"][0]
                    entry_dict["f_orbit"] = 1 / b.PB.value

                entry_dict["entry"] = entry
                entryList.append(entry_dict)

            pTable = table.Table(entryList, meta={"name": "Polyco Data Table"})

            self.polycoTable = pTable
            if len(self.polycoTable) == 0:
                raise ValueError("Zero polycos found for table")

        else:
            raise NotImplementedError(
                "Only TEMPO method has been implemented.")
Beispiel #8
0
def tempo_polyco_table_reader(filename):
    """Read tempo style polyco file to an astropy table.

    Tempo style: The polynomial ephemerides are written to file 'polyco.dat'.
    Entries are listed sequentially within the file.  The file format is::

        ====  =======   ============================================
        Line  Columns     Item
        ====  =======   ============================================
         1       1-10   Pulsar Name
                11-19   Date (dd-mmm-yy)
                20-31   UTC (hhmmss.ss)
                32-51   TMID (MJD)
                52-72   DM
                74-79   Doppler shift due to earth motion (10^-4)
                80-86   Log_10 of fit rms residual in periods
         2       1-20   Reference Phase (RPHASE)
                21-38   Reference rotation frequency (F0)
                39-43   Observatory number
                44-49   Data span (minutes)
                50-54   Number of coefficients
                55-75   Observing frequency (MHz)
                76-80   Binary phase
         3*      1-25   Coefficient 1 (COEFF(1))
                26-50   Coefficient 2 (COEFF(2))
                51-75   Coefficient 3 (COEFF(3))
        ====  =======   ============================================
        * Subsequent lines have three coefficients each, up to NCOEFF

    One polyco file could include more then one entry.

    The pulse phase and frequency at time T are then calculated as::

        DT = (T-TMID)*1440
        PHASE = RPHASE + DT*60*F0 + COEFF(1) + DT*COEFF(2) + DT^2*COEFF(3) + ....
        FREQ(Hz) = F0 + (1/60)*(COEFF(2) + 2*DT*COEFF(3) + 3*DT^2*COEFF(4) + ....)

    Parameters
    ----------
    filename : str
        Name of the input poloco file.

    References
    ----------
    http://tempo.sourceforge.net/ref_man_sections/tz-polyco.txt
    """
    entries = []

    with open(filename, "r") as f:
        line = f.readline()

        while line != "":
            # First line
            fields = line.split()
            psrname = fields[0]
            date = fields[1]
            utc = float(fields[2])
            tmid = np.longdouble(fields[3])
            dm = float(fields[4])
            doppler = float(fields[5])
            logrms = float(fields[6])

            # Second line
            fields = f.readline().split()
            refPhaseInt, refPhaseFrac = fields[0].split(".")
            refPhaseInt = np.longdouble(refPhaseInt)
            refPhaseFrac = np.longdouble("." + refPhaseFrac)
            if refPhaseInt < 0:
                refPhaseFrac = -refPhaseFrac

            refF0 = np.longdouble(fields[1])
            obs = fields[2]
            mjdspan = int(fields[3])
            nCoeff = int(fields[4])
            obsfreq = float(fields[5])

            try:
                binary_phase = float(fields[6])
                f_orbit = float(fields[7])
                is_binary = True
            except IndexError:
                is_binary = False

            # Read coefficients
            coeffs = []
            for i in range(-(nCoeff // -3)):
                line = f.readline()
                for c in line.split():
                    coeffs.append(data2longdouble(c))
            coeffs = np.array(coeffs)

            entry = PolycoEntry(tmid, mjdspan, refPhaseInt, refPhaseFrac,
                                refF0, nCoeff, coeffs)

            entry_dict = OrderedDict()
            entry_dict["psr"] = psrname
            entry_dict["date"] = date
            entry_dict["utc"] = utc
            entry_dict["tmid"] = tmid
            entry_dict["dm"] = dm
            entry_dict["doppler"] = doppler
            entry_dict["logrms"] = logrms
            entry_dict["mjd_span"] = mjdspan
            entry_dict["t_start"] = entry.tstart
            entry_dict["t_stop"] = entry.tstop
            entry_dict["obs"] = obs
            entry_dict["obsfreq"] = obsfreq

            if is_binary:
                entry_dict["binary_phase"] = binary_phase
                entry_dict["f_orbit"] = f_orbit

            entry_dict["entry"] = entry
            entries.append(entry_dict)

            line = f.readline()

    pTable = table.Table(entries, meta={"name": "Polyco Data Table"})
    return pTable
Beispiel #9
0
    def generate_polycos(
        self,
        model,
        mjdStart,
        mjdEnd,
        obs,
        segLength,
        ncoeff,
        obsFreq,
        maxha=12.0,
        method="TEMPO",
        numNodes=20,
    ):
        """
        Generate the polyco data.

        Parameters
        ---------
        model : TimingModel
            TimingModel to generate the Polycos with parameters
            setup.

        mjdStart : float / nump longdouble
            Start time of polycos in mjd

        mjdEnd : float / nump longdouble
            Ending time of polycos in mjd

        obs : str
            Observatory code

        segLength : float
            Length of polyco segement [unit: minutes]

        ncoeff : int
            number of coefficents

        obsFreq : float
            observing frequency [unit: MHz]

        maxha : float optional. Default 12.0
            Maximum hour angle

        method : string optional ['TEMPO','TEMPO2',...] Default TEMPO
            Method to generate polycos. Only the TEMPO method is supported for now.

        numNodes : int optional. Default 20
            Number of nodes for fitting. It cannot be less then the number of
            coefficents.

        Return
        ---------
        A polyco table.


        """
        mjdStart = data2longdouble(mjdStart) * u.day
        mjdEnd = data2longdouble(mjdEnd) * u.day
        timeLength = mjdEnd - mjdStart
        segLength = data2longdouble(segLength) * u.min
        obsFreq = float(obsFreq)
        month = [
            "Jan",
            "Feb",
            "Mar",
            "Apr",
            "May",
            "Jun",
            "Jul",
            "Aug",
            "Sep",
            "Oct",
            "Nov",
            "Dec",
        ]
        # Alocate memery
        coeffs = data2longdouble(np.zeros(ncoeff))
        entryList = []
        entryIntvl = np.arange(mjdStart.value, mjdEnd.value,
                               segLength.to("day").value)
        if entryIntvl[-1] < mjdEnd.value:
            entryIntvl = np.append(entryIntvl, mjdEnd.value)

        # Make sure the number of nodes is bigger then number of coeffs.
        if numNodes < ncoeff:
            numNodes = ncoeff + 1

        # generate the ploynomial coefficents
        if method == "TEMPO":
            # Using tempo1 method to create polycos
            for i in range(len(entryIntvl) - 1):
                tStart = entryIntvl[i]
                tStop = entryIntvl[i + 1]
                nodes = np.linspace(tStart, tStop, numNodes)
                tmid = ((tStart + tStop) / 2.0) * u.day
                toaMid = toa.get_TOAs_list([
                    toa.TOA(
                        (np.modf(tmid.value)[1], np.modf(tmid.value)[0]),
                        obs=obs,
                        freq=obsFreq,
                    )
                ])
                refPhase = model.phase(toaMid)
                mjdSpan = ((tStop - tStart) * u.day).to("min")
                # Create node toas(Time sample using TOA class)
                toaList = [
                    toa.TOA(
                        (np.modf(toaNode)[1], np.modf(toaNode)[0]),
                        obs=obs,
                        freq=obsFreq,
                    ) for toaNode in nodes
                ]

                toas = toa.get_TOAs_list(toaList)

                ph = model.phase(toas)
                dt = (nodes * u.day - tmid).to("min")  # Use constant
                rdcPhase = ph - refPhase
                rdcPhase = (rdcPhase.int -
                            (dt.value * model.F0.value * 60.0) * u.cycle +
                            rdcPhase.frac)
                dtd = dt.value.astype(float)  # Truncate to double
                rdcPhased = rdcPhase.astype(float)
                coeffs = np.polyfit(dtd, rdcPhased, ncoeff - 1)
                coeffs = coeffs[::-1]
                midTime = Time(int(tmid.value),
                               np.modf(tmid.value)[0],
                               format="mjd",
                               scale="utc")
                date, hms = midTime.iso.split()
                yy, mm, dd = date.split("-")
                date = dd + "-" + month[int(mm) - 1] + "-" + yy[2:4]
                hms = hms.replace(":", "")
                entry = PolycoEntry(
                    tmid.value,
                    mjdSpan.to("day").value,
                    refPhase.int,
                    refPhase.frac,
                    model.F0.value,
                    ncoeff,
                    coeffs,
                    obs,
                )
                entryList.append((
                    model.PSR.value,
                    date,
                    hms,
                    tmid.value,
                    model.DM.value,
                    0.0,
                    0.0,
                    0.0,
                    mjdSpan.to("day").value,
                    tStart,
                    tStop,
                    obs,
                    obsFreq,
                    entry,
                ))

            pTable = table.Table(
                rows=entryList,
                names=(
                    "psr",
                    "date",
                    "utc",
                    "tmid",
                    "dm",
                    "doppler",
                    "logrms",
                    "binary_phase",
                    "mjd_span",
                    "t_start",
                    "t_stop",
                    "obs",
                    "obsfreq",
                    "entry",
                ),
                meta={"name": "Polyco Data Table"},
            )
            self.polycoTable = pTable
            if len(self.polycoTable) == 0:
                raise ValueError("Zero polycos found for table")
        else:
            #  Reading from an old polycofile
            pass
Beispiel #10
0
def tempo_polyco_table_reader(filename):
    """Read tempo style polyco file to an astropy table.

    Tempo style: The polynomial ephemerides are written to file 'polyco.dat'.  Entries
    are listed sequentially within the file.  The file format is::

        ====  =======   ============================================
        Line  Columns     Item
        ====  =======   ============================================
         1       1-10   Pulsar Name
                11-19   Date (dd-mmm-yy)
                20-31   UTC (hhmmss.ss)
                32-51   TMID (MJD)
                52-72   DM
                74-79   Doppler shift due to earth motion (10^-4)
                80-86   Log_10 of fit rms residual in periods
         2       1-20   Reference Phase (RPHASE)
                21-38   Reference rotation frequency (F0)
                39-43   Observatory number
                44-49   Data span (minutes)
                50-54   Number of coefficients
                55-75   Observing frequency (MHz)
                76-80   Binary phase
         3*      1-25   Coefficient 1 (COEFF(1))
                26-50   Coefficient 2 (COEFF(2))
                51-75   Coefficient 3 (COEFF(3))
        ====  =======   ============================================
        * Subsequent lines have three coefficients each, up to NCOEFF

    One polyco file could include more then one entrie

    The pulse phase and frequency at time T are then calculated as::

        DT = (T-TMID)*1440
        PHASE = RPHASE + DT*60*F0 + COEFF(1) + DT*COEFF(2) + DT^2*COEFF(3) + ....
        FREQ(Hz) = F0 + (1/60)*(COEFF(2) + 2*DT*COEFF(3) + 3*DT^2*COEFF(4) + ....)

    Parameters
    ----------
    filename : str
        Name of the input poloco file.

    References
    ----------
    http://tempo.sourceforge.net/ref_man_sections/tz-polyco.txt
    """
    f = open(filename, "r")
    # Read entries to the end of file
    entries = []
    while True:
        # Read first line
        line1 = f.readline()
        if len(line1) == 0:
            break

        fields = line1.split()
        psrname = fields[0].strip()
        date = fields[1].strip()
        utc = fields[2]
        tmid = np.longdouble(fields[3])
        dm = float(fields[4])
        doppler = float(fields[5])
        logrms = float(fields[6])
        # Read second line
        line2 = f.readline()
        fields = line2.split()
        refPhaseInt, refPhaseFrac = fields[0].split(".")
        refPhaseInt = data2longdouble(refPhaseInt)
        refPhaseFrac = data2longdouble("." + refPhaseFrac)
        if refPhaseInt < 0:
            refPhaseFrac = -refPhaseFrac

        refF0 = data2longdouble(fields[1])
        obs = fields[2]
        mjdSpan = data2longdouble(
            fields[3]) / MIN_PER_DAY  # Here change to constant
        nCoeff = int(fields[4])
        obsfreq = float(fields[5].strip())

        try:
            binaryPhase = data2longdouble(fields[6])
        except ValueError:
            binaryPhase = data2longdouble(0.0)

        # Read coefficients
        nCoeffLines = int(np.ceil(nCoeff / 3))

        # if nCoeff%3>0:
        #    nCoeffLines += 1
        coeffs = []

        for i in range(nCoeffLines):
            line = f.readline()
            for c in line.split():
                coeffs.append(data2longdouble(c))
        coeffs = np.array(coeffs)

        tmid = tmid * u.day
        mjdspan = mjdSpan * u.day
        tstart = data2longdouble(tmid) - data2longdouble(mjdspan) / 2.0
        tstop = data2longdouble(tmid) + data2longdouble(mjdspan) / 2.0
        rphase = Phase(refPhaseInt, refPhaseFrac)
        refF0 = data2longdouble(refF0)
        coeffs = data2longdouble(coeffs)
        entry = PolycoEntry(tmid, mjdspan, refPhaseInt, refPhaseFrac, refF0,
                            nCoeff, coeffs, obs)

        entries.append((
            psrname,
            date,
            utc,
            tmid.value,
            dm,
            doppler,
            logrms,
            binaryPhase,
            mjdspan,
            tstart,
            tstop,
            obs,
            obsfreq,
            entry,
        ))
    entry_list = []
    for ii in range(len(entries[0])):
        entry_list.append([t[ii] for t in entries])

    # Construct the polyco data table
    pTable = table.Table(
        entry_list,
        names=(
            "psr",
            "date",
            "utc",
            "tmid",
            "dm",
            "doppler",
            "logrms",
            "binary_phase",
            "mjd_span",
            "t_start",
            "t_stop",
            "obs",
            "obsfreq",
            "entry",
        ),
        meta={"name": "Polyco Data Table"},
    )

    pTable["index"] = np.arange(len(entries))
    return pTable
Beispiel #11
0
def test_data2longdouble_converts_arrays(a):
    assert_array_equal(data2longdouble(a), np.asarray(a, dtype=np.longdouble))
Beispiel #12
0
def test_data2longdouble_accepts_types(d, ld):
    assert data2longdouble(d) == ld