Skip to content

Commit ebf878d

Browse files
Create a basic measurement plot and rename the previous one to overlay_measurements
1 parent c9342d6 commit ebf878d

File tree

3 files changed

+81
-12
lines changed

3 files changed

+81
-12
lines changed

python/nyx_space/plots/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"""
1818

1919
from .gauss_markov import plot_gauss_markov
20-
from .od import plot_covar, plot_estimates, plot_measurements
20+
from .od import plot_covar, plot_estimates, overlay_measurements
2121
from .traj import plot_traj, plot_ground_track, plot_traj_errors
2222

2323
__all__ = [
@@ -27,5 +27,5 @@
2727
"plot_traj",
2828
"plot_traj_errors",
2929
"plot_ground_track",
30-
"plot_measurements",
30+
"overlay_measurements",
3131
]

python/nyx_space/plots/od.py

+77-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
"""
1818

1919
import plotly.graph_objects as go
20+
import plotly.express as px
21+
from datetime import datetime
2022

2123
from .utils import plot_with_error, plot_line, finalize_plot, colors
2224

@@ -28,6 +30,7 @@
2830
import numpy as np
2931
from scipy.stats import norm
3032

33+
from nyx_space.time import Epoch
3134

3235
def plot_estimates(
3336
dfs,
@@ -247,11 +250,11 @@ def plot_estimates(
247250

248251
if msr_df is not None:
249252
# Plot the measurements on both plots
250-
pos_fig = plot_measurements(
253+
pos_fig = overlay_measurements(
251254
msr_df, title, time_col_name, fig=pos_fig, show=False
252255
)
253256

254-
vel_fig = plot_measurements(
257+
vel_fig = overlay_measurements(
255258
msr_df, title, time_col_name, fig=vel_fig, show=False
256259
)
257260

@@ -454,11 +457,11 @@ def plot_covar(
454457

455458
if msr_df is not None:
456459
# Plot the measurements on both plots
457-
pos_fig = plot_measurements(
460+
pos_fig = overlay_measurements(
458461
msr_df, title, time_col_name, fig=pos_fig, show=False
459462
)
460463

461-
vel_fig = plot_measurements(
464+
vel_fig = overlay_measurements(
462465
msr_df, title, time_col_name, fig=vel_fig, show=False
463466
)
464467

@@ -481,15 +484,19 @@ def plot_covar(
481484
return pos_fig, vel_fig
482485

483486

484-
def plot_measurements(
487+
def overlay_measurements(
488+
fig,
485489
dfs,
486490
title,
487491
time_col_name="Epoch:Gregorian UTC",
488492
html_out=None,
489493
copyright=None,
490-
fig=None,
491494
show=True,
492495
):
496+
"""
497+
Given a plotly figure, overlay the measurements as shaded regions on top of the existing plot.
498+
For a plot of measurements only, use `plot_measurements`.
499+
"""
493500
if not isinstance(dfs, list):
494501
dfs = [dfs]
495502

@@ -571,7 +578,7 @@ def plot_measurements(
571578
line_width=0,
572579
)
573580

574-
finalize_plot(fig, title, x_title, copyright, show)
581+
finalize_plot(fig, title, x_title, None, copyright)
575582

576583
if html_out:
577584
with open(html_out, "w") as f:
@@ -673,7 +680,7 @@ def plot_residuals(
673680

674681
if msr_df is not None:
675682
# Plot the measurements on both plots
676-
fig = plot_measurements(
683+
fig = overlay_measurements(
677684
msr_df, title, time_col_name, fig=fig, show=False
678685
)
679686

@@ -744,3 +751,65 @@ def plot_residual_histogram(
744751

745752
if show:
746753
fig.show()
754+
755+
def plot_measurements(
756+
df,
757+
msr_type,
758+
title=None,
759+
time_col_name="Epoch:Gregorian UTC",
760+
html_out=None,
761+
copyright=None,
762+
show=True,
763+
):
764+
"""
765+
Plot the provided measurement type, fuzzy matching of the column name
766+
"""
767+
768+
msr_col_name = [col for col in df.columns if msr_type in col.lower()]
769+
770+
if title is None:
771+
# Build a title
772+
station_names = ", ".join([name for name in df["Tracking device"].unique()])
773+
start = Epoch(df["Epoch:Gregorian UTC"].iloc[0])
774+
end = Epoch(df["Epoch:Gregorian UTC"].iloc[-1])
775+
arc_duration = end.timedelta(start)
776+
title = f"Measurements from {station_names} spanning {start} to {end} ({arc_duration})"
777+
778+
try:
779+
orig_tim_col = df[time_col_name]
780+
except KeyError:
781+
# Find the time column
782+
try:
783+
col_name = [x for x in df.columns if x.startswith("Epoch")][0]
784+
except IndexError:
785+
raise KeyError("Could not find any Epoch column")
786+
print(f"Could not find time column {time_col_name}, using `{col_name}`")
787+
orig_tim_col = df[col_name]
788+
789+
# Build a Python datetime column
790+
pd_ok_epochs = []
791+
for epoch in orig_tim_col:
792+
epoch = epoch.replace("UTC", "").strip()
793+
if "." not in epoch:
794+
epoch += ".0"
795+
pd_ok_epochs += [datetime.fromisoformat(str(epoch).replace("UTC", "").strip())]
796+
df["time_col"] = pd.Series(pd_ok_epochs)
797+
x_title = "Epoch {}".format(time_col_name[-3:])
798+
799+
fig = px.scatter(df, x="time_col", y=msr_col_name, color="Tracking device")
800+
801+
finalize_plot(fig, title, x_title, msr_col_name[0], copyright)
802+
803+
if html_out:
804+
with open(html_out, "w") as f:
805+
f.write(fig.to_html())
806+
print(f"Saved HTML to {html_out}")
807+
808+
if show:
809+
fig.show()
810+
else:
811+
return fig
812+
813+
if __name__ == "__main__":
814+
df = pd.read_parquet("output_data/msr-2023-11-25T06-14-01.parquet")
815+
plot_measurements(df, "range")

python/nyx_space/plots/utils.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def _add_watermark(who):
104104
nyx_tpl.layout.annotations = [
105105
dict(
106106
name="watermark",
107-
text=f"Nyx Space 🄯 AGPLv3 {year}",
107+
text=f"Powered by Nyx Space © {year}",
108108
opacity=0.75,
109109
font=dict(color="#3d84e8", size=12),
110110
xref="paper",
@@ -201,7 +201,7 @@ def finalize_plot(fig, title, xtitle=None, ytitle=None, copyright=None):
201201
"""
202202

203203
annotations = [dict(templateitemname="watermark")]
204-
if copyright:
204+
if copyright is not None:
205205
annotations += [
206206
dict(
207207
templateitemname="watermark",

0 commit comments

Comments
 (0)