Skip to content

Plot refactor - #415

Open
eshelDror wants to merge 38 commits into
sblunt:mainfrom
eshelDror:plot_refactor
Open

Plot refactor#415
eshelDror wants to merge 38 commits into
sblunt:mainfrom
eshelDror:plot_refactor

Conversation

@eshelDror

Copy link
Copy Markdown
Collaborator

No description provided.

@eshelDror
eshelDror marked this pull request as ready for review July 19, 2026 19:32
Comment thread orbitize/plot.py
cmap = colors.LinearSegmentedColormap.from_list(
"trunc({n},{a:.2f},{b:.2f})".format(n=cmap.name, a=0.0, b=0.7),
cmap(np.linspace(0.0, 0.7, 1000)),
)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to define cmap here and below? Can we reduce it to just one def, either at the top here or in the Plotter class?

Comment thread orbitize/plot.py
def __init__(
self,
results,
object_to_plot=1, # TODO: Support multiplanet

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting that we should resolve this todo before merge (I'm sure this is already on your radar).

Comment thread orbitize/plot.py Outdated
self.results = results
self.system = results.system

if default_cmap is not None:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure the logic works here to define the colormap as we expect

Comment thread orbitize/plot.py Outdated

# For plotting different astrometry instruments
if plot_astrometry_insts:
astr_colors = ("#FF7F11", "#11FFE3", "#14FF11", "#7A11FF", "#FF1919")

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

define these in the same place you define the RV data colors and symbols above.

Comment thread orbitize/plot.py Outdated

return fig

def _plot_full_orbits(self, ax, plot_astrometry, square_plot, fontsize, cmap, plot_astrometry_insts, astr_insts=None, astr_inst_inds=None, astr_colors=None, astr_symbols=None):

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest putting all the private methods together in the beginning

Comment thread orbitize/plot.py
plt.sca(ax3)

# scale back to primary RV semi amplitude
vz0 = self.vz1[i] * (-(mtot[i] - m0[i]) / np.median(m0[i])) # TODO: vectorize

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use the output of calc_all_orbits here rather than doing the math ourselves

Comment thread orbitize/plot.py Outdated
else:
plt.sca(ax3)

# scale back to primary RV semi amplitude

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this comment isn't relevant anymore; we can remove it

Comment thread orbitize/plot.py
plt.plot(yr_epochs, pas, color=sep_pa_color)

def _plot_rv_data(self, ax3, ax4, rv_time_series, rv_time_series2, sep_pa_color):
# plot RV orbits here

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's call these _plot_rv_model, _plot_sep_pa_model, etc, since the data is being plotted in a separate place

Comment thread orbitize/plot.py Outdated
epochs = inst_data["epoch"]
epochs = Time(epochs, format="mjd").decimalyear
inst_err = inst_data["quant1_err"]
gam_err2 = np.sqrt(np.square(inst_err)+np.square(med_sigma[i]))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these (gam_err1, gam_err2, gam_err_2) could use more informative variable names

Comment thread orbitize/plot.py Outdated
s=30,
marker=next(ax3_symbols),
c=c,
label=name,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the name is "defrv" (our default when the user doesn't provide an instrument name) we should make the label something more informative like "RV data"

Comment thread orbitize/plot.py Outdated
epochs = Time(epochs, format="mjd").decimalyear
inst_err = inst_data["quant1_err"]
gam_err2 = np.sqrt(np.square(inst_err)+np.square(med_sigma[i]))
gam_err_1 = np.sqrt(gam_err2)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subtle point here-- each orbit may have its own fitted value of jitter (sigma). We want to use that value, rather than the median across all orbits.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think gam_err_1 is unneeded. Below, gam_err_2 should be np.sqrt(gam_err2**2 + stddev_ga[i]**2)

Comment thread orbitize/plot.py Outdated
plt.errorbar(
x=epochs2,
y=rvs2-med_ga2[i],
yerr=stddev_ga2[i],

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job working through all the differences here!

Comment thread orbitize/plot.py Outdated
ecolor=c,
zorder=5,
ls="none",
label="{} gamma err".format(name2)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably suggest writing these captions out in latex to make them as clear as possible: std(rv_{inst name} - gamma_{inst name}); sigma_{inst name}2 + sigma2 (and same for the other case below)

Comment thread orbitize/plot.py
deoff = self.astr_deoff
seps = []
pas = []
raoff_100 = self.raoff1

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use your defined variables throughout rather than redefining them (for clarity)

Comment thread orbitize/plot.py

# for j in range(len(astr_epochs)):

# seps0, pas0 = orbitize.system.radec2seppa(raoff[i][j], deoff[i][j], mod180=mod180)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented out code

Comment thread orbitize/plot.py
arcs with PAs that cross 360 deg during observations (default: False)

Return:
``matplotlib.pyplot.Figure``: the residual plots

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the same logic for plotting residuals as we used above for plotting the gammas for RVs. Offer two options for plotting the uncertainties, exactly the same way you did above.

Comment thread orbitize/plot.py
timestep = epoch_in_yr[1] - epoch_in_yr[0]
# dra/dt and ddec/dt
ddec_b = np.gradient(deoff[i, :], timestep) # in mas/yr
dec_b_radian = (

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use astropy.units to do these conversions for clarity

@sblunt

sblunt commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Looks great! Excellent job @eshelDror. A few small overall comments:

  1. Please push the changes to the notebooks without outputs (i.e. run. "clear output" before pushing). That makes the diff a little cleaner. The plots will be autogenerated by nbconvert when the documentation is building, and you'll see the plots on orbitize.info.
  2. In general, it would be very good to use a consistent set of mask variables (e.g. self.rv_data) throughout, rather than redefining them in each subfunction. This is definitely orbitize's fault, not yours, but since you're refactoring the plot code, I think you should be the one to fix it. :D I left a few in-line comments with suggested places to make these changes, but I don't think I got all of them.

Comment thread orbitize/plot.py

if plot_priors:
axes = figure.axes
num_params = len(param_indices)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can avoid much of this normalization code by passing hist2d_kwargs = {"density":True} into corner.corner.

Comment thread orbitize/plot.py
for i, param_i in enumerate(param_indices):
prior = results.system.sys_priors[param_i]
if not hasattr(prior, "compute_lnprob"):
continue

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should never happen; Prior objects by definition (by means of the abstract base class) must have a compute_lnprob method, so I think you can safely remove this check

@sblunt

sblunt commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Also, see aesthetic suggestions in #378 and please implement the ones you like! I think the main things I'd like to see here based on those suggestions are:

  1. by default using circles instead of stars for astrometric data
  2. using minor ticks and mirror ticks on all panels
  3. using a (slightly) bigger font size
  4. I also think the default red astrometry is a little jarring. Play around with the default color scheme and see what you can figure out that you like!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants