Source code for pint.pintk.paredit
import io
import tkinter as tk
import tkinter.filedialog as tkFileDialog
import pint.models
import pint.logging
from loguru import logger as log
import pint.pintk.plk
[docs]class ParChoiceWidget(tk.Frame):
"""
Lets the user select between the pre-fit and post-fit model for the
loaded pulsar
"""
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.configure(bg=pint.pintk.plk.background)
self.choose_callback = None
self.initLayout()
def initLayout(self):
self.choice = tk.StringVar()
self.prefit = tk.Radiobutton(
self,
text="Pre-Fit",
command=self.choose,
variable=self.choice,
value="prefit",
bg=pint.pintk.plk.background,
fg=pint.pintk.plk.foreground,
)
self.prefit.select()
self.prefit.grid(row=0, column=0)
self.postfit = tk.Radiobutton(
self,
text="Post-Fit",
command=self.choose,
variable=self.choice,
value="postfit",
bg=pint.pintk.plk.background,
fg=pint.pintk.plk.foreground,
)
self.postfit.grid(row=0, column=1)
def setCallbacks(self, choose):
self.choose_callback = choose
def choose(self):
self.choose_callback()
[docs]class ParActionsWidget(tk.Frame):
"""
Allows the user to reset the model, apply changes, or save to a parfile
"""
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.configure(bg=pint.pintk.plk.background)
self.reset_callback = None
self.remove_callback = None
self.apply_callback = None
self.write_callback = None
self.centerPE_callback = None
self.centerPO_callback = None
self.centerT0_callback = None
self.initLayout()
def initLayout(self):
button = tk.Button(
self,
text="Reset Model",
command=self.resetParfile,
fg=pint.pintk.plk.foreground,
)
button.grid(row=0, column=0)
button = tk.Button(
self,
text="Remove Changes",
command=self.removeChanges,
fg=pint.pintk.plk.foreground,
)
button.grid(row=0, column=1)
button = tk.Button(
self,
text="Apply Changes",
command=self.applyChanges,
fg=pint.pintk.plk.foreground,
)
button.grid(row=0, column=2)
button = tk.Button(
self,
text="Write Par",
command=self.writePar,
fg=pint.pintk.plk.foreground,
)
button.grid(row=0, column=3)
button = tk.Button(
self,
text="Center PEPOCH",
command=self.centerPEPOCH,
fg=pint.pintk.plk.foreground,
)
button.grid(row=0, column=4)
button = tk.Button(
self,
text="Center POSEPOCH",
command=self.centerPOSEPOCH,
fg=pint.pintk.plk.foreground,
)
button.grid(row=1, column=1)
button = tk.Button(
self,
text="Center T0",
command=self.centerT0,
fg=pint.pintk.plk.foreground,
)
button.grid(row=1, column=2)
def setCallbacks(
self,
resetParfile,
removeChanges,
applyChanges,
writePar,
centerPEPOCH,
centerPOSEPOCH,
centerT0,
):
self.reset_callback = resetParfile
self.remove_callback = removeChanges
self.apply_callback = applyChanges
self.write_callback = writePar
self.centerPE_callback = centerPEPOCH
self.centerPO_callback = centerPOSEPOCH
self.centerT0_callback = centerT0
def resetParfile(self):
log.debug("Reset clicked")
if self.reset_callback is not None:
self.reset_callback()
def removeChanges(self):
log.debug("Remove clicked")
if self.remove_callback is not None:
self.remove_callback()
def applyChanges(self):
log.debug("Apply clicked")
if self.apply_callback is not None:
self.apply_callback()
def writePar(self):
log.debug("Write clicked")
if self.write_callback is not None:
self.write_callback()
def centerPEPOCH(self):
log.debug("Center PEPOCH clicked")
if self.centerPE_callback is not None:
self.centerPE_callback()
def centerPOSEPOCH(self):
log.debug("Center POSEPOCH clicked")
if self.centerPO_callback is not None:
self.centerPO_callback()
def centerT0(self):
log.debug("Center T0 clicked")
if self.centerT0_callback is not None:
self.centerT0_callback()
[docs]class ParWidget(tk.Frame):
"""
A widget that allows editing and saving of a pulsar parfile
"""
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.configure(bg=pint.pintk.plk.background)
self.psr = None
self.update_callbacks = None
self.initLayout()
def initLayout(self):
self.choiceWidget = ParChoiceWidget(master=self)
self.choiceWidget.grid(row=0, column=0, sticky="nw")
self.editor = tk.Text(self)
self.editor.grid(row=1, column=0, sticky="nesw")
scrollbar = tk.Scrollbar(self, command=self.editor.yview)
scrollbar.grid(row=1, column=1, sticky="nesw")
self.editor["yscrollcommand"] = scrollbar.set
self.actionsWidget = ParActionsWidget(master=self)
self.actionsWidget.grid(row=2, column=0, sticky="w")
self.grid_rowconfigure(0, weight=1)
self.grid_rowconfigure(1, weight=10)
self.grid_rowconfigure(2, weight=1)
def setPulsar(self, psr, updates):
self.psr = psr
self.choiceWidget.setCallbacks(self.set_model)
self.actionsWidget.setCallbacks(
self.reset,
self.set_model,
self.applyChanges,
self.writePar,
self.centerPEPOCH,
self.centerPOSEPOCH,
self.centerT0,
)
self.set_model()
self.update_callbacks = updates
def call_updates(self):
if self.update_callbacks is not None:
for ucb in self.update_callbacks:
ucb()
def reset(self):
self.choiceWidget.prefit.select()
self.psr.reset_model()
self.set_model()
self.call_updates()
def set_model(self, newpsr=None):
# if the pulsar was updated in pintk, update here
if newpsr != None:
self.psr = newpsr
choice = self.choiceWidget.choice.get()
if choice == "postfit":
if self.psr.fitted:
self.editor.delete("1.0", tk.END)
self.editor.insert("1.0", self.psr.postfit_model.as_parfile())
else:
log.warning("There is no postfit model yet!")
self.choiceWidget.prefit.select()
elif choice == "prefit":
self.editor.delete("1.0", tk.END)
self.editor.insert("1.0", self.psr.prefit_model.as_parfile())
def applyChanges(self):
text = self.editor.get("1.0", "end-1c")
if self.psr.fitted:
# if pulsar already fitted, add changes to postfit model as well
self.psr.postfit_model = pint.models.get_model(io.StringIO(text))
self.psr.prefit_model = pint.models.get_model(io.StringIO(text))
self.call_updates()
def writePar(self):
filename = tkFileDialog.asksaveasfilename(title="Choose output par file")
try:
with open(filename, "w") as fout:
fout.write(self.editor.get("1.0", "end-1c"))
log.info(f"Saved parfile to {filename}")
except Exception:
if filename in [(), ""]:
log.warning("Writing par file cancelled.")
else:
log.warning("Could not save parfile to filename:\t%s" % filename)
def centerPEPOCH(self):
if not hasattr(self.psr.prefit_model, "PEPOCH"):
log.warning("No PEPOCH to center.")
return
mintime, maxtime = (
self.psr.all_toas.get_mjds().min(),
self.psr.all_toas.get_mjds().max(),
)
midpoint = (mintime + maxtime) / 2
if self.psr.fitted:
self.psr.postfit_model.change_pepoch(midpoint)
self.psr.prefit_model.change_pepoch(midpoint)
self.set_model()
self.applyChanges()
def centerPOSEPOCH(self):
if not hasattr(self.psr.prefit_model, "POSEPOCH"):
log.warning("No POSEPOCH to center.")
return
mintime, maxtime = (
self.psr.all_toas.get_mjds().min(),
self.psr.all_toas.get_mjds().max(),
)
midpoint = (mintime + maxtime) / 2
if self.psr.fitted:
self.psr.postfit_model.change_posepoch(midpoint)
self.psr.prefit_model.change_posepoch(midpoint)
self.set_model()
self.applyChanges()
def centerT0(self):
if not hasattr(self.psr.prefit_model, "T0"):
log.warning("No T0 to center.")
return
mintime, maxtime = (
self.psr.all_toas.get_mjds().min(),
self.psr.all_toas.get_mjds().max(),
)
midpoint = (mintime + maxtime) / 2
if self.psr.fitted:
self.psr.postfit_model.change_binary_epoch(midpoint)
self.psr.prefit_model.change_binary_epoch(midpoint)
self.set_model()
self.applyChanges()