Skip to content

Commit

Permalink
Merge branch 'nanograv:master' into fasterastrom
Browse files Browse the repository at this point in the history
  • Loading branch information
dlakaplan authored Oct 17, 2023
2 parents deb3ec4 + 0201737 commit 4922800
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ the released changes.
- `ssb_to_psb_ICRS` implementation is now a lot faster (uses erfa functions directly)
- `ssb_to_psb_ECL` implementation within `AstrometryEcliptic` model is now a lot faster (uses erfa functions directly)
- Upgraded versioneer for compatibility with Python 3.12
- Creation of `Fitter` objects will fail if there are free unfittable parameters in the timing model.
- Only fittable parameters will be listed as check boxes in the `plk` interface.
### Added
- CHI2, CHI2R, TRES, DMRES now in postfit par files
- Added `WaveX` model as a `DelayComponent` with Fourier amplitudes as fitted parameters
Expand All @@ -24,6 +26,7 @@ the released changes.
- Support for wideband data in `pint.bayesian` (no correlated noise).
- Added `DMWaveX` model (Fourier representation of DM noise)
- Piecewise orbital model (`BinaryBTPiecewise`)
- `TimingModel.fittable_params` property
- Simulate correlated noise using `pint.simulation` (also available via the `zima` script)
### Fixed
- Wave model `validate()` can correctly use PEPOCH to assign WAVEEPOCH parameter
Expand All @@ -33,4 +36,5 @@ the released changes.
- Fixed an incorrect docstring in `pbprime()` functions.
- Fix ICRS -> ECL conversion when parameter uncertainties are not set.
- `get_TOAs` raises an exception upon finding mixed narrowband and wideband TOAs in a tim file. `TOAs.is_wideband` returns True only if *ALL* TOAs have the -pp_dm flag.
- `TimingModel.designmatrix()` method will fail with an informative error message if there are free unfittable parameters in the timing model.
### Removed
10 changes: 10 additions & 0 deletions src/pint/fitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ class Fitter:
"""

def __init__(self, toas, model, track_mode=None, residuals=None):
if not set(model.free_params).issubset(model.fittable_params):
free_unfittable_params = set(model.free_params).difference(
model.fittable_params
)
raise ValueError(
f"Cannot create fitter because the following unfittable parameters "
f"were found unfrozen in the model: {free_unfittable_params}. "
f"Freeze these parameters before creating the fitter."
)

self.toas = toas
self.model_init = model
self.track_mode = track_mode
Expand Down
8 changes: 5 additions & 3 deletions src/pint/models/binary_ell1.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,11 @@ def __init__(self):
self.binary_model_name = "ELL1k"
self.binary_model_class = ELL1kmodel

self.remove_param("OMDOT")
self.remove_param("EDOT")
self.remove_param("EPS1DOT")
self.remove_param("EPS2DOT")

self.add_param(
floatParameter(
name="OMDOT",
Expand All @@ -451,9 +456,6 @@ def __init__(self):
)
)

self.remove_param("EPS1DOT")
self.remove_param("EPS2DOT")

def validate(self):
"""Validate parameters."""
super().validate()
Expand Down
57 changes: 48 additions & 9 deletions src/pint/models/timing_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
Parameter,
boolParameter,
floatParameter,
funcParameter,
intParameter,
maskParameter,
strParameter,
Expand Down Expand Up @@ -592,7 +593,8 @@ def params(self):

@property_exists
def free_params(self):
"""List of all the free parameters in the timing model. Can be set to change which are free.
"""List of all the free parameters in the timing model.
Can be set to change which are free.
These are ordered as ``self.params`` does.
Expand All @@ -615,6 +617,17 @@ def free_params(self, params):
f"Parameter(s) are familiar but not in the model: {params}"
)

@property_exists
def fittable_params(self):
"""List of parameters that are fittable, i.e., the parameters
which have a derivative implemented. These derivatives are usually
accessed via the `d_delay_d_param` and `d_phase_d_param` methods."""
return [
p
for p in self.params
if (p in self.phase_deriv_funcs or p in self.delay_deriv_funcs)
]

def match_param_aliases(self, alias):
"""Return PINT parameter name corresponding to this alias.
Expand Down Expand Up @@ -1965,16 +1978,38 @@ def designmatrix(self, toas, acc_delay=None, incfrozen=False, incoffset=True):
units : astropy.units.Unit
The units of the corresponding parts of the design matrix
Note
----
Here we have negative sign here. Since in pulsar timing
the residuals are calculated as (Phase - int(Phase)), which is different
from the conventional definition of least square definition (Data - model)
We decide to add minus sign here in the design matrix, so the fitter
keeps the conventional way.
Notes
-----
1. We have negative sign here. Since the residuals are calculated as
(Phase - int(Phase)) in pulsar timing, which is different from the conventional
definition of least square definition (Data - model), we have decided to add
a minus sign here in the design matrix so that the fitter keeps the conventional
sign.
2. Design matrix entries can be computed only for parameters for which the
derivatives are implemented. If a parameter without a derivative is unfrozen
while calling this method, it will raise an informative error, except in the
case of unfrozen noise parameters, which are simply ignored.
"""

noise_params = self.get_params_of_component_type("NoiseComponent")

if (
not set(self.free_params)
.difference(noise_params)
.issubset(self.fittable_params)
):
free_unfittable_params = (
set(self.free_params)
.difference(noise_params)
.difference(self.fittable_params)
)
raise ValueError(
f"Cannot compute the design matrix because the following unfittable parameters "
f"were found unfrozen in the model: {free_unfittable_params}. "
f"Freeze these parameters before computing the design matrix."
)

# unfrozen_noise_params = [
# param for param in noise_params if not getattr(self, param).frozen
# ]
Expand Down Expand Up @@ -2918,7 +2953,11 @@ def __init__(self):
def __repr__(self):
return "{}(\n {})".format(
self.__class__.__name__,
",\n ".join(str(getattr(self, p)) for p in self.params),
",\n ".join(
str(getattr(self, p))
for p in self.params
if not isinstance(p, funcParameter)
),
)

def setup(self):
Expand Down
1 change: 1 addition & 0 deletions src/pint/pintk/plk.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ def addFitCheckBoxes(self, model):
for p in model.components[comp].params
if p not in pulsar.nofitboxpars
and getattr(model, p).quantity is not None
and p in model.fittable_params
]

# Don't bother showing components without any fittable parameters
Expand Down

0 comments on commit 4922800

Please sign in to comment.