18Wrapper class for the PulsarParameters structure, so that it can be accessed
19in a dictionary-like way.
23from __future__
import division, absolute_import, print_function
30from astropy
import units
as u
41 "DM": u.pc / (u.cm) ** 3,
42 "DM1": u.pc / (u.cm**3 * u.yr),
64 "GLF2": u.Hz / u.s**2,
72 "EPS1": u.dimensionless_unscaled,
73 "EPS2": u.dimensionless_unscaled,
82 "SINI": u.dimensionless_unscaled,
85 "DR": u.dimensionless_unscaled,
86 "DTHETA": u.dimensionless_unscaled,
87 "SHAPMAX": u.dimensionless_unscaled,
109 "H0": u.dimensionless_unscaled,
110 "APLUS": u.dimensionless_unscaled,
111 "ACROSS": u.dimensionless_unscaled,
114 "COSIOTA": u.dimensionless_unscaled,
116 "C22": u.dimensionless_unscaled,
117 "C21": u.dimensionless_unscaled,
120 "CGW": u.dimensionless_unscaled,
122 "COSTHETA": u.dimensionless_unscaled,
124 "I21": u.dimensionless_unscaled,
125 "I31": u.dimensionless_unscaled,
126 "Q22": u.kg * u.m**2,
127 "H0_F": u.dimensionless_unscaled,
128 "HPLUS": u.dimensionless_unscaled,
129 "HCROSS": u.dimensionless_unscaled,
132 "HSCALARB": u.dimensionless_unscaled,
133 "HSCALARL": u.dimensionless_unscaled,
136 "HVECTORX": u.dimensionless_unscaled,
137 "HVECTORY": u.dimensionless_unscaled,
140 "HPLUS_F": u.dimensionless_unscaled,
141 "HCROSS_F": u.dimensionless_unscaled,
142 "PSITENSOR_F": u.rad,
143 "PHI0TENSOR_F": u.rad,
144 "HSCALARB_F": u.dimensionless_unscaled,
145 "HSCALARL_F": u.dimensionless_unscaled,
146 "PSISCALAR_F": u.rad,
147 "PHI0SCALAR_F": u.rad,
148 "HVECTORX_F": u.dimensionless_unscaled,
149 "HVECTORY_F": u.dimensionless_unscaled,
150 "PSIVECTOR_F": u.rad,
151 "PHI0VECTOR_F": u.rad,
152 "TRANSIENTSTARTTIME": u.s,
164 "PMRA": u.mas / u.yr,
165 "PMDEC": u.mas / u.yr,
168 "PMELONG": u.mas / u.yr,
169 "PMELAT": u.mas / u.yr,
172 "PMBETA": u.mas / u.yr,
173 "PMLAMBDA": u.mas / u.yr,
183 "OMDOT": u.deg / u.yr,
192 "D_AOP": 1.0 / u.arcsec,
199 "TRANSIENTSTARTTIME": u.d,
214 A class to wrap the SWIG-wrapped lalpulsar.PulsarParameters structure.
216 This
class lets you access the structure in
a more Pythonic way, as well as providing
217 a nice format
for holding pulsar (`.par`) parameter files.
219 The
class can be used to set numerical values (double precision, unsigned integers), strings,
220 or vectors of floating point values, e.g.:
224 >>> pppy[
'DECJ'] = 0.23
225 >>> pppy[
'BINARY'] =
'BT'
226 >>> pppy[
'F'] = [10.2, 1.4e-11]
229 pp (PulsarParameters, str): a lalpulsar.PulsarParameters structure,
or a string giving the
230 path to a TEMPO-style (`.par`) pulsar parameter file. If nothing
is given then an empty
231 lalpulsar.PulsarParameters structure
is created. The `read()` method can subsequently
232 be used to read
in a `.par` file,
or parameters can be added.
235 An example of initialising the
class with
a previously created `lalpulsar.PulsarParameters`
241 >>> pp = lalpulsar.ReadTEMPOParFile(
'apulsar.par')
245 The same thing could be achieved more directly using:
249 or, equivalently
with:
252 >>> pppy.read(
'apulsar.par')
258 _pulsarparameters =
None
266 if not isinstance(pp, lalpulsar.PulsarParameters)
and isinstance(pp, str):
267 if os.path.isfile(pp):
271 raise ValueError(
"Input string does not point to a file")
272 elif isinstance(pp, lalpulsar.PulsarParameters):
276 "Expected 'lalpulsar.PulsarParameters' type, string, or None"
289 Get value from pulsar parameters
298 if key[-4:].upper() ==
"_ERR":
307 sname = re.sub(
r"_\d",
"", tkey)
if "_" in tkey
else re.sub(
r"\d",
"", tkey)
310 if sname != tkey
and tkey[0:2] !=
"GL":
314 int(tkey.split(
"_")[-1])
if "_" in tkey
else int(tkey[len(sname) :])
336 if ptype == lalpulsar.PULSARTYPE_REAL8_t:
341 elif ptype == lalpulsar.PULSARTYPE_REAL8Vector_t:
344 tmpvalue = lalpulsar.PulsarGetREAL8VectorParam(
351 value = lalpulsar.PulsarGetREAL8VectorParamIndividual(
356 tmpvalue = lalpulsar.PulsarGetREAL8VectorParamErr(
359 value = tmpvalue.data
361 value = lalpulsar.PulsarGetREAL8VectorParamErrIndividual(
364 elif ptype == lalpulsar.PULSARTYPE_string_t:
368 raise ValueError(
"String-type cannot have an error")
369 elif ptype == lalpulsar.PULSARTYPE_UINT4_t:
373 raise ValueError(
"UINT4-type cannot have an error")
375 raise ValueError(
"Unrecognised type")
381 Set the value of a key
388 if isinstance(value, float):
390 elif isinstance(value, str):
392 elif isinstance(value, int):
397 elif isinstance(value, list)
or isinstance(value, np.ndarray):
398 tarray = lal.CreateREAL8Vector(len(value))
399 for i, tv
in enumerate(value):
400 if isinstance(tv, float):
403 raise ValueError(
"Non-float value in list or array")
406 raise ValueError(
"Data-type not one of know types")
410 Convert parameter values to equivalent dimensional versions.
413 name (str): the name of the parameter to convert
414 value: the value to the parameter to convert
417 :class:`astropy.unit.Unit`: a unit
class with dimensions for
a float parameters, or
a
418 list containing unit classes
for a list
or :
class:`numpy.ndarray`
421 if isinstance(value, str):
427 ppunit = u.dimensionless_unscaled
429 ppunit = PPUNITS[uname]
431 if isinstance(value, np.ndarray)
or isinstance(value, list):
435 cvalue.append(v * ppunit)
436 if uname
in [
"F",
"FB",
"P"]:
439 cvalue = value * ppunit
445 Convert from PulsarParameter units to TEMPO-par-file units
448 name (str): a parameter name
449 value (float, list, :
class:`numpy.ndarray`): the value of the parameter
450 iserr (bool): state whether where converting the parameter
's error value
453 :class:`astropy.unit.Unit`: a unit
class with dimensions for
a float parameters, or
a
454 list containing unit classes
for a list
or :
class:`numpy.ndarray`
457 from astropy.coordinates
import ICRS, Angle
458 from astropy.time
import Time
463 binaryunits = [
"XDOT",
"PBDOT",
"EPS1DOT",
"EPS2DOT",
"XPBDOT"]
479 "TRANSIENTSTARTTIME",
486 ppunit = PPUNITS[uname]
489 if uname
in TEMPOUNITS:
491 tempounit = TEMPOUNITS[uname]
493 if uname
not in TEMPOERRUNITS:
494 tempounit = TEMPOUNITS[uname]
496 tempounit = TEMPOERRUNITS[uname]
499 if uname
in binaryunits:
501 if abs(value) / 1e-12 > 1e-7:
504 if isinstance(value, str):
507 return value * u.dimensionless_unscaled
512 if ppunit == tempounit
or tempounit
is None:
515 if uname
in [
"RA",
"RAJ"]:
518 c = ICRS(pvalue, 0.0 * u.rad)
519 cvalue = c.ra.to_string(unit=tempounit, sep=
":", precision=12, pad=
True)
521 angle = Angle(pvalue)
523 angle.hms[0] * (60.0**2) + angle.hms[1] * 60.0 + angle.hms[2]
525 elif uname
in [
"DEC",
"DECJ"]
and not iserr:
526 c = ICRS(0.0 * u.rad, pvalue)
527 cvalue = c.dec.to_string(unit=tempounit, sep=
":", precision=12, pad=
True)
528 elif uname
in epochpars
and not iserr:
529 if isinstance(pvalue, list):
531 for i, pv
in enumerate(pvalue):
532 t = Time(pv, format=
"gps", scale=
"tt")
533 cvalue.append(t.mjd * tempounit)
535 t = Time(pvalue, format=
"gps", scale=
"tt")
536 cvalue = t.mjd * tempounit
537 elif uname
in binaryunits
and not iserr:
539 if abs(pvalue.value) / 1e-12 > 1e-7:
540 pvalue.value /= 1e-12
541 cvalue = pvalue.to(tempounit)
544 if isinstance(pvalue, list):
547 for i, pv
in enumerate(pvalue):
548 cvalue.append(pv.to(tempounit))
549 if uname
in [
"F",
"FB",
"P"]:
554 cvalue = pvalue.to(tempounit)
558 def parameter(self, name, withunits=False, tempounits=False):
560 Return the parameter given by name.
563 name (str): the name of the parameter to return
564 withunits (bool):
if True return the parameter
in a form
with its appropriate units
565 tempounits (bool): of
True return the parameter converted into the units required
in a
566 TEMPO-style parameter file
574 if name.upper()[-4:] ==
"_ERR":
575 uname = name.upper()[:-4]
592 Return a list of the parameter names stored in the PulsarParameters structure
599 tname = thisitem.name
603 thisitem = thisitem.next
612 Return the values of each parameter in the structure
623 if ptype == lalpulsar.PULSARTYPE_REAL8_t:
625 elif ptype == lalpulsar.PULSARTYPE_REAL8Vector_t:
626 tmpvalue = lalpulsar.PulsarGetREAL8VectorParam(
632 elif ptype == lalpulsar.PULSARTYPE_string_t:
634 elif ptype == lalpulsar.PULSARTYPE_UINT4_t:
637 raise ValueError(
"UINT4-type cannot have an error")
639 raise ValueError(
"Could not find {} in strcuture".
format(key))
641 tvalues.append(value)
647 Return the contents (not error at the moment) of the structure
as a dictionary
652 for tpair
in self.
items():
653 tdict[tpair[0]] = tpair[1]
659 Return list of item tuples for each parameter
in the structure
667 for tk, tv
in zip(tkeys, tvalues):
668 titems.append((tk, tv))
672 def read(self, filename):
674 Read a TEMPO-style parameter file into a PulsarParameters structure
677 filename (str): the path to the pulsar `.par` file.
684 pp = lalpulsar.ReadTEMPOParFile(filename)
688 "Problem reading in pulsar parameter file '{}'".
format(filename)
695 Return the error value for a particular parameter
698 name (str): the name of the parameter
702 if name.upper()[-4:] ==
"_ERR":
703 return self[name.upper()]
705 uname = name.upper() +
"_ERR"
712 Return the "fit flag" (a 1
or 0 depending whether the parameter
with fit
for by TEMPO(2)
716 name (str): the name of the parameter
719 if name.upper()
not in self.
keys():
724 if len(fitflag.data) > 1
or isinstance(self[name.upper()], (list, np.ndarray)):
727 return fitflag.data[0]
731 Convert the PulsarParameter structure to a string in the format of a
732 TEMPO-style `.par` file.
735 precision (int): the number of decimal places
for an output value
738 str: the contents
in TEMPO-format
743 max([len(kn)
for kn
in self.
keys()]) + 5
746 outputstr =
"{{name: <{0}}}{{value: <{1}}}{{fitflag}}\t{{error}}".
format(
755 for item
in self.
items():
759 if key
in [
"WAVESIN",
"WAVECOS"]
and parsedwaves:
767 if key
in TEMPOUNITS:
769 if evalue
is not None:
773 if isinstance(uvalue, list):
776 for tv, te
in zip(uvalue, uevalue):
777 tvalue.append(tv.value)
778 tevalue.append(te.value)
779 elif isinstance(uvalue, str):
781 tevalue = uevalue.value
783 tvalue = uvalue.value
784 tevalue = uevalue.value
790 if evalue
is not None:
795 if isinstance(tvalue, list)
or isinstance(tvalue, np.ndarray):
816 if key
in [
"WAVESIN",
"WAVECOS"]:
822 wavecos = self[
"WAVECOS"]
824 wavesin = self[
"WAVESIN"]
827 for ws, wc
in zip(wavesin, wavecos):
828 precstrs =
"{{0:.{}f}}".
format(precision)
829 if ws < 1e-6
or ws > 1e6:
831 precstrs =
"{{0:.{}e}}".
format(precision)
833 precstrc =
"{{0:.{}f}}".
format(precision)
834 if wc < 1e-6
or wc > 1e6:
836 precstrc =
"{{0:.{}e}}".
format(precision)
839 outputdic[
"name"] =
"WAVE{}{}".
format(idxsep, idxoffset)
841 outputdic[
"value"] =
"{}\t{}".
format(
842 precstrs.format(ws), precstrc.format(wc)
844 outputdic[
"fitflag"] =
""
845 outputdic[
"error"] =
""
847 parstr += outputstr.format(**outputdic).strip() +
"\n"
849 for tv, te, tf
in zip(tvalue, tevalue, fitflag):
850 precstr =
"{{0:.{}f}}".
format(precision)
851 if tv < 1e-6
or tv > 1e6:
853 precstr =
"{{0:.{}e}}".
format(precision)
855 precstre =
"{{0:.{}f}}".
format(precision)
856 if te < 1e-6
or te > 1e6:
858 precstre =
"{{0:.{}e}}".
format(precision)
861 outputdic[
"name"] =
"{}{}{}".
format(key, idxsep, idxoffset)
863 outputdic[
"value"] = precstr.format(tv)
864 outputdic[
"fitflag"] =
"1" if tf == 1
else ""
865 outputdic[
"error"] = precstre.format(te)
if te != 0.0
else ""
867 parstr += outputstr.format(**outputdic).strip() +
"\n"
869 if isinstance(tvalue, float)
or key
in [
"RA",
"RAJ",
"DEC",
"DECJ"]:
870 if isinstance(tvalue, float):
871 precstr =
"{{0:.{}f}}".
format(precision)
872 if tvalue < 1e-6
or tvalue > 1e6:
874 precstr =
"{{0:.{}e}}".
format(precision)
876 ovalue = precstr.format(tvalue)
880 precstre =
"{{0:.{}f}}".
format(precision)
882 if tevalue
is not None:
884 if tevalue < 1e-6
or tevalue > 1e6:
886 precstre =
"{{0:.{}e}}".
format(precision)
888 oevalue = precstre.format(tevalue)
890 if fitflag
is not None:
897 outputdic[
"name"] = key
898 outputdic[
"value"] = ovalue
899 outputdic[
"fitflag"] = ofitflag
900 outputdic[
"error"] = oevalue
902 parstr += outputstr.format(**outputdic).strip() +
"\n"
906 def pp_to_par(self, filename, precision=19):
908 Output the PulsarParameter structure to a `.par` file.
911 filename (str): the path to the output file
912 precision (int): the number of decimal places for an output value
916 fp = open(filename,
"w")
918 raise IOError(
"Could not open file '{}' for writing".
format(filename))
920 fp.write(self.
pp_to_str(precision=precision))
925 Return the PulsarParameters structure
932 Create a copy of the parameters.
936 memo[id(self)] = newpar
937 lalpulsar.PulsarCopyParams(self.PulsarParameters(), newpar.PulsarParameters())
A class to wrap the SWIG-wrapped lalpulsar.PulsarParameters structure.
def __init__(self, pp=None)
def read(self, filename)
Read a TEMPO-style parameter file into a PulsarParameters structure.
def pp_to_par(self, filename, precision=19)
Output the PulsarParameter structure to a .par file.
def get_fitflag(self, name)
Return the "fit flag" (a 1 or 0 depending whether the parameter with fit for by TEMPO(2) in the ....
def convert_to_tempo_units(self, name, value, iserr=False)
Convert from PulsarParameter units to TEMPO-par-file units.
def __deepcopy__(self, memo)
Create a copy of the parameters.
def __setitem__(self, key, value)
Set the value of a key.
def __getitem__(self, key)
Get value from pulsar parameters.
def parameter(self, name, withunits=False, tempounits=False)
Return the parameter given by name.
def pp_to_str(self, precision=19)
Convert the PulsarParameter structure to a string in the format of a TEMPO-style ....
def as_dict(self)
Return the contents (not error at the moment) of the structure as a dictionary.
def keys(self)
Return a list of the parameter names stored in the PulsarParameters structure.
def PulsarParameters(self)
Return the PulsarParameters structure.
def get_error(self, name)
Return the error value for a particular parameter.
def convert_to_units(self, name, value)
Convert parameter values to equivalent dimensional versions.
def items(self)
Return list of item tuples for each parameter in the structure.
def values(self)
Return the values of each parameter in the structure.