Skip to content

Commit f5c254e

Browse files
committed
API changes: Added backwards-compatibility layer for all plotting functions that would otherwise be broke with proposed changes. Deprecation strategy were issued for distinct cases:
- Functions to be removed (plot_cumulative_events_versus_time_dev, plot_histogram, plot_ecdf, plot_magnitude_histogram_dev, add_labels_for_publication) fallback to legacy code and issue warning of future removal. - Abstracted functions ( [plot_number_test, plot_spatial_test, plot_magnitude_test, plot_likelihood_test] >> plot_test_distribution ; plot_poisson_consistency_test >> plot_consistency test ) also fallback to legacy code and issue deprecation warning hinting the new function and docs. - Refactored functions with strong API breaks (plot_cumulative_events_versus_time, plot_basemap, plot_consistency_test (when NB-distributed)) adapts to new call with known cases OR fallsback to legacy code. - Refactored functions with minor API breaks (plot_comparison_test, plot_concentration_ROC_diagram, plot_ROC_diagram, plot_Molchan_diagram) only adapts to new code with known cases without fallback to legacy. - Renamed function (plot_spatial_dataset >> plot_gridded_dataset) just wraps to correct function. refac: renamed plot_distribution_test to plot_test_distribution. Added to all catalog-based-test's names the prefix "Catalog" for consistency. ft: Added 'reset_times' to plot_magnitude_versus_time for backwards compat. tests: added unit tests for plot_magnitude_versus_time includint reset_times arg.
1 parent c009af4 commit f5c254e

File tree

5 files changed

+1931
-37
lines changed

5 files changed

+1931
-37
lines changed

csep/core/catalog_evaluations.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def magnitude_test(forecast, observed_catalog, verbose=True):
206206

207207
# prepare result
208208
result = CatalogMagnitudeTestResult(test_distribution=test_distribution,
209-
name='M-Test',
209+
name='Catalog M-Test',
210210
observed_statistic=obs_d_statistic,
211211
quantile=(delta_1, delta_2),
212212
status='normal',
@@ -301,7 +301,7 @@ def pseudolikelihood_test(forecast, observed_catalog, verbose=True):
301301
# prepare evaluation result
302302
result = CatalogPseudolikelihoodTestResult(
303303
test_distribution=test_distribution_1d,
304-
name='PL-Test',
304+
name='Catalog PL-Test',
305305
observed_statistic=obs_plh,
306306
quantile=(delta_1, delta_2),
307307
status=message,

csep/models.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def plot(self, show=False, plot_args=None):
143143
'bins': bins}
144144
# looks funny, but will update the defaults with the user defined arguments
145145
plot_args_defaults.update(plot_args)
146-
ax = plots.plot_distribution_test(self, show=show)
146+
ax = plots.plot_test_distribution(self, show=show)
147147
return ax
148148

149149

@@ -160,7 +160,7 @@ def plot(self, show=False, plot_args=None):
160160
'bins': 'auto'}
161161
# looks funny, but will update the defaults with the user defined arguments
162162
plot_args_defaults.update(plot_args)
163-
ax = plots.plot_distribution_test(self, show=show)
163+
ax = plots.plot_test_distribution(self, show=show)
164164
return ax
165165

166166

@@ -175,7 +175,7 @@ def plot(self, show=False, plot_args=None):
175175
'title': 'Magnitude Test',
176176
'bins': 'auto'}
177177
plot_args_defaults.update(plot_args)
178-
ax = plots.plot_distribution_test(self, show=show)
178+
ax = plots.plot_test_distribution(self, show=show)
179179
return ax
180180

181181

@@ -194,7 +194,7 @@ def plot(self, show=False, plot_args=None):
194194
}
195195
# looks funny, but will update the defaults with the user defined arguments
196196
plot_args_defaults.update(plot_args)
197-
ax = plots.plot_distribution_test(self, show=show)
197+
ax = plots.plot_test_distribution(self, show=show)
198198
return ax
199199

200200

csep/utils/plots.py

+54-18
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ def plot_magnitude_versus_time(
101101
max_size: int = 300,
102102
power: int = 4,
103103
alpha: float = 0.5,
104+
reset_times: bool = False,
104105
ax: Optional[matplotlib.axes.Axes] = None,
105106
show: bool = False,
106107
**kwargs: Any,
@@ -118,6 +119,7 @@ def plot_magnitude_versus_time(
118119
Defaults to `300`.
119120
power (int, optional): Power scaling of the scatter sizing. Defaults to `4`.
120121
alpha (float, optional): Transparency level for the scatter points. Defaults to `0.5`.
122+
reset_times (bool): If True, x-axis shows time in days since first event.
121123
ax (matplotlib.axes.Axes, optional): Axis object on which to plot. If not provided, a
122124
new figure and axis are created. Defaults to `None`.
123125
show (bool, optional): Whether to display the plot. Defaults to `False`.
@@ -149,8 +151,19 @@ def plot_magnitude_versus_time(
149151
# Plot data
150152
mag = catalog.data["magnitude"]
151153
datetimes = catalog.get_datetimes()
154+
155+
if reset_times:
156+
# Convert to days since first event
157+
SECONDS_PER_DAY = 86400
158+
timestamps = numpy.array([dt.timestamp() for dt in datetimes])
159+
xdata = (timestamps - timestamps[0]) / SECONDS_PER_DAY
160+
xlabel = plot_args["xlabel"] or "Days since first event"
161+
else:
162+
xdata = datetimes
163+
xlabel = plot_args["xlabel"] or "Datetime"
164+
152165
ax.scatter(
153-
datetimes,
166+
xdata,
154167
mag,
155168
marker="o",
156169
c=color,
@@ -159,15 +172,16 @@ def plot_magnitude_versus_time(
159172
)
160173

161174
# Set labels and title
162-
ax.set_xlabel(plot_args["xlabel"] or "Datetime", fontsize=plot_args["xlabel_fontsize"])
175+
ax.set_xlabel(xlabel, fontsize=plot_args["xlabel_fontsize"])
163176
ax.set_ylabel(plot_args["ylabel"] or "Magnitude", fontsize=plot_args["ylabel_fontsize"])
164177
ax.set_title(plot_args["title"], fontsize=plot_args["title_fontsize"])
165178

166179
# Autoformat ticks and labels
167-
ax.xaxis.set_major_locator(plot_args["datetime_locator"])
168-
ax.xaxis.set_major_formatter(plot_args["datetime_formatter"])
180+
if not reset_times:
181+
ax.xaxis.set_major_locator(plot_args["datetime_locator"])
182+
ax.xaxis.set_major_formatter(plot_args["datetime_formatter"])
183+
fig.autofmt_xdate()
169184
ax.grid(plot_args["grid"])
170-
fig.autofmt_xdate()
171185

172186
if plot_args["tight_layout"]:
173187
fig.tight_layout()
@@ -177,7 +191,7 @@ def plot_magnitude_versus_time(
177191
return ax
178192

179193

180-
def plot_cumulative_events_versus_time(
194+
def _plot_cumulative_events_versus_time(
181195
catalog_forecast: "CatalogForecast",
182196
observation: "CSEPCatalog",
183197
time_axis: str = "datetime",
@@ -232,7 +246,6 @@ def plot_cumulative_events_versus_time(
232246
Returns:
233247
matplotlib.axes.Axes: The Matplotlib axes object with the plotted data.
234248
"""
235-
236249
# Initialize plot
237250
plot_args = {**DEFAULT_PLOT_ARGS, **kwargs}
238251
fig, ax = pyplot.subplots(figsize=plot_args["figsize"]) if ax is None else (ax.figure, ax)
@@ -507,7 +520,7 @@ def get_histogram_synthetic_cat(x, mags, normed=True):
507520
###############
508521
# Spatial plots
509522
###############
510-
def plot_basemap(
523+
def _plot_basemap(
511524
basemap: Optional[str] = None,
512525
extent: Optional[List[float]] = None,
513526
coastline: bool = True,
@@ -887,7 +900,7 @@ def plot_gridded_dataset(
887900
#####################
888901
# Single Result plots
889902
#####################
890-
def plot_distribution_test(
903+
def plot_test_distribution(
891904
evaluation_result: "EvaluationResult",
892905
bins: Union[str, int, List[Any]] = "fd",
893906
percentile: Optional[int] = 95,
@@ -1123,7 +1136,7 @@ def plot_calibration_test(
11231136
#####################
11241137
# Results batch plots
11251138
#####################
1126-
def plot_comparison_test(
1139+
def _plot_comparison_test(
11271140
results_t: List["EvaluationResult"],
11281141
results_w: Optional[List["EvaluationResult"]] = None,
11291142
percentile: int = 95,
@@ -1282,7 +1295,7 @@ def plot_comparison_test(
12821295
return ax
12831296

12841297

1285-
def plot_consistency_test(
1298+
def _plot_consistency_test(
12861299
eval_results: Union[List["EvaluationResult"], "EvaluationResult"],
12871300
normalize: bool = False,
12881301
one_sided_lower: bool = False,
@@ -1416,7 +1429,7 @@ def plot_consistency_test(
14161429
###################
14171430
# Alarm-based plots
14181431
###################
1419-
def plot_concentration_ROC_diagram(
1432+
def _plot_concentration_ROC_diagram(
14201433
forecast: "GriddedForecast",
14211434
catalog: "CSEPCatalog",
14221435
linear: bool = True,
@@ -1532,7 +1545,7 @@ def plot_concentration_ROC_diagram(
15321545
return ax
15331546

15341547

1535-
def plot_ROC_diagram(
1548+
def _plot_ROC_diagram(
15361549
forecast: "GriddedForecast",
15371550
catalog: "CSEPCatalog",
15381551
linear: bool = True,
@@ -1659,7 +1672,7 @@ def plot_ROC_diagram(
16591672
return ax
16601673

16611674

1662-
def plot_Molchan_diagram(
1675+
def _plot_Molchan_diagram(
16631676
forecast: "GriddedForecast",
16641677
catalog: "CSEPCatalog",
16651678
linear: bool = True,
@@ -2159,7 +2172,7 @@ def _annotate_distribution_plot(
21592172

21602173
if auto_annotate:
21612174
if evaluation_result.name == "Catalog N-Test":
2162-
xlabel = "Event Count"
2175+
xlabel = "Event Counts"
21632176
ylabel = "Number of Catalogs"
21642177
title = f"{evaluation_result.name}: {evaluation_result.sim_name}"
21652178
annotation_xy = (0.5, 0.3)
@@ -2176,7 +2189,7 @@ def _annotate_distribution_plot(
21762189
)
21772190

21782191
elif evaluation_result.name == "Catalog S-Test":
2179-
xlabel = "Normalized Spatial Statistic"
2192+
xlabel = "Spatial Statistic"
21802193
ylabel = "Number of Catalogs"
21812194
title = f"{evaluation_result.name}: {evaluation_result.sim_name}"
21822195
annotation_xy = (0.2, 0.6)
@@ -2187,7 +2200,7 @@ def _annotate_distribution_plot(
21872200
)
21882201

21892202
elif evaluation_result.name == "Catalog M-Test":
2190-
xlabel = "Magnitude"
2203+
xlabel = "Magnitude Statistic"
21912204
ylabel = "Number of Catalogs"
21922205
title = f"{evaluation_result.name}: {evaluation_result.sim_name}"
21932206
annotation_xy = (0.55, 0.6)
@@ -2197,7 +2210,7 @@ def _annotate_distribution_plot(
21972210
f"$\\omega = {evaluation_result.observed_statistic:.2f}$"
21982211
)
21992212
elif evaluation_result.name == "Catalog PL-Test":
2200-
xlabel = "Likelihood"
2213+
xlabel = "Pseudo-Likelihood"
22012214
ylabel = "Number of Catalogs"
22022215
title = f"{evaluation_result.name}: {evaluation_result.sim_name}"
22032216
annotation_xy = (0.55, 0.3)
@@ -2411,3 +2424,26 @@ def _process_stat_distribution(
24112424
mean = numpy.mean(test_distribution)
24122425

24132426
return plow, phigh, mean, observed_statistic
2427+
2428+
2429+
# Public export of function wrappers for backwards/legacy compatibility.
2430+
from .plots_legacy import (plot_cumulative_events_versus_time,
2431+
plot_cumulative_events_versus_time_dev,
2432+
plot_histogram,
2433+
plot_ecdf,
2434+
plot_magnitude_histogram_dev,
2435+
plot_basemap,
2436+
plot_spatial_dataset,
2437+
plot_number_test,
2438+
plot_magnitude_test,
2439+
plot_distribution_test,
2440+
plot_likelihood_test,
2441+
plot_spatial_test,
2442+
plot_poisson_consistency_test,
2443+
plot_comparison_test,
2444+
plot_consistency_test,
2445+
plot_pvalues_and_intervals,
2446+
plot_concentration_ROC_diagram,
2447+
plot_ROC_diagram,
2448+
plot_Molchan_diagram)
2449+

0 commit comments

Comments
 (0)