Example #1
0
    def build_model(self, parfile=None, name=''):
        """Read parfile using the model_instance attribute.
        Parameters
        ---------
        name: str, optional
            The name for the timing model
        parfile : str optional
            The parfile name
        """
        if parfile is not None:
            self.get_comp_from_parfile(parfile)
        sorted_comps = self.sort_components()
        self.timing_model = TimingModel(name, sorted_comps)
        param_inModel = self.timing_model.get_params_mapping()
        # Find unrecognised parameters in par file.

        if self.param_inparF is not None:
            parName = []
            # add aliases
            for p in list(param_inModel.keys()):
                parName+= getattr(self.timing_model, p).aliases

            parName += param_inModel.keys()

            for pp in self.param_inparF.keys():
                if pp not in parName:
                    self.param_unrecognized[pp] = self.param_inparF[pp]

            for ptype in ['prefixParameter', 'maskParameter']:
                prefix_param = \
                    self.search_prefix_param( \
                         list(self.param_unrecognized.keys()),self.timing_model,
                         ptype)
                prefix_in_model = self.timing_model.get_params_of_type(ptype)
                for key in prefix_param.keys():
                    ppnames = [x for x in prefix_in_model if x.startswith(key)]
                    for ppn in ppnames:
                        pfx, idxs, idxv = split_prefixed_name(ppn)
                        if pfx == key:
                            exm_par = getattr(self.timing_model, ppn)
                        else:
                            continue
                    exm_par_comp = param_inModel[exm_par.name]
                    for parname in prefix_param[key]:
                        pre,idstr,idx = split_prefixed_name(parname)
                        if idx == exm_par.index:
                            continue
                        if hasattr(exm_par, 'new_param'):
                            new_par = exm_par.new_param(idx)
                            self.timing_model.add_param_from_top(new_par,
                                                                 exm_par_comp)

        if parfile is not None:
            self.timing_model.read_parfile(parfile)
Example #2
0
    def build_model(self, parfile=None, name=''):
        """Read parfile using the model_instance attribute.
        Parameters
        ---------
        name: str, optional
            The name for the timing model
        parfile : str optional
            The parfile name
        """
        if parfile is not None:
            self.get_comp_from_parfile(parfile)
        sorted_comps = self.sort_components()
        self.timing_model = TimingModel(name, sorted_comps)
        param_inModel = self.timing_model.get_params_mapping()
        # Find unrecognised parameters in par file.

        if self.param_inparF is not None:
            parName = []
            # add aliases
            for p in list(param_inModel.keys()):
                parName += getattr(self.timing_model, p).aliases

            parName += param_inModel.keys()

            for pp in self.param_inparF.keys():
                if pp not in parName:
                    self.param_unrecognized[pp] = self.param_inparF[pp]

            for ptype in ['prefixParameter', 'maskParameter']:
                prefix_param = \
                    self.search_prefix_param( \
                         list(self.param_unrecognized.keys()),self.timing_model,
                         ptype)
                prefix_in_model = self.timing_model.get_params_of_type(ptype)
                for key in prefix_param.keys():
                    ppnames = [x for x in prefix_in_model if x.startswith(key)]
                    for ppn in ppnames:
                        pfx, idxs, idxv = split_prefixed_name(ppn)
                        if pfx == key:
                            exm_par = getattr(self.timing_model, ppn)
                        else:
                            continue
                    exm_par_comp = param_inModel[exm_par.name]
                    for parname in prefix_param[key]:
                        pre, idstr, idx = split_prefixed_name(parname)
                        if idx == exm_par.index:
                            continue
                        if hasattr(exm_par, 'new_param'):
                            new_par = exm_par.new_param(idx)
                            self.timing_model.add_param_from_top(
                                new_par, exm_par_comp)

        if parfile is not None:
            self.timing_model.read_parfile(parfile)
Example #3
0
    def d_dm_d_DMs(
            self,
            toas,
            param_name,
            acc_delay=None):  # NOTE we should have a better name for this.)
        """Derivatives of DM wrt the DM taylor expansion parameters."""
        par = getattr(self, param_name)
        if param_name == "DM":
            order = 0
        else:
            pn, idxf, idxv = split_prefixed_name(param_name)
            order = idxv
        dms = self.get_DM_terms()
        dm_terms = np.longdouble(np.zeros(len(dms)))
        dm_terms[order] = np.longdouble(1.0)
        if self.DMEPOCH.value is None:
            if any(t.value != 0 for t in dms[1:]):
                # Should be ruled out by validate()
                raise ValueError(
                    f"DMEPOCH is not set but {param_name} is not zero")
            DMEPOCH = 0
        else:
            DMEPOCH = self.DMEPOCH.value
        dt = (toas["tdbld"] - DMEPOCH) * u.day
        dt_value = (dt.to(u.yr)).value
        d_dm_d_dm_param = taylor_horner(dt_value,
                                        dm_terms) * (self.DM.units / par.units)

        return d_dm_d_dm_param
Example #4
0
    def read_parfile(self, filename):
        """Read values from the specified parfile into the model parameters."""
        pfile = open(filename, 'r')
        for l in [pl.strip() for pl in pfile.readlines()]:
            # Skip blank lines
            if not l:
                continue
            # Skip commented lines
            if l.startswith('#') or l[:2]=="C ":
                continue
            parsed = False
            for par in self.params:
                if getattr(self, par).from_parfile_line(l):
                    parsed = True
            if not parsed:
                try:
                    prefix,f,v = utils.split_prefixed_name(l.split()[0])
                    if prefix not in ignore_prefix:
                        log.warn("Unrecognized parfile line '%s'" % l)
                except:
                    if l.split()[0] not in ignore_params:
                        log.warn("Unrecognized parfile line '%s'" % l)

        # The "setup" functions contain tests for required parameters or
        # combinations of parameters, etc, that can only be done
        # after the entire parfile is read
        self.setup()
Example #5
0
 def d_phase_d_GLTD(self, toas, param, delay):
     """Calculate the derivative wrt GLF0D
     """
     tbl = toas.table
     p, ids, idv = split_prefixed_name(param)
     if p != "GLTD_":
         raise ValueError(
             "Can not calculate d_phase_d_GLF0D with respect to %s." % param
         )
     eph = np.longdouble(getattr(self, "GLEP_" + ids).value)
     par_GLTD = getattr(self, param)
     if par_GLTD.value == 0.0:
         return np.zeros(len(tbl), dtype=np.longdouble) * u.cycle / par_GLTD.units
     glf0d = getattr(self, "GLF0D_" + ids).quantity
     tau = par_GLTD.quantity
     dt = (tbl["tdbld"] - eph) * u.day - delay
     dt = dt.to(u.second)
     affected = np.where(dt > 0.0)[0]
     dpdGLTD = np.zeros(len(tbl), dtype=np.longdouble) * u.cycle / par_GLTD.units
     with u.set_enabled_equivalencies(dimensionless_cycles):
         dpdGLTD[affected] += glf0d * (
             np.longdouble(1.0) - np.exp(-dt[affected] / tau)
         ) + glf0d * tau * (-np.exp(-dt[affected] / tau)) * dt[affected] / (
             tau * tau
         )
     return dpdGLTD
Example #6
0
    def d_dm_d_DMs(
            self,
            toas,
            param_name,
            acc_delay=None):  # NOTE we should have a better name for this.)
        """ Derivatives of DM wrt the DM taylor expansion parameters.
        """
        tbl = toas.table
        try:
            bfreq = self.barycentric_radio_freq(toas)
        except AttributeError:
            warn("Using topocentric frequency for dedispersion!")
            bfreq = tbl["freq"]
        par = getattr(self, param_name)
        unit = par.units
        if param_name == "DM":
            order = 0
        else:
            pn, idxf, idxv = split_prefixed_name(param_name)
            order = idxv
        dms = self.get_DM_terms()
        dm_terms = np.longdouble(np.zeros(len(dms)))
        dm_terms[order] = np.longdouble(1.0)
        if self.DMEPOCH.value is None:
            DMEPOCH = tbl["tdbld"][0]
        else:
            DMEPOCH = self.DMEPOCH.value
        dt = (tbl["tdbld"] - DMEPOCH) * u.day
        dt_value = (dt.to(u.yr)).value
        d_dm_d_dm_param = taylor_horner(dt_value,
                                        dm_terms) * (self.DM.units / par.units)

        return d_dm_d_dm_param
Example #7
0
 def deriv_prep(self, toas, param, delay):
     """Get the things we need for any of the derivative calcs"""
     tbl = toas.table
     p, ids, idv = split_prefixed_name(param)
     eph = getattr(self, "GLEP_" + ids).value
     dt = (tbl["tdbld"] - eph) * u.day - delay
     dt = dt.to(u.second)
     affected = np.where(dt > 0.0)[0]
     return tbl, p, ids, idv, dt, affected
Example #8
0
def test_aliases_mapping():
    """Test if aliases gets mapped correclty
    """
    mb = AllComponents()
    # all alases should be mapped to the components
    assert set(mb._param_alias_map.keys()) == set(
        mb.param_component_map.keys())

    # Test if the param_alias_map is passed by pointer
    # Testing the private function for building the aliases map
    mb._check_alias_conflict("TESTAX", "TESTAXX", mb._param_alias_map)
    # assert "TESTAX" in mb._param_alias_map
    # Test existing entry
    # When adding an existing alias to the map. The mapped value should be the
    # same, otherwrise it will fail.
    mb._check_alias_conflict("F0", "F0", mb._param_alias_map)
    # assert mb._param_alias_map["F0"] == "F0"
    # Test repeatable_params with differnt indices.
    for rp in mb.repeatable_param:
        pint_par, first_init_par = mb.alias_to_pint_param(rp)
        cp = mb.param_component_map[pint_par][0]
        pint_par_obj = getattr(mb.components[cp], pint_par)
        try:
            prefix, id, ids = split_prefixed_name(rp)
        except PrefixError:
            prefix = rp

        new_idx_par = prefix + "2"
        assert mb.alias_to_pint_param(
            new_idx_par)[0] == pint_par_obj.prefix + "2"
        new_idx_par = prefix + "55"
        assert mb.alias_to_pint_param(
            new_idx_par)[0] == pint_par_obj.prefix + "55"
        # Test all aliases
        for als in pint_par_obj.aliases:
            assert mb.alias_to_pint_param(als)[0] == pint_par_obj.name
            try:
                als_prefix, id, ids = split_prefixed_name(als)
            except PrefixError:
                als_prefix = als
        assert mb.alias_to_pint_param(als_prefix +
                                      "2")[0] == pint_par_obj.prefix + "2"
        assert (mb.alias_to_pint_param(als_prefix +
                                       "55")[0] == pint_par_obj.prefix + "55")
Example #9
0
    def search_prefix_param(self, paramList, prefix_inModel):
        """ Check if the Unrecognized parameter has prefix parameter
        """
        prefixs = {}
        for pn in prefix_inModel:
            try:
                pre,idxstr,idxV = split_prefixed_name(pn)
                prefixs[pre] = []
            except:
                continue

        for p in paramList:
            try:
                pre,idxstr,idxV = split_prefixed_name(p)
                if pre in prefixs.keys():
                    prefixs[pre].append(p)
            except:
                continue

        return prefixs
Example #10
0
    def read_parfile(self, filename):
        """Read values from the specified parfile into the model parameters."""
        checked_param = []
        repeat_param = {}
        param_map = self.get_params_mapping()
        comps = self.components
        pfile = open(filename, 'r')
        for l in [pl.strip() for pl in pfile.readlines()]:
            # Skip blank lines
            if not l:
                continue
            # Skip commented lines
            if l.startswith('#') or l[:2]=="C ":
                continue

            k = l.split()
            name = k[0].upper()
            
            if name == 'UNITS' and len(k) > 1 and k[1] != 'TDB':
                log.error("UNITS %s not yet supported by PINT" % k[1])
                raise Exception("UNITS %s not yet supported by PINT" % k[1])

            
            if name in checked_param:
                if name in repeat_param.keys():
                    repeat_param[name] += 1
                else:
                    repeat_param[name] = 2
                k[0] = k[0] + str(repeat_param[name])
                l = ' '.join(k)
            parsed = False
            for par in param_map.keys():
                host_comp = param_map[par]
                if host_comp != 'timing_model':
                    cmp = comps[host_comp]
                else:
                    cmp = self
                if cmp.__getattr__(par).from_parfile_line(l):
                    parsed = True

            if not parsed:
                try:
                    prefix,f,v = utils.split_prefixed_name(l.split()[0])
                    if prefix not in ignore_prefix:
                        log.warn("Unrecognized parfile line '%s'" % l)
                except:
                    if l.split()[0] not in ignore_params:
                        log.warn("Unrecognized parfile line '%s'" % l)

            checked_param.append(name)
        # The "setup" functions contain tests for required parameters or
        # combinations of parameters, etc, that can only be done
        # after the entire parfile is read
        self.setup()
Example #11
0
    def search_prefix_param(self, paramList, prefix_inModel):
        """ Check if the Unrecognized parameter has prefix parameter
        """
        prefixs = {}
        for pn in prefix_inModel:
            try:
                pre,idxstr,idxV = split_prefixed_name(pn)
                prefixs[pre] = []
            except:
                continue

        for p in paramList:
            try:
                pre,idxstr,idxV = split_prefixed_name(p)
                if pre in prefixs.keys():
                    prefixs[pre].append(p)
            except:
                continue

        return prefixs
Example #12
0
 def d_phase_d_F(self, toas, param, delay):
     """Calculate the derivative wrt to an spin term."""
     par = getattr(self, param)
     unit = par.units
     pn, idxf, idxv = split_prefixed_name(param)
     if param.startswith("PWF"):
         order = split_prefixed_name(param[:4])[2] + 1
     else:
         order = 0
     # order = idxv + 1
     fterms = self.get_spin_terms(idxv)
     # make the choosen fterms 1 others 0
     fterms = [ft * np.longdouble(0.0) / unit for ft in fterms]
     fterms[order] += np.longdouble(1.0)
     glepnm = f"PWEP_{idxf}"
     res = u.Quantity(np.zeros(toas.ntoas,
                               dtype=np.longdouble)) * (1 / unit)
     dt, affected = self.get_dt_and_affected(toas, delay, glepnm)
     d_pphs_d_f = taylor_horner(dt.to(u.second), fterms)
     res[affected] = d_pphs_d_f.to(1 / unit)
     return res
Example #13
0
 def search_prefix_param(self,paramList,prefixList):
     """ Check if the Unrecognized parameter has prefix parameter
     """
     for pn in prefixList:
         self.param_prefix[pn] = []
         pnlen = len(pn)
         for p in paramList:
             try:
                 pre,idxstr,idxV = split_prefixed_name(p)
             except:
                 continue
             if pre == pn:
                 self.param_prefix[pn].append(p)
Example #14
0
 def d_phase_d_F(self, toas, param, delay):
     """Calculate the derivative wrt to an spin term."""
     par = getattr(self, param)
     unit = par.units
     pn, idxf, idxv = split_prefixed_name(param)
     order = idxv + 1
     fterms = [0.0 * u.Unit("")] + self.get_spin_terms()
     # make the choosen fterms 1 others 0
     fterms = [ft * numpy.longdouble(0.0) / unit for ft in fterms]
     fterms[order] += numpy.longdouble(1.0)
     dt = self.get_dt(toas, delay)
     d_pphs_d_f = taylor_horner(dt.to(u.second), fterms)
     return d_pphs_d_f.to(1 / unit)
Example #15
0
    def search_prefix_param(self, paramList, model, prefix_type):
        """Check if the Unrecognized parameter has prefix parameter"""
        prefixs = {}
        prefix_inModel = model.get_params_of_type_top(prefix_type)
        for pn in prefix_inModel:
            par = getattr(model, pn)
            prefixs[par.prefix] = []
            for p in paramList:
                try:
                    pre, idxstr, idxV = split_prefixed_name(p)
                    if pre in [par.prefix] + par.prefix_aliases:
                        prefixs[par.prefix].append(p)
                except ValueError:  # FIXME: is this meant to catch KeyErrors?
                    continue

        return prefixs
Example #16
0
 def d_phase_d_GLPH(self, toas, param, delay):
     """Calculate the derivative wrt GLPH"""
     tbl = toas.table
     p, ids, idv = split_prefixed_name(param)
     if p != "GLPH_":
         raise ValueError(
             "Can not calculate d_phase_d_GLPH with respect to %s." % param
         )
     eph = np.longdouble(getattr(self, "GLEP_" + ids).value)
     par_GLPH = getattr(self, param)
     dt = (tbl["tdbld"] - eph) * u.day - delay
     dt = dt.to(u.second)
     affected = np.where(dt > 0.0)[0]
     dpdGLPH = np.zeros(len(tbl), dtype=np.longdouble) * u.cycle / par_GLPH.units
     dpdGLPH[affected] += 1.0 * u.cycle / par_GLPH.units
     return dpdGLPH
Example #17
0
    def read_parfile(self, filename):
        """Read values from the specified parfile into the model parameters."""
        checked_param = []
        repeat_param = {}
        param_map = self.get_params_mapping()
        comps = self.components
        pfile = open(filename, 'r')
        for l in [pl.strip() for pl in pfile.readlines()]:
            # Skip blank lines
            if not l:
                continue
            # Skip commented lines
            if l.startswith('#') or l[:2]=="C ":
                continue

            k = l.split()
            name = k[0].upper()
            if name in checked_param:
                if name in repeat_param.keys():
                    repeat_param[name] += 1
                else:
                    repeat_param[name] = 2
                k[0] = k[0] + str(repeat_param[name])
                l = ' '.join(k)
            parsed = False
            for par in param_map.keys():
                host_comp = param_map[par]
                if host_comp != 'timing_model':
                    cmp = comps[host_comp]
                else:
                    cmp = self
                if cmp.__getattr__(par).from_parfile_line(l):
                    parsed = True
            if not parsed:
                try:
                    prefix,f,v = utils.split_prefixed_name(l.split()[0])
                    if prefix not in ignore_prefix:
                        log.warn("Unrecognized parfile line '%s'" % l)
                except:
                    if l.split()[0] not in ignore_params:
                        log.warn("Unrecognized parfile line '%s'" % l)

            checked_param.append(name)
        # The "setup" functions contain tests for required parameters or
        # combinations of parameters, etc, that can only be done
        # after the entire parfile is read
        self.setup()
Example #18
0
 def d_phase_d_GLF1(self, toas, param, delay):
     """Calculate the derivative wrt GLF1"""
     tbl = toas.table
     p, ids, idv = split_prefixed_name(param)
     if p != "GLF1_":
         raise ValueError(
             "Can not calculate d_phase_d_GLF1 with respect to %s." % param
         )
     eph = np.longdouble(getattr(self, "GLEP_" + ids).value)
     par_GLF1 = getattr(self, param)
     dt = (tbl["tdbld"] - eph) * u.day - delay
     dt = dt.to(u.second)
     affected = np.where(dt > 0.0)[0]
     dpdGLF1 = np.zeros(len(tbl), dtype=np.longdouble) * u.cycle / par_GLF1.units
     with u.set_enabled_equivalencies(dimensionless_cycles):
         dpdGLF1[affected] += np.longdouble(0.5) * dt[affected] * dt[affected]
     return dpdGLF1
Example #19
0
    def search_prefix_param(self, paramList, model, prefix_type):
        """ Check if the Unrecognized parameter has prefix parameter
        """
        prefixs = {}
        prefix_inModel = model.get_params_of_type(prefix_type)
        for pn in prefix_inModel:
            par = getattr(model,  pn)
            prefixs[par.prefix] = []
            for p in paramList:
                try:
                    pre,idxstr,idxV = split_prefixed_name(p)
                    if pre in [par.prefix,] + par.prefix_aliases:
                        prefixs[par.prefix].append(p)
                except:
                    continue

        return prefixs
Example #20
0
    def get_model_instance(self,parfile=None):
        """Read parfile using the model_instance attribute.
            Parameters
            ---------
            parfile : str optional
                The parfile name
        """
        if self.model_instance is None:
            model = self.build_model()

        self.model_instance = model()
        self.param_inModel = self.model_instance.params
        self.prefix_names = self.model_instance.prefix_params
        # Find unrecognised parameters in par file.

        if self.param_inparF is not None:
            parName = []
            for p in self.param_inModel:
                parName+= getattr(self.model_instance,p).aliases

            parName += self.param_inModel

            for pp in self.param_inparF.keys():
                if pp not in parName:
                    self.param_unrecognized[pp] = self.param_inparF[pp]

            self.search_prefix_param(self.param_unrecognized.keys(),self.prefix_names)

            if self.param_prefix != {}:
                for p in self.param_prefix.keys():
                    ppnames = [x for x in self.model_instance.params if x.startswith(p)]
                    for ppn in ppnames:
                        pfxp = getattr(self.model_instance,ppn)
                        if pfxp.is_prefix is True:
                            for pp in self.param_prefix[p]:
                                pre,idstr,idx = split_prefixed_name(pp)
                                if idx == pfxp.index:
                                    continue
                                newPfxp = pfxp.new_index_prefix_param(idx)
                                self.model_instance.add_param(newPfxp)

        if parfile is not None:
            self.model_instance.read_parfile(parfile)

        return self.model_instance
Example #21
0
 def d_phase_d_GLF0D(self, toas, param, delay):
     """Calculate the derivative wrt GLF0D
     """
     tbl = toas.table
     p, ids, idv = split_prefixed_name(param)
     if p != "GLF0D_":
         raise ValueError(
             "Can not calculate d_phase_d_GLF0D with respect to %s." % param
         )
     eph = np.longdouble(getattr(self, "GLEP_" + ids).value)
     par_GLF0D = getattr(self, param)
     tau = getattr(self, "GLTD_%d" % idv).quantity
     dt = (tbl["tdbld"] - eph) * u.day - delay
     dt = dt.to(u.second)
     affected = np.where(dt > 0.0)[0]
     dpdGLF0D = np.zeros(len(tbl), dtype=np.longdouble) / par_GLF0D.units
     dpdGLF0D[affected] += tau * (np.longdouble(1.0) - np.exp(-dt[affected] / tau))
     return dpdGLF0D
Example #22
0
    def get_model_instance(self,parfile=None):
        """Read parfile using the model_instance attribute.
            Parameters
            ---------
            parfile : str optional
                The parfile name
        """
        if self.model_instance is None:
            model = self.build_model()

        self.model_instance = model()
        self.param_inModel = self.model_instance.params
        self.prefix_names = self.model_instance.prefix_params
        # Find unrecognised parameters in par file.

        if self.param_inparF is not None:
            parName = []
            for p in self.param_inModel:
                parName+= getattr(self.model_instance,p).aliases

            parName += self.param_inModel

            for pp in self.param_inparF.keys():
                if pp not in parName:
                    self.param_unrecognized[pp] = self.param_inparF[pp]

            for ptype in ['prefixParameter', 'maskParameter']:
                prefix_in_model = self.model_instance.get_params_of_type(ptype)
                prefix_param = self.search_prefix_param(self.param_unrecognized.keys(),
                                                        prefix_in_model)
                for key in prefix_param.keys():
                    ppnames = [x for x in prefix_in_model if x.startswith(key)]
                    exm_par = getattr(self.model_instance,ppnames[0])
                    for parname in prefix_param[key]:
                        pre,idstr,idx = split_prefixed_name(parname)
                        if idx == exm_par.index:
                             continue
                        if hasattr(exm_par, 'new_param'):
                            new_par = exm_par.new_param(idx)
                            self.model_instance.add_param(new_par)

        if parfile is not None:
            self.model_instance.read_parfile(parfile)
Example #23
0
    def get_model_instance(self,parfile=None):
        """Read parfile using the model_instance attribute.
            Parameters
            ---------
            parfile : str optional
                The parfile name
        """
        if self.model_instance is None:
            model = self.build_model()

        self.model_instance = model()
        self.param_inModel = self.model_instance.params
        self.prefix_names = self.model_instance.prefix_params
        # Find unrecognised parameters in par file.

        if self.param_inparF is not None:
            parName = []
            for p in self.param_inModel:
                parName+= getattr(self.model_instance,p).aliases

            parName += self.param_inModel

            for pp in self.param_inparF.keys():
                if pp not in parName:
                    self.param_unrecognized[pp] = self.param_inparF[pp]

            for ptype in ['prefixParameter', 'maskParameter']:
                prefix_in_model = self.model_instance.get_params_of_type(ptype)
                prefix_param = self.search_prefix_param(self.param_unrecognized.keys(),
                                                        prefix_in_model)
                for key in prefix_param.keys():
                    ppnames = [x for x in prefix_in_model if x.startswith(key)]
                    exm_par = getattr(self.model_instance,ppnames[0])
                    for parname in prefix_param[key]:
                        pre,idstr,idx = split_prefixed_name(parname)
                        if idx == exm_par.index:
                            continue
                        if hasattr(exm_par, 'new_param'):
                            new_par = exm_par.new_param(idx)
                            self.model_instance.add_param(new_par)

        if parfile is not None:
            self.model_instance.read_parfile(parfile)
Example #24
0
def add_prefixed_param(modelIns,names):
    """Add a prefixed parameter into the timing model.
       Parameter
       ----------
       modelIns : PINT Timing_model class
           The timing model of parameters adding to
       names : string or list of strings
           The name list of prefixed parameters.s
    """
    if type(names) is str:
        names = [names,]
    for n in names:
        prefix,indexformat,indexV = split_prefixed_name(n)
        if prefix in modelIns.prefix_params:
            units = modelIns.prefix_params_units[prefix]
            des = modelIns.prefix_params_description[prefix]

        modelIns.add_param(prefixParameter(name = n,units = units,value = 0.0,
                           description = des))
Example #25
0
    def read_parfile(self, filename):
        """Read values from the specified parfile into the model parameters."""
        checked_param = []
        repeat_param = {}
        pfile = open(filename, 'r')
        for l in [pl.strip() for pl in pfile.readlines()]:
            # Skip blank lines
            if not l:
                continue
            # Skip commented lines
            if l.startswith('#') or l[:2]=="C ":
                continue

            k = l.split()
            name = k[0].upper()

            if name in checked_param:
                if name in repeat_param.keys():
                    repeat_param[name] += 1
                else:
                    repeat_param[name] = 2
                k[0] = k[0] + str(repeat_param[name])
                l = ' '.join(k)

            parsed = False
            for par in self.params:
                if getattr(self, par).from_parfile_line(l):
                    parsed = True
            if not parsed:
                try:
                    prefix,f,v = utils.split_prefixed_name(l.split()[0])
                    if prefix not in ignore_prefix:
                        log.warn("Unrecognized parfile line '%s'" % l)
                except:
                    if l.split()[0] not in ignore_params:
                        log.warn("Unrecognized parfile line '%s'" % l)

            checked_param.append(name)
        # The "setup" functions contain tests for required parameters or
        # combinations of parameters, etc, that can only be done
        # after the entire parfile is read
        self.setup()
Example #26
0
def choose_model(parfile,
                 category_order=None,
                 name=None,
                 check_for_missing_parameters=False):
    """Determine which model components are appropriate for parfile."""
    if name is None:
        if isinstance(parfile, str):
            name = os.path.basename(parfile)
        else:
            name = ""
    if category_order is None:
        category_order = DEFAULT_ORDER

    models_by_category = defaultdict(list)
    for k, c_type in Component.component_types.items():
        models_by_category[c_type.category].append(c_type)

    par_dict = {}
    par_lines = []
    multi_tags = set([
        "JUMP",
        "ECORR",
        "T2EFAC",
        "T2EQUAD",
        "EQUAD",
        "EFAC",
        "DMJUMP",
        "DMEFAC",
        "DMEQUAD",
    ])
    multi_line = Counter()
    for l in interesting_lines(lines_of(parfile), comments=("#", "C ")):
        ll = l.split()
        k = ll[0]
        if k in multi_tags:
            multi_line[k] += 1
            k = k + str(multi_line[k])
        if k in par_dict:
            # FIXME: what happens with JUMPs?
            log.info("Lines with duplicate keys in par file: {} and {}".format(
                [k] + par_dict[k], ll))
        par_dict[k] = ll[1:]
        par_lines.append(l)

    models_to_use = {}
    for category, models in models_by_category.items():
        acceptable = []
        for m_type in models:
            m = m_type()
            if m.is_in_parfile(par_dict):
                acceptable.append(m)
        if len(acceptable) > 1:
            raise ValueError(
                "Multiple models are compatible with this par file: {}".format(
                    acceptable))
        if acceptable:
            models_to_use[category] = acceptable[0]

    if "BINARY" in par_dict:
        vals = par_dict["BINARY"]
        if len(vals) != 1:
            raise ValueError("Mal-formed binary model selection: {}".format(
                repr(" ".join(["BINARY"] + vals))))
        (bm, ) = vals
        if "pulsar_system" not in models_to_use:
            # Either we're missing parameters or the model is bogus
            # FIXME: distinguish
            raise UnknownBinaryModel(
                "Unknown binary model requested in par file: {}".format(bm))
        # FIXME: consistency check - the componens actually chosen should know the name bm

    models_in_order = []
    for category in category_order:
        try:
            models_in_order.append(models_to_use.pop(category))
        except KeyError:
            pass
    models_in_order.extend(v for k, v in sorted(models_to_use.items()))
    tm = TimingModel(name, models_in_order)

    # FIXME: this should go in TimingModel for when you try to
    # add conflicting components
    alias_map = {}
    for prefix_type in ["prefixParameter", "maskParameter"]:
        for pn in tm.get_params_of_type_top(prefix_type):
            par = getattr(tm, pn)
            for a in [par.prefix] + par.prefix_aliases:
                if a in alias_map:
                    raise ValueError(
                        "Two prefix/mask parameters have the same "
                        "alias {}: {} and {}".format(a, alias_map[a], par))
                alias_map[a] = par

    leftover_params = par_dict.copy()
    for k in tm.get_params_mapping():
        leftover_params.pop(k, None)
        for a in getattr(tm, k).aliases:
            leftover_params.pop(a, None)

    for p in leftover_params:
        try:
            pre, idxstr, idxV = split_prefixed_name(p)
            try:
                par = alias_map[pre]
            except KeyError:
                if pre in ignore_prefix:
                    # log.warning("Ignoring unhandled prefix {}".format(pre))
                    continue
                else:
                    raise ValueError(
                        "Mystery parameter {}, prefix {} with number {}".
                        format(p, pre, idxV))
            component = tm.get_params_mapping()[par.name]
            new_parameter = par.new_param(idxV)
            if hasattr(tm, new_parameter.name):
                raise ValueError("Received duplicate parameter {}".format(
                    new_parameter.name))
            tm.add_param_from_top(new_parameter, component)
            # print("added", new_parameter)
        except PrefixError:
            pass

    return tm
Example #27
0
    def build_model(self, parfile=None, name=""):
        """Read parfile using the model_instance attribute. Throws error if
           mismatched coordinate systems detected.
        Parameters
        ---------
        name: str, optional
            The name for the timing model
        parfile : str optional
            The parfile name
        """
        if parfile is not None:
            self.get_comp_from_parfile(parfile)
            # ensure coordinate systems match for POS and PM
            if "RAJ" in self.preprocess_parfile(parfile).keys():
                if "PMELONG" in self.preprocess_parfile(parfile):
                    raise AttributeError(
                        "Cannot have Ecliptic proper motion parameters (PMELONG/PMELAT) with Equatorial position parameters (RAJ/DECJ) in par file."
                    )
                elif "PMELAT" in self.preprocess_parfile(parfile):
                    raise AttributeError(
                        "Cannot have Ecliptic proper motion parameters (PMELONG/PMELAT) with Equatorial position parameters (RAJ/DECJ) in par file."
                    )
            elif "ELONG" in self.preprocess_parfile(parfile).keys():
                if "PMRA" in self.preprocess_parfile(parfile):
                    raise AttributeError(
                        "Cannot have Equatorial proper motion parameters (PMRA/PMDEC) with Ecliptic position parameters (ELONG/ELAT) in par file."
                    )
                elif "PMDEC" in self.preprocess_parfile(parfile):
                    raise AttributeError(
                        "Cannot have Equatorial proper motion parameters (PMRA/PMDEC) with Ecliptic position parameters (ELONG/ELAT) in par file."
                    )
        sorted_comps = self.sort_components()
        self.timing_model = TimingModel(name, sorted_comps)
        param_inModel = self.timing_model.get_params_mapping()
        # Find unrecognised parameters in par file.

        if self.param_inparF is not None:
            parName = []
            # add aliases
            for p in list(param_inModel.keys()):
                parName += getattr(self.timing_model, p).aliases

            parName += param_inModel.keys()

            for pp in self.param_inparF.keys():
                if pp not in parName:
                    self.param_unrecognized[pp] = self.param_inparF[pp]

            for ptype in ["prefixParameter", "maskParameter"]:
                prefix_param = self.search_prefix_param(
                    self.param_unrecognized, self.timing_model, ptype)
                prefix_in_model = self.timing_model.get_params_of_type_top(
                    ptype)
                for key in prefix_param:
                    ppnames = [x for x in prefix_in_model if x.startswith(key)]
                    for ppn in ppnames:
                        pfx, idxs, idxv = split_prefixed_name(ppn)
                        if pfx == key:
                            exm_par = getattr(self.timing_model, ppn)
                        else:
                            continue
                    exm_par_comp = param_inModel[exm_par.name]
                    for parname in prefix_param[key]:
                        pre, idstr, idx = split_prefixed_name(parname)
                        if idx == exm_par.index:
                            continue
                        if hasattr(exm_par, "new_param"):
                            new_par = exm_par.new_param(idx)
                            self.timing_model.add_param_from_top(
                                new_par, exm_par_comp)
            if "BINARY" in self.param_inparF:
                vals = self.param_inparF["BINARY"]
                if len(vals) != 1:
                    raise ValueError(
                        "Mal-formed binary model selection: {}".format(
                            repr(" ".join(["BINARY"] + vals))))
                (bm, ) = vals
                cats = self.timing_model.get_components_by_category()
                if "pulsar_system" not in cats:
                    raise UnknownBinaryModel(
                        "Unknown binary model requested in par file: {}".
                        format(bm))
                # FIXME: consistency check - the componens actually chosen should know the name bm
        for p in self.timing_model.params:
            if isinstance(self.timing_model[p], maskParameter):
                # maskParameters need a bogus alias for parfile parsing
                # remove this bogus alias
                try:
                    ix = self.timing_model[p].aliases.index(
                        self.timing_model[p].prefix)
                except ValueError:
                    pass
                else:
                    del self.timing_model[p].aliases[ix]
        if parfile is not None:
            self.timing_model.read_parfile(parfile)
Example #28
0
    def read_parfile(self, file):
        """Read values from the specified parfile into the model parameters.

        Parameters
        ----------
        file : str or list or file-like
            The parfile to read from. May be specified as a filename,
            a list of lines, or a readable file-like object.

        """
        repeat_param = defaultdict(int)
        param_map = self.get_params_mapping()
        comps = self.components.copy()
        comps['timing_model'] = self
        wants_tcb = None
        stray_lines = []
        for li in interesting_lines(lines_of(file), comments=("#", "C ")):
            k = li.split()
            name = k[0].upper()

            if name == 'UNITS':
                if name in repeat_param:
                    raise ValueError("UNITS is repeated in par file")
                else:
                    repeat_param[name] += 1
                if len(k) > 1 and k[1] == 'TDB':
                    wants_tcb = False
                else:
                    wants_tcb = li
                continue

            if name == 'EPHVER':
                if len(k) > 1 and k[1] != '2' and wants_tcb is None:
                    wants_tcb = li
                log.warning("EPHVER %s does nothing in PINT" % k[1])
                #actually people expect EPHVER 5 to work
                #even though it's supposed to imply TCB which doesn't
                continue

            repeat_param[name] += 1
            if repeat_param[name] > 1:
                k[0] = k[0] + str(repeat_param[name])
                li = ' '.join(k)

            used = []
            for p, c in param_map.items():
                if getattr(comps[c], p).from_parfile_line(li):
                    used.append((c, p))
            if len(used) > 1:
                log.warning("More than one component made use of par file "
                            "line {!r}: {}".format(li, used))
            if used:
                continue

            if name in ignore_params:
                log.debug("Ignoring parfile line '%s'" % (li, ))
                continue

            try:
                prefix, f, v = utils.split_prefixed_name(name)
                if prefix in ignore_prefix:
                    log.debug("Ignoring prefix parfile line '%s'" % (li, ))
                    continue
            except utils.PrefixError:
                pass

            stray_lines.append(li)

        if wants_tcb:
            raise ValueError(
                "Only UNITS TDB supported by PINT but parfile has {}".format(
                    wants_tcb))
        if stray_lines:
            for l in stray_lines:
                log.warning("Unrecognized parfile line {!r}".format(l))
            for name, param in getattr(self, "discarded_components", []):
                log.warning("Model component {} was rejected because we "
                            "didn't find parameter {}".format(name, param))
            log.warning("Final object: {}".format(self))

        # The "setup" functions contain tests for required parameters or
        # combinations of parameters, etc, that can only be done
        # after the entire parfile is read
        self.setup()
Example #29
0
    def _pintify_parfile(self, parfile, allow_name_mixing=False):
        """Translate parfile parameter name to PINT style name.

        This function converts the parfile information to PINT understandable
        parameter name. It also returns the PINT unrecognized parameters and
        check if the parfile has illegal repeating lines.

        Parameters
        ----------
        parfile : str, file-like object, or parfile dictionary
            Parfile name, parfile StringIO, or the parfile dictionary returned
            by :func:`parse_parfile`.

        allow_name_mixing : bool, optional
            Flag for allowing the input to have mixing aliases names for the
            same parameter. For example, if this flag is true, one can have
            T2EFAC and EFAC, both of them maps to PINT parameter EFAC, present
            in the parfile at the same time.

        Returns
        -------
            pint_param_dict : dict
                Pintified parameter dictionary with the PINT name as key and list of
                parameter value-uncertainty lines as value. For the
                repeating parameters in the parfile, the value will contain
                mulitple lines.

            original_name_map : dict
                PINT name maps to the original .par file input names. PINT name
                is the key and the original name is in the value.

            unknown_param : dict
                The PINT unrecognized parameters in the format of a dictionary.
                The key is the unknown parameter name and the value is the
                parfile value lines.

        Raises
        ------
        TimingModelError
            If the parfile has mulitple line with non-repeating parameters.
        """
        pint_param_dict = defaultdict(list)
        original_name_map = defaultdict(list)
        unknown_param = defaultdict(list)
        repeating = Counter()
        if isinstance(parfile, (str, StringIO)):
            parfile_dict = parse_parfile(parfile)
        else:
            parfile_dict = parfile
        for k, v in parfile_dict.items():
            try:
                pint_name, init0 = self.all_components.alias_to_pint_param(k)
            except UnknownParameter:
                if k in ignore_params:  # Parameter is known but in the ingore list
                    continue
                else:  # Check ignored prefix
                    try:
                        pfx, idxs, idx = split_prefixed_name(k)
                        if pfx in ignore_prefix:  # It is an ignored prefix.
                            continue
                        else:
                            unknown_param[k] += v
                    except PrefixError:
                        unknown_param[k] += v
                continue
            pint_param_dict[pint_name] += v
            original_name_map[pint_name].append(k)
            repeating[pint_name] += len(v)
            # Check if this parameter is allowed to be repeated by PINT
            if len(pint_param_dict[pint_name]) > 1:
                if pint_name not in self.all_components.repeatable_param:
                    raise TimingModelError(
                        f"Parameter {pint_name} is not a repeatable parameter. "
                        f"However, mulitple line use it.")
        # Check if the name is mixed
        for p_n, o_n in original_name_map.items():
            if len(o_n) > 1:
                if not allow_name_mixing:
                    raise TimingModelError(
                        f"Parameter {p_n} have mixed input names/alias "
                        f"{o_n}. If you want to have mixing names, please use"
                        f" 'allow_name_mixing=True', and the output .par file "
                        f"will use '{original_name_map[pint_name][0]}'.")
            original_name_map[p_n] = o_n[0]

        return pint_param_dict, original_name_map, unknown_param
Example #30
0
    def build_model(self, parfile=None, name=""):
        """Read parfile using the model_instance attribute.
        Parameters
        ---------
        name: str, optional
            The name for the timing model
        parfile : str optional
            The parfile name
        """
        if parfile is not None:
            self.get_comp_from_parfile(parfile)
        sorted_comps = self.sort_components()
        self.timing_model = TimingModel(name, sorted_comps)
        param_inModel = self.timing_model.get_params_mapping()
        # Find unrecognised parameters in par file.

        if self.param_inparF is not None:
            parName = []
            # add aliases
            for p in list(param_inModel.keys()):
                parName += getattr(self.timing_model, p).aliases

            parName += param_inModel.keys()

            for pp in self.param_inparF.keys():
                if pp not in parName:
                    self.param_unrecognized[pp] = self.param_inparF[pp]

            for ptype in ["prefixParameter", "maskParameter"]:
                prefix_param = self.search_prefix_param(
                    self.param_unrecognized, self.timing_model, ptype)
                prefix_in_model = self.timing_model.get_params_of_type(ptype)
                for key in prefix_param:
                    ppnames = [x for x in prefix_in_model if x.startswith(key)]
                    for ppn in ppnames:
                        pfx, idxs, idxv = split_prefixed_name(ppn)
                        if pfx == key:
                            exm_par = getattr(self.timing_model, ppn)
                        else:
                            continue
                    exm_par_comp = param_inModel[exm_par.name]
                    for parname in prefix_param[key]:
                        pre, idstr, idx = split_prefixed_name(parname)
                        if idx == exm_par.index:
                            continue
                        if hasattr(exm_par, "new_param"):
                            new_par = exm_par.new_param(idx)
                            self.timing_model.add_param_from_top(
                                new_par, exm_par_comp)
            if "BINARY" in self.param_inparF:
                vals = self.param_inparF["BINARY"]
                if len(vals) != 1:
                    raise ValueError(
                        "Mal-formed binary model selection: {}".format(
                            repr(" ".join(["BINARY"] + vals))))
                (bm, ) = vals
                cats = self.timing_model.get_component_of_category()
                if "pulsar_system" not in cats:
                    raise UnknownBinaryModel(
                        "Unknown binary model requested in par file: {}".
                        format(bm))
                # FIXME: consistency check - the componens actually chosen should know the name bm

        if parfile is not None:
            self.timing_model.read_parfile(parfile)
Example #31
0
    def read_parfile(self, filename):
        """Read values from the specified parfile into the model parameters."""
        checked_param = []
        repeat_param = {}
        param_map = self.get_params_mapping()
        comps = self.components
        pfile = open(filename, 'r')
        wants_tcb = None
        for l in [pl.strip() for pl in pfile.readlines()]:
            # Skip blank lines
            if not l:
                continue
            # Skip commented lines
            if l.startswith('#') or l[:2] == "C ":
                continue

            k = l.split()
            name = k[0].upper()

            if name == 'UNITS':
                if len(k) > 1 and k[1] == 'TDB':
                    wants_tcb = False
                else:
                    wants_tcb = k[1]

            if name == 'EPHVER':
                if len(k) > 1 and k[1] != '2' and wants_tcb is None:
                    wants_tcb = l
                log.warning("EPHVER %s does nothing in PINT" % k[1])
                #actually people expect EPHVER 5 to work
                #even though it's supposed to imply TCB which doesn't

            if name in checked_param:
                if name in repeat_param.keys():
                    repeat_param[name] += 1
                else:
                    repeat_param[name] = 2
                k[0] = k[0] + str(repeat_param[name])
                l = ' '.join(k)
            parsed = False
            for par in param_map.keys():
                host_comp = param_map[par]
                if host_comp != 'timing_model':
                    cmp = comps[host_comp]
                else:
                    cmp = self
                if cmp.__getattr__(par).from_parfile_line(l):
                    parsed = True

            if not parsed:
                p = l.split()[0]
                if p in ignore_params:
                    log.debug("Ignoring parfile line '%s'" % (l, ))
                    parsed = True
            if not parsed:
                p = l.split()[0]
                try:
                    prefix, f, v = utils.split_prefixed_name(l.split()[0])
                    if prefix in ignore_prefix:
                        log.debug("Ignoring prefix parfile line '%s'" % (l, ))
                        parsed = True
                except utils.PrefixError:
                    pass
            if not parsed:
                log.warning("Unrecognized parfile line '%s'" % (l, ))

            checked_param.append(name)
        if wants_tcb:
            raise ValueError("UNITS %s not yet supported by PINT" % k[1])
        # The "setup" functions contain tests for required parameters or
        # combinations of parameters, etc, that can only be done
        # after the entire parfile is read
        self.setup()
Example #32
0
    def _setup_model(
        self,
        timing_model,
        pint_param_dict,
        original_name=None,
        setup=True,
        validate=True,
    ):
        """Fill up a timing model with parameter values and then setup the model.

        This function fills up the timing model parameter values from the input
        pintified parameter dictionary. If the parameter has not initialized yet,
        it will add the parameter to the timing model. For the repeatable parameters,
        it will search matching key value pair first. If the input parameter line's
        key-value matches the existing parameter, the parameter value and uncertainty
        will copy to the existing parameter. If there is no match, it will find an
        empty existing parameter, whose `key` is `None`, and fill it up. If no empyt
        parameter left, it will add a new parameter to it.

        Parameters
        ----------
        timing_model : pint.models.TimingModel
            Timing model to get setup.
        pint_param_dict: dict
            Pintified parfile dictionary which can be aquired by
            :meth:`ModelBuilder._pintify_parfile`
        origin_name : dict, optional
            A map from PINT name to the original input name.
        setup : bool, optional
            Whether to run the setup function in the timing model.
        validate : bool, optional
            Whether to run the validate funciotn in the timing model.
        """
        if original_name is not None:
            use_alias = True
        else:
            use_alias = False

        for pp, v in pint_param_dict.items():
            try:
                par = getattr(timing_model, pp)
            except AttributeError:
                # since the input is pintfied, it should be an uninitized indexed parameter
                # double check if the missing parameter an indexed parameter.
                pint_par, first_init = self.all_components.alias_to_pint_param(
                    pp)
                try:
                    prefix, _, index = split_prefixed_name(pint_par)
                except PrefixError:
                    par_hosts = self.all_components.param_component_map[
                        pint_par]
                    currnt_cp = timing_model.components.keys()
                    raise TimingModelError(
                        f"Parameter {pint_par} is recognized"
                        f" by PINT, but not used in the current"
                        f" timing model. It is used in {par_hosts},"
                        f" but the current timing model uses {currnt_cp}.")
                # TODO need to create a beeter API for _loacte_param_host
                host_component = timing_model._locate_param_host(first_init)
                timing_model.add_param_from_top(
                    getattr(timing_model, first_init).new_param(index),
                    host_component[0][0],
                )
                par = getattr(timing_model, pint_par)

            # Fill up the values
            param_line = len(v)
            if param_line < 2:
                if use_alias:  # Use the input alias as input
                    name = original_name[pp]
                else:
                    name = pp
                par.from_parfile_line(" ".join([name] + v))
            else:  # For the repeatable parameters
                lines = copy.deepcopy(v)  # Line queue.
                # Check how many repeatable parameters in the model.
                example_par = getattr(timing_model, pp)
                prefix, _, index = split_prefixed_name(pp)
                for li in lines:
                    # Creat a temp parameter with the idx bigger than all the existing indices
                    repeatable_map = timing_model.get_prefix_mapping(prefix)
                    new_max_idx = max(repeatable_map.keys()) + 1
                    temp_par = example_par.new_param(new_max_idx)
                    temp_par.from_parfile_line(" ".join(
                        [prefix + str(new_max_idx), li]))
                    if use_alias:  # Use the input alias as input
                        temp_par.use_alias = original_name[pp]
                    # Check current repeatable's key and value
                    # TODO need to change here when maskParameter name changes to name_key_value
                    empty_repeat_param = []
                    for idx, rp in repeatable_map.items():
                        rp_par = getattr(timing_model, rp)
                        if rp_par.compare_key_value(temp_par):
                            # Key and key value match, copy the new line to it
                            # and exit
                            rp_par.from_parfile_line(" ".join([rp, li]))
                            if use_alias:  # Use the input alias as input
                                rp_par.use_alias = original_name[pp]
                            break

                        if rp_par.key is None:
                            # Empty space for new repeatable parameter
                            empty_repeat_param.append(rp_par)

                    # There is no current repeatable parameter matching the new line
                    # First try to fill up an empty space.
                    if empty_repeat_param != []:
                        emt_par = empty_repeat_param.pop(0)
                        emt_par.from_parfile_line(" ".join([emt_par.name, li]))
                        if use_alias:  # Use the input alias as input
                            emt_par.use_alias = original_name[pp]
                    else:
                        # No empty space, add a new parameter to the timing model.
                        host_component = timing_model._locate_param_host(pp)
                        timing_model.add_param_from_top(
                            temp_par, host_component[0][0])

        if setup:
            timing_model.setup()
        if validate:
            timing_model.validate()
        return timing_model