Skip to content

Commit 320ebc3

Browse files
committed
New plot
1 parent 1230842 commit 320ebc3

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

src/adam_impact_study/analysis/plots.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3029,3 +3029,147 @@ def plot_discovered_by_diameter_impact_period(
30293029
plt.tight_layout(rect=[0, 0, 0.85, 1])
30303030

30313031
return fig, ax
3032+
3033+
3034+
def plot_observed_vs_unobserved_elements(
3035+
summary: ImpactorResultSummary,
3036+
diameter: float = 1,
3037+
) -> Tuple[plt.Figure, plt.Axes]:
3038+
"""
3039+
Plot the distribution of objects in orbital element space with three categories:
3040+
- Discovered (blue)
3041+
- Observed but not discovered (yellow)
3042+
- Unobserved (red)
3043+
3044+
Parameters
3045+
----------
3046+
summary : ImpactorResultSummary
3047+
The summary of impact study results.
3048+
diameter : float, optional
3049+
The diameter [km] to filter the results by, by default 1.
3050+
3051+
Returns
3052+
-------
3053+
Tuple[plt.Figure, plt.Axes]
3054+
The figure and axes objects for the plot.
3055+
"""
3056+
# Filter to only include the given diameter
3057+
summary = summary.apply_mask(pc.equal(summary.orbit.diameter, diameter))
3058+
3059+
if len(summary) == 0:
3060+
print(f"No data found for diameter {diameter} km.")
3061+
return
3062+
3063+
orbits_at_diameter = summary.apply_mask(pc.equal(summary.orbit.diameter, diameter))
3064+
print("num orbits:", len(orbits_at_diameter))
3065+
3066+
# Get Keplerian coordinates
3067+
kep_coordinates = summary.orbit.coordinates.to_keplerian()
3068+
a_au = kep_coordinates.a.to_numpy(zero_copy_only=False)
3069+
i_deg = kep_coordinates.i.to_numpy(zero_copy_only=False)
3070+
e = kep_coordinates.e.to_numpy(zero_copy_only=False)
3071+
3072+
#print discovered objedts by those with a non null discovery time
3073+
discovered_objects = summary.apply_mask(pc.invert(pc.is_null(summary.discovery_time.days)))
3074+
print(discovered_objects)
3075+
#do the same for undiscovered by the null discovery time
3076+
undiscovered_objects = summary.apply_mask(pc.is_null(summary.discovery_time.days))
3077+
print(undiscovered_objects)
3078+
3079+
#print the object names that are observed but not discovered
3080+
3081+
assert len(orbits_discovered) + len(orbits_observed_not_discovered) + len(orbits_unobserved) == len(orbits_at_diameter)
3082+
# Create the plots
3083+
fig, axes = plt.subplots(1, 2, dpi=200, figsize=(18, 7))
3084+
3085+
# --- Plot a vs i ---
3086+
# Plot discovered (blue) first
3087+
axes[0].scatter(
3088+
a_au[discovered_mask],
3089+
i_deg[discovered_mask],
3090+
c='blue',
3091+
alpha=0.6,
3092+
label='Discovered',
3093+
s=20
3094+
)
3095+
# Plot observed but not discovered (yellow) second
3096+
axes[0].scatter(
3097+
a_au[observed_not_discovered_mask],
3098+
i_deg[observed_not_discovered_mask],
3099+
c='yellow',
3100+
alpha=0.6,
3101+
label='Observed (Not Discovered)',
3102+
s=20
3103+
)
3104+
# Plot unobserved (red) last
3105+
axes[0].scatter(
3106+
a_au[unobserved_mask],
3107+
i_deg[unobserved_mask],
3108+
c='red',
3109+
alpha=0.6,
3110+
label='Unobserved',
3111+
s=20
3112+
)
3113+
3114+
axes[0].set_xlabel("Semimajor Axis (a) [AU]")
3115+
axes[0].set_ylabel("Inclination (i) [deg]")
3116+
axes[0].set_title("a vs i")
3117+
axes[0].legend()
3118+
axes[0].grid(True, alpha=0.3)
3119+
3120+
# --- Plot a vs e ---
3121+
# Plot discovered (blue) first
3122+
axes[1].scatter(
3123+
a_au[discovered_mask],
3124+
e[discovered_mask],
3125+
c='blue',
3126+
alpha=0.6,
3127+
label='Discovered',
3128+
s=20
3129+
)
3130+
# Plot observed but not discovered (yellow) second
3131+
axes[1].scatter(
3132+
a_au[observed_not_discovered_mask],
3133+
e[observed_not_discovered_mask],
3134+
c='yellow',
3135+
alpha=0.6,
3136+
label='Observed (Not Discovered)',
3137+
s=20
3138+
)
3139+
# Plot unobserved (red) last
3140+
axes[1].scatter(
3141+
a_au[unobserved_mask],
3142+
e[unobserved_mask],
3143+
c='red',
3144+
alpha=0.6,
3145+
label='Unobserved',
3146+
s=20
3147+
)
3148+
3149+
axes[1].set_xlabel("Semimajor Axis (a) [AU]")
3150+
axes[1].set_ylabel("Eccentricity (e)")
3151+
axes[1].set_title("a vs e")
3152+
axes[1].legend()
3153+
axes[1].grid(True, alpha=0.3)
3154+
3155+
# Add overall title with statistics
3156+
n_total = len(observed_mask)
3157+
n_discovered = discovered_mask.sum()
3158+
n_observed_not_discovered = observed_not_discovered_mask.sum()
3159+
n_unobserved = unobserved_mask.sum()
3160+
assert n_total == n_discovered + n_observed_not_discovered + n_unobserved
3161+
3162+
percent_discovered = (n_discovered / n_total) * 100
3163+
percent_observed_not_discovered = (n_observed_not_discovered / n_total) * 100
3164+
percent_unobserved = (n_unobserved / n_total) * 100
3165+
3166+
fig.suptitle(
3167+
f"Distribution of Objects (Diameter: {diameter} km)\n"
3168+
f"Total Objects: {n_total}, "
3169+
f"Discovered: {n_discovered} ({percent_discovered:.1f}%), "
3170+
f"Observed Not Discovered: {n_observed_not_discovered} ({percent_observed_not_discovered:.1f}%), "
3171+
f"Unobserved: {n_unobserved} ({percent_unobserved:.1f}%)"
3172+
)
3173+
3174+
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
3175+
return fig, axes

0 commit comments

Comments
 (0)