pastastore 1.8.0__py3-none-any.whl → 1.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pastastore/plotting.py CHANGED
@@ -42,6 +42,13 @@ class Plots:
42
42
  """
43
43
  self.pstore = pstore
44
44
 
45
+ def __repr__(self):
46
+ """Return string representation of Plots submodule."""
47
+ methods = "".join(
48
+ [f"\n - {meth}" for meth in dir(self) if not meth.startswith("_")]
49
+ )
50
+ return "Plotting submodule, available methods:" + methods
51
+
45
52
  def _timeseries(
46
53
  self,
47
54
  libname,
@@ -98,8 +105,7 @@ class Plots:
98
105
 
99
106
  if len(names) > 20 and split:
100
107
  raise ValueError(
101
- "More than 20 time series leads to too many "
102
- "subplots, set split=False."
108
+ "More than 20 time series leads to too many subplots, set split=False."
103
109
  )
104
110
 
105
111
  if ax is None:
@@ -478,6 +484,7 @@ class Plots:
478
484
  figsize=(6, 6),
479
485
  label=None,
480
486
  legend=True,
487
+ progressbar=True,
481
488
  ):
482
489
  """Plot a cumulative step histogram for a model statistic.
483
490
 
@@ -501,6 +508,8 @@ class Plots:
501
508
  of models
502
509
  legend: bool, optional
503
510
  show legend, by default True
511
+ progressbar: bool, optional
512
+ show progressbar, default is True.
504
513
 
505
514
  Returns
506
515
  -------
@@ -508,7 +517,7 @@ class Plots:
508
517
  The axes in which the cumulative histogram is plotted
509
518
  """
510
519
  statsdf = self.pstore.get_statistics(
511
- [statistic], modelnames=modelnames, progressbar=False
520
+ [statistic], modelnames=modelnames, progressbar=progressbar
512
521
  )
513
522
 
514
523
  if ax is None:
@@ -542,7 +551,7 @@ class Plots:
542
551
 
543
552
  if label is None:
544
553
  if extend:
545
- label = f"No. Models = {len(statsdf)-1}"
554
+ label = f"No. Models = {len(statsdf) - 1}"
546
555
  else:
547
556
  label = f"No. Models = {len(statsdf)}"
548
557
 
@@ -580,15 +589,15 @@ class Plots:
580
589
  The CompareModels object containing the comparison results.
581
590
  """
582
591
  models = self.pstore.get_models(modelnames)
583
- names = []
592
+ names = kwargs.pop("names", [])
584
593
  onames = [iml.oseries.name for iml in models]
585
- if len(np.unique(onames)) == 1:
594
+ if len(np.unique(onames)) == 1 and len(names) == 0:
586
595
  for modelname in modelnames:
587
596
  if onames[0] in modelname:
588
597
  names.append(modelname.replace(onames[0], ""))
589
598
  else:
590
599
  names.append(modelname)
591
- else:
600
+ elif len(np.unique(onames)) > 1:
592
601
  names = modelnames
593
602
  cm = ps.CompareModels(models, names=names)
594
603
  cm.plot(**kwargs)
@@ -618,6 +627,13 @@ class Maps:
618
627
  """
619
628
  self.pstore = pstore
620
629
 
630
+ def __repr__(self):
631
+ """Return string representation of Maps submodule."""
632
+ methods = "".join(
633
+ [f"\n - {meth}" for meth in dir(self) if not meth.startswith("_")]
634
+ )
635
+ return "Mapping submodule, available methods:" + methods
636
+
621
637
  def stresses(
622
638
  self,
623
639
  names=None,
@@ -628,6 +644,7 @@ class Maps:
628
644
  figsize=(10, 8),
629
645
  backgroundmap=False,
630
646
  label_kwargs=None,
647
+ show_legend: bool = True,
631
648
  **kwargs,
632
649
  ):
633
650
  """Plot stresses locations on map.
@@ -654,6 +671,9 @@ class Maps:
654
671
  by OpenStreetMap.Mapnik. Default option is False.
655
672
  label_kwargs: dict, optional
656
673
  dictionary with keyword arguments to pass to add_labels method
674
+ show_legend : bool, optional
675
+ add legend with each kind of stress and associated color, only possible
676
+ if colors are not explicitly passed. Default is True.
657
677
 
658
678
  Returns
659
679
  -------
@@ -680,7 +700,8 @@ class Maps:
680
700
  mask0 = (stresses["x"] != 0.0) | (stresses["y"] != 0.0)
681
701
 
682
702
  if "c" in kwargs:
683
- c = kwargs.pop("c", None)
703
+ c = kwargs.pop("c")
704
+ kind_to_color = None
684
705
  else:
685
706
  c = stresses.loc[mask0, "kind"]
686
707
  kind_to_color = {k: f"C{i}" for i, k in enumerate(c.unique())}
@@ -688,7 +709,7 @@ class Maps:
688
709
 
689
710
  r = self._plotmap_dataframe(stresses.loc[mask0], c=c, figsize=figsize, **kwargs)
690
711
  if "ax" in kwargs:
691
- ax = kwargs["ax"]
712
+ ax = kwargs.pop("ax")
692
713
  else:
693
714
  ax = r
694
715
  if labels:
@@ -696,6 +717,11 @@ class Maps:
696
717
  label_kwargs = {}
697
718
  self.add_labels(stresses, ax, adjust=adjust, **label_kwargs)
698
719
 
720
+ if show_legend and kind_to_color is not None:
721
+ for k, color in kind_to_color.items():
722
+ ax.plot([], [], color=color, label=k, **kwargs, marker="o", ls="none")
723
+ ax.legend(loc=(0, 1), frameon=False, ncol=5)
724
+
699
725
  if backgroundmap:
700
726
  self.add_background_map(ax)
701
727
 
@@ -816,6 +842,81 @@ class Maps:
816
842
 
817
843
  return ax
818
844
 
845
+ def _map_helper(
846
+ self,
847
+ df,
848
+ column,
849
+ label=True,
850
+ adjust=False,
851
+ cmap="viridis",
852
+ norm=None,
853
+ vmin=None,
854
+ vmax=None,
855
+ figsize=(10, 8),
856
+ backgroundmap=False,
857
+ **kwargs,
858
+ ):
859
+ """Help function for plotting values on map.
860
+
861
+ Parameters
862
+ ----------
863
+ df: pd.DataFrame
864
+ dataframe containing plotting information
865
+ column: str
866
+ column with values to plot
867
+ label: bool, optional
868
+ label points, by default True
869
+ adjust: bool, optional
870
+ automated smart label placement using adjustText, by default False
871
+ cmap: str or colormap, optional
872
+ (name of) the colormap, by default "viridis"
873
+ norm: norm, optional
874
+ normalization for colorbar, by default None
875
+ vmin: float, optional
876
+ vmin for colorbar, by default None
877
+ vmax: float, optional
878
+ vmax for colorbar, by default None
879
+ ax : matplotlib.Axes, optional
880
+ axes handle, if not provided a new figure is created.
881
+ figsize: tuple, optional
882
+ figuresize, by default(10, 8)
883
+ backgroundmap: bool, optional
884
+ if True, add background map (default CRS is EPSG:28992) with default tiles
885
+ by OpenStreetMap.Mapnik. Default option is False.
886
+ progressbar: bool, optional
887
+ show progressbar, default is True.
888
+
889
+ Returns
890
+ -------
891
+ ax: matplotlib.Axes
892
+ axes object
893
+
894
+ See Also
895
+ --------
896
+ self.add_background_map
897
+ """
898
+ scatter_kwargs = {
899
+ "cmap": cmap,
900
+ "norm": norm,
901
+ "vmin": vmin,
902
+ "vmax": vmax,
903
+ "edgecolors": "w",
904
+ "linewidths": 0.7,
905
+ }
906
+ scatter_kwargs.update(kwargs)
907
+
908
+ ax = self._plotmap_dataframe(
909
+ df, column=column, figsize=figsize, **scatter_kwargs
910
+ )
911
+ if label:
912
+ df.set_index("index", inplace=True)
913
+ self.add_labels(df, ax, adjust=adjust)
914
+
915
+ if backgroundmap:
916
+ self.add_background_map(ax)
917
+
918
+ return ax
919
+
819
920
  def modelstat(
820
921
  self,
821
922
  statistic,
@@ -828,6 +929,7 @@ class Maps:
828
929
  vmax=None,
829
930
  figsize=(10, 8),
830
931
  backgroundmap=False,
932
+ progressbar=True,
831
933
  **kwargs,
832
934
  ):
833
935
  """Plot model statistic on map.
@@ -857,6 +959,8 @@ class Maps:
857
959
  backgroundmap: bool, optional
858
960
  if True, add background map (default CRS is EPSG:28992) with default tiles
859
961
  by OpenStreetMap.Mapnik. Default option is False.
962
+ progressbar: bool, optional
963
+ show progressbar, default is True.
860
964
 
861
965
  Returns
862
966
  -------
@@ -868,7 +972,7 @@ class Maps:
868
972
  self.add_background_map
869
973
  """
870
974
  statsdf = self.pstore.get_statistics(
871
- [statistic], modelnames=modelnames, progressbar=False
975
+ [statistic], modelnames=modelnames, progressbar=progressbar
872
976
  ).to_frame()
873
977
 
874
978
  statsdf["oseries"] = [
@@ -878,28 +982,177 @@ class Maps:
878
982
  statsdf = statsdf.reset_index().set_index("oseries")
879
983
  df = statsdf.join(self.pstore.oseries, how="left")
880
984
 
881
- scatter_kwargs = {
882
- "cmap": cmap,
883
- "norm": norm,
884
- "vmin": vmin,
885
- "vmax": vmax,
886
- "edgecolors": "w",
887
- "linewidths": 0.7,
888
- }
985
+ return self._map_helper(
986
+ df,
987
+ column=statistic,
988
+ label=label,
989
+ adjust=adjust,
990
+ cmap=cmap,
991
+ norm=norm,
992
+ vmin=vmin,
993
+ vmax=vmax,
994
+ figsize=figsize,
995
+ backgroundmap=backgroundmap,
996
+ **kwargs,
997
+ )
889
998
 
890
- scatter_kwargs.update(kwargs)
999
+ def modelparam(
1000
+ self,
1001
+ parameter,
1002
+ modelnames=None,
1003
+ label=True,
1004
+ adjust=False,
1005
+ cmap="viridis",
1006
+ norm=None,
1007
+ vmin=None,
1008
+ vmax=None,
1009
+ figsize=(10, 8),
1010
+ backgroundmap=False,
1011
+ progressbar=True,
1012
+ **kwargs,
1013
+ ):
1014
+ """Plot model parameter value on map.
891
1015
 
892
- ax = self._plotmap_dataframe(
893
- df, column=statistic, figsize=figsize, **scatter_kwargs
1016
+ Parameters
1017
+ ----------
1018
+ parameter: str
1019
+ name of the parameter, e.g. "rech_A" or "river_a"
1020
+ modelnames : list of str, optional
1021
+ list of modelnames to include
1022
+ label: bool, optional
1023
+ label points, by default True
1024
+ adjust: bool, optional
1025
+ automated smart label placement using adjustText, by default False
1026
+ cmap: str or colormap, optional
1027
+ (name of) the colormap, by default "viridis"
1028
+ norm: norm, optional
1029
+ normalization for colorbar, by default None
1030
+ vmin: float, optional
1031
+ vmin for colorbar, by default None
1032
+ vmax: float, optional
1033
+ vmax for colorbar, by default None
1034
+ ax : matplotlib.Axes, optional
1035
+ axes handle, if not provided a new figure is created.
1036
+ figsize: tuple, optional
1037
+ figuresize, by default(10, 8)
1038
+ backgroundmap: bool, optional
1039
+ if True, add background map (default CRS is EPSG:28992) with default tiles
1040
+ by OpenStreetMap.Mapnik. Default option is False.
1041
+ progressbar: bool, optional
1042
+ show progressbar, default is True
1043
+
1044
+ Returns
1045
+ -------
1046
+ ax: matplotlib.Axes
1047
+ axes object
1048
+
1049
+ See Also
1050
+ --------
1051
+ self.add_background_map
1052
+ """
1053
+ paramdf = self.pstore.get_parameters(
1054
+ [parameter],
1055
+ modelnames=modelnames,
1056
+ progressbar=progressbar,
1057
+ ignore_errors=True,
1058
+ ).to_frame()
1059
+
1060
+ paramdf["oseries"] = [
1061
+ self.pstore.get_models(m, return_dict=True)["oseries"]["name"]
1062
+ for m in paramdf.index
1063
+ ]
1064
+ paramdf = paramdf.reset_index().set_index("oseries")
1065
+ df = paramdf.join(self.pstore.oseries, how="left")
1066
+
1067
+ return self._map_helper(
1068
+ df,
1069
+ column=parameter,
1070
+ label=label,
1071
+ adjust=adjust,
1072
+ cmap=cmap,
1073
+ norm=norm,
1074
+ vmin=vmin,
1075
+ vmax=vmax,
1076
+ figsize=figsize,
1077
+ backgroundmap=backgroundmap,
1078
+ **kwargs,
894
1079
  )
895
- if label:
896
- df.set_index("index", inplace=True)
897
- self.add_labels(df, ax, adjust=adjust)
898
1080
 
899
- if backgroundmap:
900
- self.add_background_map(ax)
1081
+ def signature(
1082
+ self,
1083
+ signature,
1084
+ names=None,
1085
+ label=True,
1086
+ adjust=False,
1087
+ cmap="viridis",
1088
+ norm=None,
1089
+ vmin=None,
1090
+ vmax=None,
1091
+ figsize=(10, 8),
1092
+ backgroundmap=False,
1093
+ progressbar=True,
1094
+ **kwargs,
1095
+ ):
1096
+ """Plot signature value on map.
901
1097
 
902
- return ax
1098
+ Parameters
1099
+ ----------
1100
+ signature: str
1101
+ name of the signature, e.g. "mean_annual_maximum" or "duration_curve_slope"
1102
+ names : list of str, optional
1103
+ list of observation well names to include
1104
+ label: bool, optional
1105
+ label points, by default True
1106
+ adjust: bool, optional
1107
+ automated smart label placement using adjustText, by default False
1108
+ cmap: str or colormap, optional
1109
+ (name of) the colormap, by default "viridis"
1110
+ norm: norm, optional
1111
+ normalization for colorbar, by default None
1112
+ vmin: float, optional
1113
+ vmin for colorbar, by default None
1114
+ vmax: float, optional
1115
+ vmax for colorbar, by default None
1116
+ ax : matplotlib.Axes, optional
1117
+ axes handle, if not provided a new figure is created.
1118
+ figsize: tuple, optional
1119
+ figuresize, by default(10, 8)
1120
+ backgroundmap: bool, optional
1121
+ if True, add background map (default CRS is EPSG:28992) with default tiles
1122
+ by OpenStreetMap.Mapnik. Default option is False.
1123
+ progressbar: bool, optional
1124
+ show progressbar, default is True
1125
+
1126
+ Returns
1127
+ -------
1128
+ ax: matplotlib.Axes
1129
+ axes object
1130
+
1131
+ See Also
1132
+ --------
1133
+ self.add_background_map
1134
+ """
1135
+ signature_df = self.pstore.get_signatures(
1136
+ [signature],
1137
+ names=names,
1138
+ progressbar=progressbar,
1139
+ ignore_errors=True,
1140
+ )
1141
+ df = signature_df.join(self.pstore.oseries, how="left")
1142
+
1143
+ return self._map_helper(
1144
+ df,
1145
+ column=signature,
1146
+ label=label,
1147
+ adjust=adjust,
1148
+ cmap=cmap,
1149
+ norm=norm,
1150
+ vmin=vmin,
1151
+ vmax=vmax,
1152
+ figsize=figsize,
1153
+ backgroundmap=backgroundmap,
1154
+ **kwargs,
1155
+ )
903
1156
 
904
1157
  @staticmethod
905
1158
  def _plotmap_dataframe(
@@ -949,6 +1202,7 @@ class Maps:
949
1202
  if ax is None:
950
1203
  return_scatter = False
951
1204
  fig, ax = plt.subplots(figsize=figsize)
1205
+ ax.set_aspect("equal", adjustable="box")
952
1206
  else:
953
1207
  return_scatter = True
954
1208
  fig = ax.figure
@@ -1011,8 +1265,8 @@ class Maps:
1011
1265
  label: bool, optional, default is True
1012
1266
  add labels to points on map
1013
1267
  metadata_source: str, optional
1014
- whether to obtain metadata from model Timeseries or from
1015
- metadata in pastastore("store"), default is "model"
1268
+ one of "model" or "store", pick whether to obtain metadata from model
1269
+ Timeseries or from metadata in pastastore, default is "model"
1016
1270
  offset : float, optional
1017
1271
  add offset to current extent of model time series, useful
1018
1272
  for zooming out around models
@@ -1053,7 +1307,7 @@ class Maps:
1053
1307
  yi = imeta.pop("y", np.nan)
1054
1308
  else:
1055
1309
  raise ValueError(
1056
- "metadata_source must be either " "'model' or 'store'!"
1310
+ "metadata_source must be either 'model' or 'store'!"
1057
1311
  )
1058
1312
  if np.isnan(xi) or np.isnan(yi):
1059
1313
  print(f"No x,y-data for {istress.name}!")
@@ -1062,7 +1316,7 @@ class Maps:
1062
1316
  print(f"x,y-data is 0.0 for {istress.name}, not plotting!")
1063
1317
  continue
1064
1318
 
1065
- stresses.loc[istress.name, :] = (xi, yi, name, f"C{count%10}")
1319
+ stresses.loc[istress.name, :] = (xi, yi, name, f"C{count % 10}")
1066
1320
  count += 1
1067
1321
 
1068
1322
  # create figure
@@ -1083,7 +1337,7 @@ class Maps:
1083
1337
  xm = float(ometa.pop("x", np.nan))
1084
1338
  ym = float(ometa.pop("y", np.nan))
1085
1339
  else:
1086
- raise ValueError("metadata_source must be either " "'model' or 'store'!")
1340
+ raise ValueError("metadata_source must be either 'model' or 'store'!")
1087
1341
 
1088
1342
  po = ax.scatter(xm, ym, s=osize, marker="o", label=oserieslabel, color="k")
1089
1343
  legend_list = [po]
@@ -1250,14 +1504,14 @@ class Maps:
1250
1504
  if np.isin(st.loc[s, "kind"], kinds):
1251
1505
  (c,) = np.where(skind == st.loc[s, "kind"])
1252
1506
  if color_lines:
1253
- color = f"C{c[0]+1}"
1507
+ color = f"C{c[0] + 1}"
1254
1508
  else:
1255
1509
  color = "k"
1256
1510
  segments.append(
1257
1511
  [[os["x"], os["y"]], [st.loc[s, "x"], st.loc[s, "y"]]]
1258
1512
  )
1259
1513
  segment_colors.append(color)
1260
- scatter_colors.append(f"C{c[0]+1}")
1514
+ scatter_colors.append(f"C{c[0] + 1}")
1261
1515
 
1262
1516
  stused = np.append(stused, s)
1263
1517
 
@@ -1294,7 +1548,7 @@ class Maps:
1294
1548
  [],
1295
1549
  marker="o",
1296
1550
  color="w",
1297
- markerfacecolor=f"C{c[0]+1}",
1551
+ markerfacecolor=f"C{c[0] + 1}",
1298
1552
  label=kind,
1299
1553
  markersize=10,
1300
1554
  )