Skip to content

Commit

Permalink
Merge pull request #1617 from abhisrkckl/param-order
Browse files Browse the repository at this point in the history
Make `TimingModel.params` and `TimingModel.ordered_params` identical.
  • Loading branch information
dlakaplan authored Aug 17, 2023
2 parents 458fd07 + 18f4604 commit c6b2c82
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ the released changes.
- Third-order Roemer delay terms to ELL1 model
- Made the addition of a TZR TOA (`AbsPhase`) in the `TimingModel` explicit in `Residuals` class.
- Updated `CONTRIBUTING.rst` with the latest information.
- Made `TimingModel.params` and `TimingModel.ordered_params` identical. Deprecated `TimingModel.ordered_params`.
### Added
- Third-order Roemer delay terms to ELL1 model
- Options to add a TZR TOA (`AbsPhase`) during the creation of a `TimingModel` using `ModelBuilder.__call__`, `get_model`, and `get_model_and_toas`
Expand Down
4 changes: 2 additions & 2 deletions src/pint/fitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def get_summary(self, nodmx=False):

# to handle all parameter names, determine the longest length for the first column
longestName = 0 # optionally specify the minimum length here instead of 0
for pn in self.model.params_ordered:
for pn in self.model.params:
if nodmx and pn.startswith("DMX"):
continue
if len(pn) > longestName:
Expand All @@ -378,7 +378,7 @@ def get_summary(self, nodmx=False):
s += ("{:<" + spacingName + "s} {:>20s} {:>28s} {}\n").format(
"=" * longestName, "=" * 20, "=" * 28, "=" * 5
)
for pn in self.model.params_ordered:
for pn in self.model.params:
if nodmx and pn.startswith("DMX"):
continue
prefitpar = getattr(self.model_init, pn)
Expand Down
58 changes: 32 additions & 26 deletions src/pint/models/timing_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,11 @@ class TimingModel:
removed with methods on this object, and for many of them additional
parameters in families (``DMXEP_1234``) can be added.
Parameters in a TimingModel object are listed in the ``model.params`` and
``model.params_ordered`` objects. Each Parameter can be set as free or
frozen using its ``.frozen`` attribute, and a list of the free parameters
is available through the ``model.free_params`` property; this can also
be used to set which parameters are free. Several methods are available
to get and set some or all parameters in the forms of dictionaries.
Parameters in a TimingModel object are listed in the ``model.params`` object.
Each Parameter can be set as free or frozen using its ``.frozen`` attribute,
and a list of the free parameters is available through the ``model.free_params``
property; this can also be used to set which parameters are free. Several methods
are available to get and set some or all parameters in the forms of dictionaries.
TimingModel objects also support a number of functions for computing
various things like orbital phase, and barycentric versions of TOAs,
Expand Down Expand Up @@ -500,20 +499,30 @@ def __getattr__(self, name):
)

@property_exists
def params(self):
"""List of all parameter names in this model and all its components (order is arbitrary)."""
# FIXME: any reason not to just use params_ordered here?
p = self.top_level_params
for cp in self.components.values():
p = p + cp.params
return p
def params_ordered(self):
"""List of all parameter names in this model and all its components.
This is the same as `params`."""

# Historically, this was different from `params` because Python
# dictionaries were unordered until Python 3.7. Now there is no reason for
# them to be different.

warn(
"`TimingModel.params_ordered` is now deprecated and may be removed in the future. "
"Use `TimingModel.params` instead. It gives the same output as `TimingModel.params_ordered`.",
DeprecationWarning,
)

return self.params

@property_exists
def params_ordered(self):
def params(self):
"""List of all parameter names in this model and all its components, in a sensible order."""

# Define the order of components in the list
# Any not included will be printed between the first and last set.
# FIXME: make order completely canonical (sort components by name?)

start_order = ["astrometry", "spindown", "dispersion"]
last_order = ["jump_delay"]
compdict = self.get_components_by_category()
Expand Down Expand Up @@ -551,15 +560,15 @@ def params_ordered(self):
def free_params(self):
"""List of all the free parameters in the timing model. Can be set to change which are free.
These are ordered as ``self.params_ordered`` does.
These are ordered as ``self.params`` does.
Upon setting, order does not matter, and aliases are accepted.
ValueError is raised if a parameter is not recognized.
On setting, parameter aliases are converted with
:func:`pint.models.timing_model.TimingModel.match_param_aliases`.
"""
return [p for p in self.params_ordered if not getattr(self, p).frozen]
return [p for p in self.params if not getattr(self, p).frozen]

@free_params.setter
def free_params(self, params):
Expand Down Expand Up @@ -620,7 +629,7 @@ def get_params_dict(self, which="free", kind="quantity"):
if which == "free":
ps = self.free_params
elif which == "all":
ps = self.params_ordered
ps = self.params
else:
raise ValueError("get_params_dict expects which to be 'all' or 'free'")
c = OrderedDict()
Expand Down Expand Up @@ -2013,10 +2022,7 @@ def compare(
log.debug("Check verbosity - only warnings/info will be displayed")
othermodel = copy.deepcopy(othermodel)

if (
"POSEPOCH" in self.params_ordered
and "POSEPOCH" in othermodel.params_ordered
):
if "POSEPOCH" in self.params and "POSEPOCH" in othermodel.params:
if (
self.POSEPOCH.value is not None
and othermodel.POSEPOCH.value is not None
Expand All @@ -2027,7 +2033,7 @@ def compare(
% (other_model_name, model_name)
)
othermodel.change_posepoch(self.POSEPOCH.value)
if "PEPOCH" in self.params_ordered and "PEPOCH" in othermodel.params_ordered:
if "PEPOCH" in self.params and "PEPOCH" in othermodel.params:
if (
self.PEPOCH.value is not None
and self.PEPOCH.value != othermodel.PEPOCH.value
Expand All @@ -2036,7 +2042,7 @@ def compare(
"Updating PEPOCH in %s to match %s" % (other_model_name, model_name)
)
othermodel.change_pepoch(self.PEPOCH.value)
if "DMEPOCH" in self.params_ordered and "DMEPOCH" in othermodel.params_ordered:
if "DMEPOCH" in self.params and "DMEPOCH" in othermodel.params:
if (
self.DMEPOCH.value is not None
and self.DMEPOCH.value != othermodel.DMEPOCH.value
Expand Down Expand Up @@ -2071,7 +2077,7 @@ def compare(
f"{model_name} is in ECL({self.ECL.value}) coordinates but {other_model_name} is in ICRS coordinates and convertcoordinates=False"
)

for pn in self.params_ordered:
for pn in self.params:
par = getattr(self, pn)
if par.value is None:
continue
Expand Down Expand Up @@ -2298,8 +2304,8 @@ def compare(
)

# Now print any parameters in othermodel that were missing in self.
mypn = self.params_ordered
for opn in othermodel.params_ordered:
mypn = self.params
for opn in othermodel.params:
if opn in mypn and getattr(self, opn).value is not None:
continue
if nodmx and opn.startswith("DMX"):
Expand Down
5 changes: 5 additions & 0 deletions tests/test_design_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,8 @@ def test_combine_designmatrix_all(self):
]
== 0.0
)

def test_param_order(self):
params_dm = self.model.designmatrix(self.toas, incoffset=False)[1]
params_free = self.model.free_params
assert params_dm == params_free

0 comments on commit c6b2c82

Please sign in to comment.