Skip to content

Commit 3b9bd3d

Browse files
committed
build: added rasterio to conda requirements
docs: Added "plot composition" section to Plotting tutorial. Added plot_magnitude_vs_time and plot_magnitude_histogram examples to Catalog-forecast tutorial. Added reflinks to tutorial headers. Added load_evaluation_result to API ref. ft: Added default plot_region=True to forecast.plot(). Added log_scale option to plot_magnitude_histogram for y axis, and also the mean is plotted now instead of median. Remove tight_layout from plot_catalog() option. fix: added transform argument when plotting the region in plot_gridded_dataset.
1 parent 0f0f811 commit 3b9bd3d

12 files changed

+158
-81
lines changed

csep/core/catalogs.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ def plot(self, ax=None, show=False, extent=None, set_global=False, **kwargs):
857857

858858
# no mutable function arguments
859859
plot_args_default = {
860-
'basemap': kwargs.pop('basemap', None) or 'ESRI_terrain',
860+
'basemap': kwargs.pop('basemap', 'ESRI_terrain') if ax is None else None
861861
}
862862

863863
# Plot the region border (if it exists) by default
@@ -870,10 +870,11 @@ def plot(self, ax=None, show=False, extent=None, set_global=False, **kwargs):
870870

871871
plot_args = kwargs.get('plot_args', {})
872872
plot_args_default.update(plot_args)
873+
plot_args_default.update(kwargs)
873874

874875
# this call requires internet connection and basemap
875876
ax = plot_catalog(self, ax=ax, show=show, extent=extent,
876-
set_global=set_global, **plot_args_default, **kwargs)
877+
set_global=set_global, **plot_args_default)
877878
return ax
878879

879880
def plot_magnitude_versus_time(self, ax=None, show=False, **kwargs):

csep/core/forecasts.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,10 @@ def plot(self, ax=None, show=False, log=True, extent=None, set_global=False, plo
453453

454454
plot_args = plot_args or {}
455455
plot_args.update({
456-
'basemap': kwargs.pop('basemap', None) or 'ESRI_terrain',
456+
'basemap': kwargs.pop('basemap', 'ESRI_terrain') if ax is None else None,
457457
'title': kwargs.pop('title', None) or self.name,
458458
'figsize': kwargs.pop('figsize', None) or (8, 8),
459+
'plot_region': True
459460
})
460461
plot_args.update(**kwargs)
461462
# this call requires internet connection and basemap

csep/utils/plots.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ def plot_magnitude_histogram(
393393
observation: "CSEPCatalog",
394394
magnitude_bins: Optional[Union[List[float], numpy.ndarray]] = None,
395395
percentile: int = 95,
396+
log_scale: bool = True,
396397
ax: Optional["matplotlib.axes.Axes"] = None,
397398
show: bool = False,
398399
**kwargs,
@@ -411,6 +412,8 @@ def plot_magnitude_histogram(
411412
Defaults to `None`.
412413
percentile (int, optional): The percentile used for uncertainty intervals. Defaults to
413414
`95`.
415+
log_scale (bool, optional): Whether to plot the y-axis in logarithmic scale. Defaults to
416+
True.
414417
ax (matplotlib.axes.Axes, optional): The axes object to draw the plot on. If `None`, a
415418
new figure and axes are created. Defaults to `None`.
416419
show (bool, optional): Whether to display the plot immediately. Defaults to `False`.
@@ -482,6 +485,7 @@ def get_histogram_synthetic_cat(x, mags, normed=True):
482485
bin_centers = (bin_edges[1:] + bin_edges[:-1]) / 2
483486

484487
# Compute statistics for the forecast histograms
488+
forecast_mean = numpy.mean(forecast_hist, axis=0)
485489
forecast_median = numpy.median(forecast_hist, axis=0)
486490
forecast_low = numpy.percentile(forecast_hist, (100 - percentile) / 2.0, axis=0)
487491
forecast_high = numpy.percentile(forecast_hist, 100 - (100 - percentile) / 2.0, axis=0)
@@ -490,7 +494,12 @@ def get_histogram_synthetic_cat(x, mags, normed=True):
490494
forecast_err_upper = forecast_high - forecast_median
491495

492496
# Plot observed histogram
493-
ax.semilogy(
497+
if log_scale:
498+
plot_func = ax.semilogy
499+
else:
500+
plot_func = ax.plot
501+
502+
plot_func(
494503
bin_centers,
495504
obs_hist,
496505
color=plot_args["color"],
@@ -504,11 +513,11 @@ def get_histogram_synthetic_cat(x, mags, normed=True):
504513
# Plot forecast histograms as bar plot with error bars
505514
ax.plot(
506515
bin_centers,
507-
forecast_median,
516+
forecast_mean,
508517
".",
509518
markersize=plot_args["markersize"],
510519
color="darkred",
511-
label="Forecast Median",
520+
label="Forecast Mean",
512521
)
513522
ax.errorbar(
514523
bin_centers,
@@ -815,9 +824,6 @@ def plot_catalog(
815824

816825
ax.set_title(plot_args["title"], fontsize=plot_args["title_fontsize"], y=1.06)
817826

818-
if plot_args["tight_layout"]:
819-
ax.figure.tight_layout()
820-
821827
if show:
822828
pyplot.show()
823829

@@ -934,7 +940,8 @@ def plot_gridded_dataset(
934940
if plot_region and not set_global:
935941
try:
936942
pts = region.tight_bbox()
937-
ax.plot(pts[:, 0], pts[:, 1], lw=1, color=plot_args["region_color"])
943+
ax.plot(pts[:, 0], pts[:, 1], lw=1, color=plot_args["region_color"],
944+
transform=ccrs.PlateCarree())
938945
except AttributeError:
939946
pass
940947

docs/reference/api_reference.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@ This contains a reference document to the PyCSEP API.
77

88
.. :currentmodule:: csep
99
10-
Loading catalogs and forecasts
11-
------------------------------
10+
Loading catalogs, forecasts and results
11+
---------------------------------------
1212

1313
.. autosummary::
1414
:toctree: generated
1515

16-
load_stochastic_event_sets
1716
load_catalog
1817
query_comcat
1918
query_bsi
2019
query_gns
2120
query_gcmt
2221
load_gridded_forecast
2322
load_catalog_forecast
23+
load_stochastic_event_sets
24+
load_evaluation_result
2425

2526
Catalogs
2627
--------

examples/tutorials/catalog_filtering.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
.. _tutorial-catalog-filtering:
33
4-
Catalogs operations
4+
Catalogs Operations
55
===================
66
77
This example demonstrates how to perform standard operations on a catalog. This example requires an internet

examples/tutorials/catalog_forecast_evaluation.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""
2-
.. _catalog-forecast-evaluation:
2+
3+
.. _tutorial-catalog-forecast-evaluation:
34
45
Catalog-based Forecast Evaluation
56
=================================
@@ -24,7 +25,7 @@
2425

2526
import csep
2627
from csep.core import regions, catalog_evaluations
27-
from csep.utils import datasets, time_utils
28+
from csep.utils import datasets, time_utils, plots
2829

2930
####################################################################################################################################
3031
# Define start and end times of forecast
@@ -71,12 +72,13 @@
7172
# More fine-grain control and optimizations can be achieved by creating a :class:`csep.core.forecasts.CatalogForecast` directly.
7273

7374
forecast = csep.load_catalog_forecast(datasets.ucerf3_ascii_format_landers_fname,
74-
start_time = start_time, end_time = end_time,
75-
region = space_magnitude_region,
76-
apply_filters = True)
75+
start_time=start_time, end_time=end_time,
76+
region=space_magnitude_region,
77+
apply_filters=True)
7778

7879
# Assign filters to forecast
79-
forecast.filters = [f'origin_time >= {forecast.start_epoch}', f'origin_time < {forecast.end_epoch}']
80+
forecast.filters = [f'origin_time >= {forecast.start_epoch}',
81+
f'origin_time < {forecast.end_epoch}']
8082

8183
####################################################################################################################################
8284
# Obtain evaluation catalog from ComCat
@@ -99,6 +101,22 @@
99101
# Plot the catalog
100102
comcat_catalog.plot(show=True)
101103

104+
####################################################################################################################################
105+
# Exploratory visualizations
106+
# --------------------------
107+
#
108+
# We can visualize differences between the distribution of event counts of the observations against the forecast:
109+
110+
plots.plot_cumulative_events_versus_time(forecast, comcat_catalog, time_axis='days', show=True)
111+
112+
113+
####################################################################################################################################
114+
#
115+
# and their magnitude histograms
116+
#
117+
118+
plots.plot_magnitude_histogram(forecast, comcat_catalog, log_scale=False, show=True)
119+
102120
####################################################################################################################################
103121
# Perform number test
104122
# -------------------
@@ -113,4 +131,4 @@
113131
#
114132
# We can create a simple visualization of the number test from the evaluation result class.
115133

116-
ax = number_test_result.plot(show=True)
134+
ax = number_test_result.plot(show=True)

examples/tutorials/gridded_forecast_evaluation.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,14 @@
2828
from csep.core import poisson_evaluations as poisson
2929
from csep.utils import datasets, time_utils, plots
3030

31-
# Needed to show plots from the terminal
32-
import matplotlib.pyplot as plt
33-
3431
####################################################################################################################################
3532
# Define forecast properties
3633
# --------------------------
3734
#
3835
# We choose a :ref:`time-independent-forecast` to show how to evaluate a grid-based earthquake forecast using PyCSEP. Note,
3936
# the start and end date should be chosen based on the creation of the forecast. This is important for time-independent forecasts
40-
# because they can be rescale to any arbitrary time period.
41-
from csep.utils.stats import get_Kagan_I1_score
37+
# because they can be rescaled to any arbitrary time period.
38+
4239

4340
start_date = time_utils.strptime_to_utc_datetime('2006-11-12 00:00:00.0')
4441
end_date = time_utils.strptime_to_utc_datetime('2011-11-12 00:00:00.0')
@@ -103,8 +100,8 @@
103100
# consistency tests.
104101

105102
ax = plots.plot_consistency_test(spatial_test_result,
106-
xlabel='Spatial likelihood')
107-
plt.show()
103+
xlabel='Spatial likelihood',
104+
show=True)
108105

109106

110107
####################################################################################################################################
@@ -182,5 +179,6 @@
182179
# We can also get the Kagan's I_1 score for a gridded forecast
183180
# (see Kagan, YanY. [2009] Testing long-term earthquake forecasts: likelihood methods and error diagrams, Geophys. J. Int., v.177, pages 532-542).
184181

182+
from csep.utils.stats import get_Kagan_I1_score
185183
I_1 = get_Kagan_I1_score(forecast, catalog)
186184
print("I_1score is: ", I_1)

0 commit comments

Comments
 (0)