Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plot wideband DMs and DM residuals in pintk #1534

Merged
merged 17 commits into from
Nov 17, 2023
1 change: 1 addition & 0 deletions CHANGELOG-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ the released changes.
- `ScaleToaError.d_toasigma_d_EFAC` and `ScaleToaError.d_toasigma_d_EQUAD` methods.
- Separate `.fullname` for all observatories
- `Residuals.calc_whitened_resids()` method
- Plot wideband DM measurements, wideband DM residuals, and wideband DM errors in `pintk`. (Disabled for narrowband data.)
- Optionally generate multi-frequency TOAs in an epoch using `make_fake_toas_uniform` and `make_fake_toas_fromMJDs`
- Documentation: Example notebook for simulations
### Fixed
Expand Down
57 changes: 52 additions & 5 deletions src/pint/pintk/plk.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from astropy.time import Time
import astropy.units as u
import matplotlib as mpl
from matplotlib import figure
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

Expand All @@ -23,6 +23,8 @@
import pint.logging
from loguru import logger as log

from pint.residuals import WidebandDMResiduals


try:
from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk
Expand Down Expand Up @@ -50,6 +52,9 @@
"frequency": r"Observing Frequency (MHz)",
"TOA error": r"TOA uncertainty ($\mu$s)",
"rounded MJD": r"MJD",
"WB DM": "Wideband DM (pc/cm3)",
"WB DM res": "Wideband DM residual (pc/cm3)",
"WB DM err": "Wideband DM error (pc/cm3)",
"elongation": r"Solar Elongation (deg)",
}

Expand Down Expand Up @@ -475,6 +480,9 @@
self.xvar = tk.StringVar()
self.yvar = tk.StringVar()

# This will be set in PlkWidget.setPulsar and PlkWidget.update methods.
self.wideband = False

Check warning on line 484 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L484

Added line #L484 was not covered by tests

self.initPlkXYChoice()

def initPlkXYChoice(self):
Expand Down Expand Up @@ -531,7 +539,7 @@
else self.master.psr.prefit_model
)
if choice == "elongation" and not any(
isinstance(x, Astrometry) for x in model.components
isinstance(x, Astrometry) for x in model.components.values()
):
self.xbuttons[ii].configure(state="disabled")
self.ybuttons[ii].configure(state="disabled")
Expand All @@ -544,6 +552,12 @@
):
self.xbuttons[ii].configure(state="disabled")
self.ybuttons[ii].configure(state="disabled")
if (
choice in ["WB DM", "WB DM res", "WB DM err"]
and not self.master.psr.all_toas.is_wideband()
):
self.xbuttons[ii].configure(state="disabled")
self.ybuttons[ii].configure(state="disabled")

Check warning on line 560 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L559-L560

Added lines #L559 - L560 were not covered by tests

def setCallbacks(self, updatePlot):
"""
Expand Down Expand Up @@ -718,7 +732,7 @@
self.colorModeWidget = PlkColorModeBoxes(master=self)

self.plkDpi = 100
self.plkFig = mpl.figure.Figure(dpi=self.plkDpi)
self.plkFig = plt.Figure(dpi=self.plkDpi)

Check warning on line 735 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L735

Added line #L735 was not covered by tests
self.plkCanvas = FigureCanvasTkAgg(self.plkFig, self)
self.plkCanvas.mpl_connect("button_press_event", self.canvasClickEvent)
self.plkCanvas.mpl_connect("button_release_event", self.canvasReleaseEvent)
Expand Down Expand Up @@ -773,6 +787,7 @@
self.randomboxWidget.addRandomCheckbox(self)
self.colorModeWidget.addColorModeCheckbox(self.color_modes)
self.fitterWidget.updateFitterChoices(self.psr.all_toas.wideband)
self.xyChoiceWidget.wideband = self.psr.all_toas.wideband

Check warning on line 790 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L790

Added line #L790 was not covered by tests
self.xyChoiceWidget.setChoice()
self.updatePlot(keepAxes=True)
self.plkToolbar.update()
Expand All @@ -797,6 +812,7 @@

self.fitboxesWidget.setCallbacks(self.fitboxChecked)
self.colorModeWidget.setCallbacks(self.updateGraphColors)
self.xyChoiceWidget.wideband = self.psr.all_toas.wideband

Check warning on line 815 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L815

Added line #L815 was not covered by tests
self.xyChoiceWidget.setCallbacks(self.updatePlot)
self.actionsWidget.setCallbacks(
self.fit, self.reset, self.writePar, self.writeTim, self.revert
Expand Down Expand Up @@ -919,7 +935,7 @@
f"Pulsar has not been fitted! Saving pre-fit parfile to {filename} in {format} format"
)

except:
except Exception:

Check warning on line 938 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L938

Added line #L938 was not covered by tests
if filename in [(), ""]:
print("Write Par cancelled.")
else:
Expand All @@ -938,7 +954,7 @@
log.info(f"Choose output file {filename}")
self.psr.all_toas.write_TOA_file(filename, format=format)
log.info(f"Wrote TOAs to {filename} with format {format}")
except:
except Exception:

Check warning on line 957 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L957

Added line #L957 was not covered by tests
if filename in [(), ""]:
print("Write Tim cancelled.")
else:
Expand Down Expand Up @@ -1250,6 +1266,37 @@
elif label == "rounded MJD":
data = np.floor(self.psr.all_toas.get_mjds() + 0.5 * u.d)
error = self.psr.all_toas.get_errors().to(u.d)
elif label == "WB DM":
if self.psr.all_toas.wideband:
data = self.psr.all_toas.get_dms().to(pint.dmu)
error = self.psr.all_toas.get_dm_errors().to(pint.dmu)

Check warning on line 1272 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1271-L1272

Added lines #L1271 - L1272 were not covered by tests
else:
log.warning("Cannot plot WB DMs for NB TOAs.")
data = None
error = None

Check warning on line 1276 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1274-L1276

Added lines #L1274 - L1276 were not covered by tests
elif label == "WB DM res":
if self.psr.all_toas.wideband:
if self.psr.fitter is not None:
data = self.psr.fitter.resids.dm.calc_resids().to(pint.dmu)

Check warning on line 1280 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1280

Added line #L1280 was not covered by tests
else:
data = (

Check warning on line 1282 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1282

Added line #L1282 was not covered by tests
WidebandDMResiduals(self.psr.all_toas, self.psr.prefit_model)
.calc_resids()
.to(pint.dmu)
)
error = self.psr.all_toas.get_dm_errors().to(pint.dmu)

Check warning on line 1287 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1287

Added line #L1287 was not covered by tests
else:
log.warning("Cannot plot WB DM resids for NB TOAs.")
data = None
error = None

Check warning on line 1291 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1289-L1291

Added lines #L1289 - L1291 were not covered by tests
elif label == "WB DM err":
if self.psr.all_toas.wideband:
data = self.psr.all_toas.get_dm_errors().to(pint.dmu)
error = None

Check warning on line 1295 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1294-L1295

Added lines #L1294 - L1295 were not covered by tests
else:
log.warning("Cannot plot WB DM errors for NB TOAs.")
data = None
error = None

Check warning on line 1299 in src/pint/pintk/plk.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/plk.py#L1297-L1299

Added lines #L1297 - L1299 were not covered by tests
elif label == "elongation":
data = np.degrees(
self.psr.prefit_model.sun_angle(self.psr.all_toas, also_distance=False)
Expand Down
7 changes: 5 additions & 2 deletions src/pint/pintk/pulsar.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""A wrapper around pulsar functions for pintk to use.
"""A wrapper around pulsar functions for `pintk` to use.

This object will be shared between widgets in the main frame
and will contain the pre/post fit model, toas,
Expand Down Expand Up @@ -37,6 +37,9 @@
"frequency",
"TOA error",
"rounded MJD",
"WB DM",
"WB DM res",
"WB DM err",
"elongation",
]

Expand Down Expand Up @@ -324,7 +327,7 @@
line += "%24s\t" % post.str_quantity(post.quantity)
try:
line += "%16.8g " % post.uncertainty.value
except:
except Exception:

Check warning on line 330 in src/pint/pintk/pulsar.py

View check run for this annotation

Codecov / codecov/patch

src/pint/pintk/pulsar.py#L330

Added line #L330 was not covered by tests
line += "%18s" % ""
diff = post.value - pre.value
line += "%16.8g " % diff
Expand Down
8 changes: 6 additions & 2 deletions src/pint/residuals.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def __new__(
except KeyError as e:
raise ValueError(
f"'{residual_type}' is not a PINT supported residual. Currently supported data types are {list(residual_map.keys())}"
)
) from e

return super().__new__(cls)

Expand Down Expand Up @@ -370,11 +370,15 @@ def calc_phase_resids(
# and delta_pulse_numbers (from PHASE lines or adding phase jumps in GUI)
i = pulse_num.copy()
f = np.zeros_like(pulse_num)
if np.any(np.isnan(pulse_num)):

c = np.isnan(pulse_num)
if np.any(c):
dlakaplan marked this conversation as resolved.
Show resolved Hide resolved
# i[c] = 0
raise ValueError("Pulse numbers are missing on some TOAs")
residualphase = modelphase - Phase(i, f)
# This converts from a Phase object to a np.float128
full = residualphase.int + residualphase.frac

elif self.track_mode == "nearest":
# Compute model phase
modelphase = self.model.phase(self.toas) + delta_pulse_numbers
Expand Down
Loading