nanograv / PINT

PINT is not TEMPO3 -- Software for high-precision pulsar timing
Other
121 stars 101 forks source link

Publication output #1582

Closed paulray closed 1 year ago

paulray commented 1 year ago

It would be nice if PINT had a function to write out a timing model in LaTeX table form, suitable for pasting into a publication. Tempo2 has such a plugin.

scottransom commented 1 year ago

I have a lot of python code that does this. Could be fairly easy to make a basic one. Although the problem is that there are lots of special cases...

abhisrkckl commented 1 year ago

Just out of curiosity, what is the tempo2 plugin called?

paulray commented 1 year ago

If you run this command, it will generate table.tex:

tempo2 -output publish -f NGC6440E.par NGC6440E.tim

and here is the output:

\documentclass{article}
\begin{document}
\begin{table}
\caption{Parameters for PSR 1748$-$2021E}
\begin{tabular}{ll}
\hline\hline
\multicolumn{2}{c}{Fit and data-set} \\
\hline
Pulsar name\dotfill & J1748$-$2021E \\ 
MJD range\dotfill & 53478.3---54187.6 \\ 
Data span (yr)\dotfill & 1.94 \\ 
Number of TOAs\dotfill & 62 \\
Rms timing residual ($\mu s$)\dotfill & 31.7 \\
Weighted fit\dotfill &  N \\ 
\hline
\multicolumn{2}{c}{Measured Quantities} \\ 
\hline
Right ascension, $\alpha$ (hh:mm:ss)\dotfill &  17:48:52.8003(3) \\ 
Declination, $\delta$ (dd:mm:ss)\dotfill & $-$20:21:29.37(6) \\ 
Pulse frequency, $\nu$ (s$^{-1}$)\dotfill & 61.48547655437(3) \\ 
First derivative of pulse frequency, $\dot{\nu}$ (s$^{-2}$)\dotfill & $-$1.181(3)$\times 10^{-15}$ \\ 
Dispersion measure, DM (cm$^{-3}$pc)\dotfill & 224.19(4) \\ 
\hline
\multicolumn{2}{c}{Set Quantities} \\ 
\hline
Epoch of frequency determination (MJD)\dotfill & 53750 \\ 
Epoch of position determination (MJD)\dotfill & 53750 \\ 
Epoch of dispersion measure determination (MJD)\dotfill & 53750 \\ 
NE_SW (cm^-3)\dotfill & 0 \\ 
\hline
\multicolumn{2}{c}{Derived Quantities} \\
\hline
$\log_{10}$(Characteristic age, yr) \dotfill & 8.92 \\
$\log_{10}$(Surface magnetic field strength, G) \dotfill & 9.36 \\
$\log_{10}$(Edot, ergs/s) \dotfill & 33.46 \\
\hline
\multicolumn{2}{c}{Assumptions} \\
\hline
Clock correction procedure\dotfill & TT(BIPM2019) \\
Solar system ephemeris model\dotfill & DE421 \\
Binary model\dotfill & NONE \\
TDB units (tempo1 mode)\dotfill & Y \\
FB90 time ephemeris (tempo1 mode)\dotfill & Y \\
Shapiro delay due to planets\dotfill & N \\
Tropospheric delay\dotfill & N \\
Dilate frequency\dotfill & N \\
Electron density at 1 AU (cm$^{-3}$)\dotfill & 0.00 \\ 
Model version number\dotfill & 2.00 \\ 
\hline
\end{tabular}
\end{table}
\end{document}
scottransom commented 1 year ago

Here is an example script that uses the uncertainties package, and PRESTO's parfile reader to generate a nice LaTeX table. We would want to modify this to use PINT's model information, obviously. But this should give an idea of what some of the code could look like. Note that this version puts multiple pulsars on each row.

import sys
import numpy as np
import presto.parfile as pp
import presto.psr_utils as pu
import uncertainties as unc

numdigits = 1
Mpsr = 1.4
errfac = 1.0

def valerr(val, err, digits=numdigits, errfac=errfac):
    x = unc.ufloat(val, err * errfac)
    fstr = "{:.%duSL}" % digits
    return fstr.format(x)

def split_RAJ(raj, raj_err, errfac=errfac):
    h,m,s = raj.split(':')
    s_str = valerr(float(s), raj_err, errfac=errfac)
    if float(s) < 10.0:
        s_str.zfill(len(s_str)+1)
    s_str = s_str.replace('.', '\\fs')
    return r"$%s^{\rm h}\;%s^{\rm m}\;0%s$" % (h, m, s_str)

def split_DECJ(decj, decj_err, errfac=errfac):
    d,m,s = decj.split(':')
    s_str = valerr(float(s), decj_err, errfac=errfac)
    if float(s) < 10.0:
        s_str.zfill(len(s_str)+1)
    s_str = s_str.replace('.', '\\farcs')
    return r"$%s\degrees\;%s\amin\;%s$" % (d, m, s_str)

def mf_with_err(x, xerr, pb, pberr):
    # Return the mass function with its error using error propagation
    # x is in lt-sec and pb is in days
    x = unc.ufloat(x, xerr)
    pb = unc.ufloat(pb, pberr)
    mf = pu.mass_funct(pb, x)
    return (mf.n, mf.s)

parname = "1748-2446am_std.par"
psrname = "J1748$-$2446am"
psrs = [pp.psr_par(parname)]

print(r"""\begin{deluxetable}{lc}
\tabletypesize{\footnotesize}
\tablecaption{PSR %s\label{tab1}}
\tablewidth{0pt}
\startdata""" % psrname)
print(r"\cutinhead{Timing Parameters}")
print(r"Right Ascension (RA, J2000) \dotfill & %s\\" % \
    tuple([split_RAJ(psr.RAJ, psr.RAJ_ERR) for psr in psrs]))
print(r"Declination     (DEC, J2000) \dotfill & %s\\" % \
    tuple([split_DECJ(psr.DECJ, psr.DECJ_ERR) for psr in psrs]))
print(r"Pulsar Period (ms) \dotfill & %s\\" % \
    tuple([valerr(psr.P0*1000.0, psr.P0_ERR*1000.0) for psr in psrs]))
print(r"Pulsar Frequency (Hz) \dotfill & %s\\" % \
    tuple([valerr(psr.F0, psr.F0_ERR) for psr in psrs]))
print(r"Frequency Derivative (Hz\,s$^{-1}$) \dotfill & %s\\" % \
    tuple([valerr(psr.F1, psr.F1_ERR) for psr in psrs]))
print(r"Reference Epoch (MJD) \dotfill & %.12g\\" % \
    tuple([psr.PEPOCH for psr in psrs]))
print(r"Dispersion Measure (pc cm$^{-3}$) \dotfill & %s\\" % \
    tuple([valerr(psr.DM, psr.DM_ERR) for psr in psrs]))
print(r"Orbital Period (days) \dotfill & %s\\" % \
    tuple([valerr(psr.PB, psr.PB_ERR) for psr in psrs]))
print(r"Projected Semi-Major Axis (lt-s)  \dotfill & %s\\" % \
    tuple([valerr(psr.A1, psr.A1_ERR) for psr in psrs]))
print(r"Orbital Eccentricity  \dotfill & %s\\" % \
    tuple([valerr(psr.ECC, psr.ECC_ERR) for psr in psrs]))
print(r"Epoch of Periastron (MJD) \dotfill & %s\\" % \
    tuple([valerr(psr.T0, psr.T0_ERR) for psr in psrs]))
print(r"Longitude of Periastron, $\omega$ (deg) \dotfill & %s\\" % \
    tuple([valerr(psr.OM, psr.OM_ERR) for psr in psrs]))
print(r"Time Derivative of $\omega$, $\dot\omega$ (deg\,yr$^{-1}$) \dotfill & %s\\" % \
    tuple([valerr(psr.OMDOT, psr.OMDOT_ERR) for psr in psrs]))
spans = [[psr.START, psr.FINISH] for psr in psrs]
spans = tuple([item for sublist in spans for item in sublist])
print(r"Span of Timing Data (MJD) \dotfill & %.0f$-$%.0f\\" % spans)
print(r"Number of TOAs  \dotfill & %.0f\\" % (217))
print(r"RMS TOA Residual ($\mu$s) \dotfill & %.1f\\" % (38.55))

print(r"\cutinhead{Derived Parameters}")
ve_pairs = []
for psr in psrs:
    ve_pairs.append(mf_with_err(psr.A1, psr.A1_ERR*errfac, psr.PB, psr.PB_ERR*errfac))
print(r"Mass Function (\msun) \dotfill & %s\\" % \
    tuple([valerr(*ve_pair) for ve_pair in ve_pairs]))
Mtot = pu.OMDOT_to_Mtot(psr.OMDOT, psr.PB, psr.E)
Mthi = pu.OMDOT_to_Mtot(psr.OMDOT+psr.OMDOT_ERR, psr.PB, psr.E)
Mtlo = pu.OMDOT_to_Mtot(psr.OMDOT-psr.OMDOT_ERR, psr.PB, psr.E)
Mtot_err = 0.5 * ((Mthi-Mtot) + (Mtot-Mtlo))
print(r"Total System Mass (\msun) \dotfill & %s\\" % \
    tuple([valerr(Mtot, Mtot_err*errfac)]))
print(r"Min Companion Mass (\msun) \dotfill & $\geq$\,%.2g\\" % \
    tuple([pu.companion_mass_limit(psr.PB, psr.A1, mpsr=Mpsr) for psr in psrs]))
print(r"Companion Mass (\msun) \dotfill & %.3g ($+$%.2g, $-$%.2g)\\" % \
    (0.1936, 0.114, 0.0233))
print(r"Pulsar Mass (\msun) \dotfill & %.4g ($+$%.2g, $-$%.2g)\\" % \
    (1.6492, 0.0369, 0.109))
print(r"Flux Density at 2\,GHz (mJy) \dotfill & %.2g" % \
    (0.06))
print(r"""\enddata

\tablecomments{Numbers in parentheses represent %g-$\sigma$""" % (errfac))
print(r"""uncertainties in the last digit.  The timing solution was
determined using {\tt TEMPO} with the DE436 Solar System Ephemeris and
the DD binary model. The time system used is Barycentric Dynamical
Time (TDB).  The minimum companion mass was calculated assuming a
pulsar mass of 1.4\,\msun.  The total system mass and 68\% central
confidence ranges on the masses of the pulsar and its companion were
determined assuming that $\dot\omega$ is due completely to general
relativity, and a random orbital inclination (i.e.~probability density
is constant in $\cos i$).}
\end{deluxetable}""")
scottransom commented 1 year ago

I should have mentioned that that code was used to make Table 1 in Andersen & Ransom, 2018.

dlakaplan commented 1 year ago

The method as_ufloat() may be useful to turn a parameter into an uncertainties.ufloat for printing or computing.