pastastore 1.2.1__py3-none-any.whl → 1.3.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/__init__.py CHANGED
@@ -1,10 +1,11 @@
1
- from . import connectors, util
2
- from .connectors import (
1
+ # ruff: noqa: F401
2
+ from pastastore import connectors, util
3
+ from pastastore.connectors import (
3
4
  ArcticConnector,
4
5
  ArcticDBConnector,
5
6
  DictConnector,
6
7
  PasConnector,
7
8
  PystoreConnector,
8
9
  )
9
- from .store import PastaStore
10
- from .version import __version__
10
+ from pastastore.store import PastaStore
11
+ from pastastore.version import __version__
pastastore/base.py CHANGED
@@ -11,10 +11,10 @@ import pastas as ps
11
11
  from numpy import isin
12
12
  from packaging.version import parse as parse_version
13
13
  from pastas.io.pas import PastasEncoder
14
- from tqdm import tqdm
14
+ from tqdm.auto import tqdm
15
15
 
16
- from .util import ItemInLibraryException, _custom_warning, validate_names
17
- from .version import PASTAS_LEQ_022
16
+ from pastastore.util import ItemInLibraryException, _custom_warning, validate_names
17
+ from pastastore.version import PASTAS_LEQ_022
18
18
 
19
19
  FrameorSeriesUnion = Union[pd.DataFrame, pd.Series]
20
20
  warnings.showwarning = _custom_warning
@@ -934,13 +934,24 @@ class BaseConnector(ABC):
934
934
  )
935
935
  if ui.lower() != "y":
936
936
  return
937
- names = self._parse_names(None, libname)
938
- for name in (
939
- tqdm(names, desc=f"Deleting items from {libname}") if progressbar else names
940
- ):
941
- self._del_item(libname, name)
942
- self._clear_cache(libname)
943
- print(f"Emptied library {libname} in {self.name}: " f"{self.__class__}")
937
+
938
+ if libname == "models":
939
+ # also delete linked modelnames linked to oseries
940
+ libs = ["models", "oseries_models"]
941
+ else:
942
+ libs = [libname]
943
+
944
+ # delete items and clear caches
945
+ for libname in libs:
946
+ names = self._parse_names(None, libname)
947
+ for name in (
948
+ tqdm(names, desc=f"Deleting items from {libname}")
949
+ if progressbar
950
+ else names
951
+ ):
952
+ self._del_item(libname, name)
953
+ self._clear_cache(libname)
954
+ print(f"Emptied library {libname} in {self.name}: " f"{self.__class__}")
944
955
 
945
956
  def _iter_series(self, libname: str, names: Optional[List[str]] = None):
946
957
  """Internal method iterate over time series in library.
pastastore/connectors.py CHANGED
@@ -8,8 +8,8 @@ from typing import Dict, Optional, Union
8
8
  import pandas as pd
9
9
  from pastas.io.pas import PastasEncoder, pastas_hook
10
10
 
11
- from .base import BaseConnector, ConnectorUtil, ModelAccessor
12
- from .util import _custom_warning
11
+ from pastastore.base import BaseConnector, ConnectorUtil, ModelAccessor
12
+ from pastastore.util import _custom_warning
13
13
 
14
14
  FrameorSeriesUnion = Union[pd.DataFrame, pd.Series]
15
15
  warnings.showwarning = _custom_warning
pastastore/datasets.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
 
3
- import hydropandas as hpd
4
3
  import pandas as pd
4
+ from hydropandas import Obs, ObsCollection
5
5
 
6
6
  try:
7
7
  from pastas.timeseries_utils import timestep_weighted_resample
@@ -114,7 +114,7 @@ def example_pastastore(conn="DictConnector"):
114
114
  # multiwell notebook data
115
115
  fname = os.path.join(datadir, "MenyanthesTest.men")
116
116
  # meny = ps.read.MenyData(fname)
117
- meny = hpd.ObsCollection.from_menyanthes(fname, hpd.Obs)
117
+ meny = ObsCollection.from_menyanthes(fname, Obs)
118
118
 
119
119
  oseries = meny.loc["Obsevation well", "obs"]
120
120
  ometa = {
pastastore/plotting.py CHANGED
@@ -14,9 +14,6 @@ follows::
14
14
  ax = pstore.maps.oseries()
15
15
  pstore.maps.add_background_map(ax) # for adding a background map
16
16
  """
17
-
18
- from collections.abc import Iterable
19
-
20
17
  import matplotlib.pyplot as plt
21
18
  import numpy as np
22
19
  import pandas as pd
@@ -96,15 +93,11 @@ class Plots:
96
93
 
97
94
  if ax is None:
98
95
  if split:
99
- fig, axes = plt.subplots(len(names), 1, sharex=True, figsize=figsize)
96
+ _, axes = plt.subplots(len(names), 1, sharex=True, figsize=figsize)
100
97
  else:
101
- fig, axes = plt.subplots(1, 1, figsize=figsize)
98
+ _, axes = plt.subplots(1, 1, figsize=figsize)
102
99
  else:
103
100
  axes = ax
104
- if isinstance(axes, Iterable):
105
- fig = axes[0].figure
106
- else:
107
- fig = axes.figure
108
101
 
109
102
  tsdict = self.pstore.conn._get_series(
110
103
  libname, names, progressbar=progressbar, squeeze=False
@@ -123,7 +116,6 @@ class Plots:
123
116
  if not split:
124
117
  axes.legend(loc=(0, 1), frameon=False, ncol=7, fontsize="x-small")
125
118
 
126
- fig.tight_layout()
127
119
  return axes
128
120
 
129
121
  def oseries(self, names=None, ax=None, split=False, figsize=(10, 5), **kwargs):
@@ -398,20 +390,31 @@ class Plots:
398
390
  linewidth=0,
399
391
  rasterized=True,
400
392
  )
393
+
401
394
  # make a colorbar in an ax on the
402
395
  # right side, then set the current axes to ax again
403
396
  cb = fig.colorbar(pc, ax=ax, cax=cax, extend="both")
404
397
  cb.set_ticks(bounds)
405
398
  cb.ax.set_yticklabels(labels)
406
399
  cb.ax.minorticks_off()
400
+
407
401
  if set_yticks:
408
- ax.set_yticks(np.arange(0.5, len(series) + 0.5))
402
+ ax.set_yticks(np.arange(0.5, len(series) + 0.5), minor=False)
403
+ ax.set_yticks(np.arange(0, len(series) + 1), minor=True)
409
404
  if names is None:
410
405
  names = [s.name for s in series]
411
406
  ax.set_yticklabels(names)
407
+
408
+ for tick in ax.yaxis.get_major_ticks(): # don't show major ytick marker
409
+ tick.tick1line.set_visible(False)
410
+
411
+ ax.grid(True, which="minor", axis="y")
412
+ ax.grid(True, which="major", axis="x")
413
+
412
414
  else:
413
415
  ax.set_ylabel("Timeseries (-)")
414
- ax.grid()
416
+ ax.grid(True, which="both")
417
+ ax.grid(True, which="both")
415
418
 
416
419
  return ax
417
420
 
@@ -713,6 +716,7 @@ class Maps:
713
716
  def modelstat(
714
717
  self,
715
718
  statistic,
719
+ modelnames=None,
716
720
  label=True,
717
721
  adjust=False,
718
722
  cmap="viridis",
@@ -729,6 +733,8 @@ class Maps:
729
733
  ----------
730
734
  statistic: str
731
735
  name of the statistic, e.g. "evp" or "aic"
736
+ modelnames : list of str, optional
737
+ list of modelnames to include
732
738
  label: bool, optional
733
739
  label points, by default True
734
740
  adjust: bool, optional
@@ -758,7 +764,9 @@ class Maps:
758
764
  --------
759
765
  self.add_background_map
760
766
  """
761
- statsdf = self.pstore.get_statistics([statistic], progressbar=False).to_frame()
767
+ statsdf = self.pstore.get_statistics(
768
+ [statistic], modelnames=modelnames, progressbar=False
769
+ ).to_frame()
762
770
 
763
771
  statsdf["oseries"] = [
764
772
  self.pstore.get_models(m, return_dict=True)["oseries"]["name"]
@@ -1268,13 +1276,21 @@ class Maps:
1268
1276
  """
1269
1277
  stroke = [patheffects.withStroke(linewidth=3, foreground="w")]
1270
1278
 
1279
+ fontsize = kwargs.pop("fontsize", 10)
1280
+
1271
1281
  if adjust:
1272
1282
  from adjustText import adjust_text
1273
1283
 
1274
1284
  texts = []
1275
1285
  for name, row in df.iterrows():
1276
1286
  texts.append(
1277
- ax.text(row["x"], row["y"], name, **{"path_effects": stroke})
1287
+ ax.text(
1288
+ row["x"],
1289
+ row["y"],
1290
+ name,
1291
+ fontsize=fontsize,
1292
+ **{"path_effects": stroke},
1293
+ )
1278
1294
  )
1279
1295
 
1280
1296
  adjust_text(
@@ -1290,7 +1306,6 @@ class Maps:
1290
1306
  )
1291
1307
 
1292
1308
  else:
1293
- fontsize = kwargs.pop("fontsize", 10)
1294
1309
  textcoords = kwargs.pop("textcoords", "offset points")
1295
1310
  xytext = kwargs.pop("xytext", (10, 10))
1296
1311
 
pastastore/store.py CHANGED
@@ -8,11 +8,13 @@ import pandas as pd
8
8
  import pastas as ps
9
9
  from packaging.version import parse as parse_version
10
10
  from pastas.io.pas import pastas_hook
11
- from tqdm import tqdm
11
+ from tqdm.auto import tqdm
12
12
 
13
- from .plotting import Maps, Plots
14
- from .util import _custom_warning
15
- from .yaml_interface import PastastoreYAML
13
+ from pastastore.base import BaseConnector
14
+ from pastastore.connectors import DictConnector
15
+ from pastastore.plotting import Maps, Plots
16
+ from pastastore.util import _custom_warning
17
+ from pastastore.yaml_interface import PastastoreYAML
16
18
 
17
19
  FrameorSeriesUnion = Union[pd.DataFrame, pd.Series]
18
20
  warnings.showwarning = _custom_warning
@@ -38,14 +40,19 @@ class PastaStore:
38
40
  name of the PastaStore, by default takes the name of the Connector object
39
41
  """
40
42
 
41
- def __init__(self, connector, name: str = None):
43
+ def __init__(
44
+ self,
45
+ connector: Optional[BaseConnector] = None,
46
+ name: Optional[str] = None,
47
+ ):
42
48
  """Initialize PastaStore for managing pastas time series and models.
43
49
 
44
50
  Parameters
45
51
  ----------
46
- connector : Connector object
47
- object that provides the interface to the
48
- database
52
+ connector : Connector object, optional
53
+ object that provides the connection to the database. Default is None, which
54
+ will create a DictConnector. This default Connector does not store data on
55
+ disk.
49
56
  name : str, optional
50
57
  name of the PastaStore, if not provided uses the Connector name
51
58
  """
@@ -53,6 +60,8 @@ class PastaStore:
53
60
  raise DeprecationWarning(
54
61
  "PastaStore expects the connector as the first argument since v1.1!"
55
62
  )
63
+ if connector is None:
64
+ connector = DictConnector("pastas_db")
56
65
  self.conn = connector
57
66
  self.name = name if name is not None else self.conn.name
58
67
  self._register_connector_methods()
@@ -300,6 +309,81 @@ class PastaStore:
300
309
  data = pd.concat([data, series], axis=0)
301
310
  return data
302
311
 
312
+ def get_signatures(
313
+ self,
314
+ signatures=None,
315
+ names=None,
316
+ libname="oseries",
317
+ progressbar=False,
318
+ ignore_errors=False,
319
+ ):
320
+ """Get groundwater signatures. NaN-values are returned when the
321
+ signature could not be computed.
322
+
323
+ Parameters
324
+ ----------
325
+ signatures : list of str, optional
326
+ list of groundwater signatures to compute, if None all groundwater
327
+ signatures in ps.stats.signatures.__all__ are used, by default None
328
+ names : str, list of str, or None, optional
329
+ names of the time series, by default None which
330
+ uses all the time series in the library
331
+ libname : str
332
+ name of the library containing the time series
333
+ ('oseries' or 'stresses'), by default "oseries"
334
+ progressbar : bool, optional
335
+ show progressbar, by default False
336
+ ignore_errors : bool, optional
337
+ ignore errors when True, i.e. when non-existent timeseries is
338
+ encountered in names, by default False
339
+
340
+ Returns
341
+ -------
342
+ signatures_df : pandas.DataFrame
343
+ DataFrame containing the signatures (columns) per time series (rows)
344
+ """
345
+ names = self.conn._parse_names(names, libname=libname)
346
+
347
+ if signatures is None:
348
+ signatures = ps.stats.signatures.__all__.copy()
349
+
350
+ # create dataframe for results
351
+ signatures_df = pd.DataFrame(index=names, columns=signatures, data=np.nan)
352
+
353
+ # loop through oseries names
354
+ desc = "Get groundwater signatures"
355
+ for name in tqdm(names, desc=desc) if progressbar else names:
356
+ try:
357
+ if libname == "oseries":
358
+ s = self.conn.get_oseries(name)
359
+ else:
360
+ s = self.conn.get_stresses(name)
361
+ except Exception as e:
362
+ if ignore_errors:
363
+ signatures_df.loc[name, :] = np.nan
364
+ continue
365
+ else:
366
+ raise e
367
+
368
+ try:
369
+ i_signatures = ps.stats.signatures.summary(s.squeeze(), signatures)
370
+ except Exception as e:
371
+ if ignore_errors:
372
+ i_signatures = []
373
+ for signature in signatures:
374
+ try:
375
+ sign_val = getattr(ps.stats.signatures, signature)(
376
+ s.squeeze()
377
+ )
378
+ except Exception as _:
379
+ sign_val = np.nan
380
+ i_signatures.append(sign_val)
381
+ else:
382
+ raise e
383
+ signatures_df.loc[name, signatures] = i_signatures
384
+
385
+ return signatures_df
386
+
303
387
  def get_tmin_tmax(self, libname, names=None, progressbar=False):
304
388
  """Get tmin and tmax for time series.
305
389
 
@@ -334,6 +418,23 @@ class PastaStore:
334
418
  tmintmax.loc[n, "tmax"] = s.last_valid_index()
335
419
  return tmintmax
336
420
 
421
+ def get_extent(self, libname, names=None, buffer=0.0):
422
+ names = self.conn._parse_names(names, libname=libname)
423
+ if libname in ["oseries", "stresses"]:
424
+ df = getattr(self, libname)
425
+ elif libname == "models":
426
+ df = self.oseries
427
+ else:
428
+ raise ValueError(f"Cannot get extent for library '{libname}'.")
429
+
430
+ extent = [
431
+ df.loc[names, "x"].min() - buffer,
432
+ df.loc[names, "x"].max() + buffer,
433
+ df.loc[names, "y"].min() - buffer,
434
+ df.loc[names, "y"].max() + buffer,
435
+ ]
436
+ return extent
437
+
337
438
  def get_parameters(
338
439
  self,
339
440
  parameters: Optional[List[str]] = None,
@@ -428,13 +529,13 @@ class PastaStore:
428
529
 
429
530
  modelnames = self.conn._parse_names(modelnames, libname="models")
430
531
 
431
- # create dataframe for results
432
- s = pd.DataFrame(index=modelnames, columns=statistics, data=np.nan)
433
-
434
532
  # if statistics is str
435
533
  if isinstance(statistics, str):
436
534
  statistics = [statistics]
437
535
 
536
+ # create dataframe for results
537
+ s = pd.DataFrame(index=modelnames, columns=statistics, data=np.nan)
538
+
438
539
  # loop through model names
439
540
  desc = "Get model statistics"
440
541
  for mlname in tqdm(modelnames, desc=desc) if progressbar else modelnames:
@@ -836,7 +937,7 @@ class PastaStore:
836
937
  def from_zip(
837
938
  cls,
838
939
  fname: str,
839
- conn,
940
+ conn: Optional[BaseConnector] = None,
840
941
  storename: Optional[str] = None,
841
942
  progressbar: bool = True,
842
943
  ):
@@ -846,8 +947,9 @@ class PastaStore:
846
947
  ----------
847
948
  fname : str
848
949
  pathname of zipfile
849
- conn : Connector object
850
- connector for storing loaded data
950
+ conn : Connector object, optional
951
+ connector for storing loaded data, default is None which creates a
952
+ DictConnector. This Connector does not store data on disk.
851
953
  storename : str, optional
852
954
  name of the PastaStore, by default None, which
853
955
  defaults to the name of the Connector.
@@ -861,6 +963,9 @@ class PastaStore:
861
963
  """
862
964
  from zipfile import ZipFile
863
965
 
966
+ if conn is None:
967
+ conn = DictConnector("pastas_db")
968
+
864
969
  with ZipFile(fname, "r") as archive:
865
970
  namelist = [
866
971
  fi for fi in archive.namelist() if not fi.endswith("_meta.json")
@@ -868,7 +973,7 @@ class PastaStore:
868
973
  for f in tqdm(namelist, desc="Reading zip") if progressbar else namelist:
869
974
  libname, fjson = os.path.split(f)
870
975
  if libname in ["stresses", "oseries"]:
871
- s = pd.read_json(archive.open(f), orient="columns")
976
+ s = pd.read_json(archive.open(f), dtype=float, orient="columns")
872
977
  if not isinstance(s.index, pd.DatetimeIndex):
873
978
  s.index = pd.to_datetime(s.index, unit="ms")
874
979
  s = s.sort_index()
@@ -983,9 +1088,45 @@ class PastaStore:
983
1088
  structure.loc[mlnam, pnam] = 1
984
1089
  structure.loc[mlnam, enam] = 1
985
1090
  elif "stress" in sm:
986
- for s in sm["stress"]:
1091
+ smstress = sm["stress"]
1092
+ if isinstance(smstress, dict):
1093
+ smstress = [smstress]
1094
+ for s in smstress:
987
1095
  structure.loc[mlnam, s["name"]] = 1
988
1096
  if dropna:
989
1097
  return structure.dropna(how="all", axis=1)
990
1098
  else:
991
1099
  return structure
1100
+
1101
+ def apply(self, libname, func, names=None, progressbar=True):
1102
+ """Apply function to items in library.
1103
+
1104
+ Supported libraries are oseries, stresses, and models.
1105
+
1106
+ Parameters
1107
+ ----------
1108
+ libname : str
1109
+ library name, supports "oseries", "stresses" and "models"
1110
+ func : callable
1111
+ function that accepts items from one of the supported libraries as input
1112
+ names : str, list of str, optional
1113
+ apply function to these names, by default None which loops over all stored
1114
+ items in library
1115
+ progressbar : bool, optional
1116
+ show progressbar, by default True
1117
+
1118
+ Returns
1119
+ -------
1120
+ dict
1121
+ dict of results of func, with names as keys and results as values
1122
+ """
1123
+ names = self.conn._parse_names(names, libname)
1124
+ result = {}
1125
+ if libname not in ("oseries", "stresses", "models"):
1126
+ raise ValueError(
1127
+ "'libname' must be one of ['oseries', 'stresses', 'models']!"
1128
+ )
1129
+ getter = getattr(self.conn, f"get_{libname}")
1130
+ for n in tqdm(names) if progressbar else names:
1131
+ result[n] = func(getter(n))
1132
+ return result
pastastore/util.py CHANGED
@@ -6,9 +6,9 @@ import pandas as pd
6
6
  from numpy.lib._iotools import NameValidator
7
7
  from pandas.testing import assert_series_equal
8
8
  from pastas.stats.tests import runs_test, stoffer_toloi
9
- from tqdm import tqdm
9
+ from tqdm.auto import tqdm
10
10
 
11
- from .version import PASTAS_LEQ_022
11
+ from pastastore.version import PASTAS_LEQ_022
12
12
 
13
13
 
14
14
  def _custom_warning(message, category=UserWarning, filename="", lineno=-1, *args):
@@ -684,7 +684,7 @@ def frontiers_checks(
684
684
  if check3_tmem:
685
685
  len_oseries_calib = (ml.settings["tmax"] - ml.settings["tmin"]).days
686
686
  for sm_name, sm in ml.stressmodels.items():
687
- if sm_name.startswith("wells"):
687
+ if sm._name == "WellModel":
688
688
  nwells = sm.distances.index.size
689
689
  for iw in range(nwells):
690
690
  p = sm.get_parameters(model=ml, istress=iw)
@@ -704,6 +704,8 @@ def frontiers_checks(
704
704
  )
705
705
  else:
706
706
  tmem = ml.get_response_tmax(sm_name)
707
+ if tmem is None: # no rfunc in stressmodel
708
+ tmem = 0
707
709
  check_tmem_passed = tmem < len_oseries_calib / 2
708
710
  checks.loc[f"calib_period > 2*t_mem_95%: {sm_name}", :] = (
709
711
  tmem,
@@ -715,24 +717,7 @@ def frontiers_checks(
715
717
  # Check 4 - Uncertainty Gain
716
718
  if check4_gain:
717
719
  for sm_name, sm in ml.stressmodels.items():
718
- if sm_name.startswith("wells"):
719
- p = ml.get_parameters(sm_name)
720
- gain = sm.rfunc.gain(p)
721
- A = ml.parameters.loc[f"{sm_name}_A", "optimal"]
722
- b = ml.parameters.loc[f"{sm_name}_b", "optimal"]
723
- var_A = ml.parameters.loc[f"{sm_name}_A", "stderr"] ** 2
724
- var_b = ml.parameters.loc[f"{sm_name}_b", "stderr"] ** 2
725
- cov_Ab = ml.fit.pcov.loc[f"{sm_name}_A", f"{sm_name}_b"]
726
- gain_std = np.sqrt(
727
- sm.rfunc.variance_gain(A, b, var_A, var_b, cov_Ab)
728
- )
729
- if gain_std is None:
730
- gain_std = np.nan
731
- check_gain_passed = pd.NA
732
- elif np.isnan(gain_std):
733
- check_gain_passed = pd.NA
734
- else:
735
- check_gain_passed = np.abs(gain) > 2 * gain_std
720
+ if sm._name == "WellModel":
736
721
  for iw in range(sm.distances.index.size):
737
722
  p = sm.get_parameters(model=ml, istress=iw)
738
723
  gain = sm.rfunc.gain(p)
@@ -753,23 +738,30 @@ def frontiers_checks(
753
738
  "(unit head)/(unit well stress)",
754
739
  check_gain_passed,
755
740
  )
741
+ continue
742
+ elif sm._name == "LinearTrend":
743
+ gain = ml.parameters.loc[f"{sm_name}_a", "optimal"]
744
+ gain_std = ml.parameters.loc[f"{sm_name}_a", "stderr"]
745
+ elif sm._name == "StepModel":
746
+ gain = ml.parameters.loc[f"{sm_name}_d", "optimal"]
747
+ gain_std = ml.parameters.loc[f"{sm_name}_d", "stderr"]
756
748
  else:
757
749
  gain = ml.parameters.loc[f"{sm_name}_A", "optimal"]
758
750
  gain_std = ml.parameters.loc[f"{sm_name}_A", "stderr"]
759
- if gain_std is None:
760
- gain_std = np.nan
761
- check_gain_passed = pd.NA
762
- elif np.isnan(gain_std):
763
- check_gain_passed = pd.NA
764
- else:
765
- check_gain_passed = np.abs(gain) > 2 * gain_std
751
+
752
+ if gain_std is None:
753
+ gain_std = np.nan
754
+ check_gain_passed = pd.NA
755
+ elif np.isnan(gain_std):
756
+ check_gain_passed = pd.NA
757
+ else:
766
758
  check_gain_passed = np.abs(gain) > 2 * gain_std
767
- checks.loc[f"gain > 2*std: {sm_name}", :] = (
768
- gain,
769
- 2 * gain_std,
770
- "(unit head)/(unit well stress)",
771
- check_gain_passed,
772
- )
759
+ checks.loc[f"gain > 2*std: {sm_name}", :] = (
760
+ gain,
761
+ 2 * gain_std,
762
+ "(unit head)/(unit well stress)",
763
+ check_gain_passed,
764
+ )
773
765
 
774
766
  # Check 5 - Parameter Bounds
775
767
  if check5_parambounds:
pastastore/version.py CHANGED
@@ -4,4 +4,4 @@ from packaging.version import parse as parse_version
4
4
  PASTAS_VERSION = parse_version(ps.__version__)
5
5
  PASTAS_LEQ_022 = PASTAS_VERSION <= parse_version("0.22.0")
6
6
 
7
- __version__ = "1.2.1"
7
+ __version__ = "1.3.0"
@@ -2,14 +2,14 @@ import datetime
2
2
  import logging
3
3
  import os
4
4
  from copy import deepcopy
5
- from typing import Dict, List, Optional, Union
5
+ from typing import Any, Dict, List, Optional, Union
6
6
 
7
7
  import numpy as np
8
8
  import pandas as pd
9
9
  import pastas as ps
10
10
  import yaml
11
11
 
12
- from .version import PASTAS_LEQ_022
12
+ from pastastore.version import PASTAS_LEQ_022
13
13
 
14
14
  ps.logger.setLevel("ERROR")
15
15
 
@@ -17,7 +17,7 @@ logging.basicConfig(level="INFO")
17
17
  logger = logging.getLogger(__name__)
18
18
 
19
19
 
20
- def _convert_dict_dtypes_for_yaml(d: Dict):
20
+ def _convert_dict_dtypes_for_yaml(d: Dict[str, Any]):
21
21
  """Internal method to convert dictionary values for storing in YAML format.
22
22
 
23
23
  Parameters
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pastastore
3
- Version: 1.2.1
3
+ Version: 1.3.0
4
4
  Summary: Tools for managing Pastas time series models.
5
5
  Author: D.A. Brakenhoff
6
6
  Maintainer-email: "D.A. Brakenhoff" <d.brakenhoff@artesia-water.nl>, "R. Calje" <r.calje@artesia-water.nl>, "M.A. Vonk" <m.vonk@artesia-water.nl>
@@ -50,8 +50,8 @@ Classifier: Topic :: Scientific/Engineering :: Hydrology
50
50
  Requires-Python: >=3.7
51
51
  Description-Content-Type: text/markdown
52
52
  License-File: LICENSE
53
- Requires-Dist: pastas (>=0.13)
54
- Requires-Dist: tqdm (>=4.36)
53
+ Requires-Dist: pastas >=0.13
54
+ Requires-Dist: tqdm >=4.36
55
55
  Requires-Dist: pyyaml
56
56
  Provides-Extra: arctic
57
57
  Requires-Dist: arctic ; extra == 'arctic'
@@ -64,6 +64,8 @@ Requires-Dist: Ipython ; extra == 'docs'
64
64
  Requires-Dist: ipykernel ; extra == 'docs'
65
65
  Requires-Dist: nbsphinx ; extra == 'docs'
66
66
  Requires-Dist: nbsphinx-link ; extra == 'docs'
67
+ Provides-Extra: full
68
+ Requires-Dist: pastastore[arcticdb,optional] ; extra == 'full'
67
69
  Provides-Extra: lint
68
70
  Requires-Dist: black ; extra == 'lint'
69
71
  Requires-Dist: flake8 ; extra == 'lint'
@@ -73,12 +75,12 @@ Requires-Dist: contextily ; extra == 'optional'
73
75
  Requires-Dist: pyproj ; extra == 'optional'
74
76
  Requires-Dist: adjustText ; extra == 'optional'
75
77
  Provides-Extra: pystore
76
- Requires-Dist: fsspec (>=0.3.3) ; extra == 'pystore'
78
+ Requires-Dist: fsspec >=0.3.3 ; extra == 'pystore'
77
79
  Requires-Dist: python-snappy ; extra == 'pystore'
78
80
  Requires-Dist: dask[dataframe] ; extra == 'pystore'
79
81
  Provides-Extra: test
80
82
  Requires-Dist: pastastore[arcticdb,lint,optional] ; extra == 'test'
81
- Requires-Dist: hydropandas ; extra == 'test'
83
+ Requires-Dist: hydropandas[full] ; extra == 'test'
82
84
  Requires-Dist: coverage ; extra == 'test'
83
85
  Requires-Dist: codecov ; extra == 'test'
84
86
  Requires-Dist: pytest ; extra == 'test'
@@ -86,6 +88,7 @@ Requires-Dist: pytest-cov ; extra == 'test'
86
88
  Requires-Dist: pytest-dependency ; extra == 'test'
87
89
  Requires-Dist: pytest-benchmark ; extra == 'test'
88
90
  Requires-Dist: codacy-coverage ; extra == 'test'
91
+ Requires-Dist: lxml ; extra == 'test'
89
92
 
90
93
  ![pastastore](https://github.com/pastas/pastastore/workflows/pastastore/badge.svg)
91
94
  [![Documentation Status](https://readthedocs.org/projects/pastastore/badge/?version=latest)](https://pastastore.readthedocs.io/en/latest/?badge=latest)
@@ -0,0 +1,14 @@
1
+ pastastore/__init__.py,sha256=GZvAtp_p3y2bOlcuLG2-jSHrYd72bIMDdBA5Wcy-diU,283
2
+ pastastore/base.py,sha256=nPIIiDHJMDUlvPaE2dftjPRxAM2kFtC8kHXvmB9Ayw0,62631
3
+ pastastore/connectors.py,sha256=QH6jvnhIIivn1Is9ThBeMAEcJBVnfcK46pJClGMdiBA,28747
4
+ pastastore/datasets.py,sha256=f-92WOh2ROCxOVvKGHXjnzd66Q7hO_-BtXRfMKwg1KU,6640
5
+ pastastore/plotting.py,sha256=3WTnnOfFZlt4PEsqDzNLFzFOJBtDb0vmwx4ZzdZI_xo,42120
6
+ pastastore/store.py,sha256=vIPnq-XYU-HstweWa4RSuNHotYLTBNVQjljt6SH9fWY,39529
7
+ pastastore/util.py,sha256=aVIrAtfJPatH7BfASChzwHsoug1KDthcgHlEbxl1-uk,30678
8
+ pastastore/version.py,sha256=JXttE_aGZnNgRq0bbXfNL4jCLuHlFt9gD0xf0G99owU,203
9
+ pastastore/yaml_interface.py,sha256=yNpyEHtIapx44Thv2PCm7Sc_W-reXDHjT3uRC2gDAzw,29515
10
+ pastastore-1.3.0.dist-info/LICENSE,sha256=DtHftfUEm99KzgwLr3rQUTg8H3kAS0Z-p5WWJgLf_OY,1082
11
+ pastastore-1.3.0.dist-info/METADATA,sha256=gXxIFp2Ge_pHkDPc0qfuI2wiNQGUZUSOSMWavKWQ8Fo,7844
12
+ pastastore-1.3.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
13
+ pastastore-1.3.0.dist-info/top_level.txt,sha256=QKfonr1KJZN46MFsj8eGRBw9Mg-jO-HFvgE2orVX7Sk,11
14
+ pastastore-1.3.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.40.0)
2
+ Generator: bdist_wheel (0.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,14 +0,0 @@
1
- pastastore/__init__.py,sha256=1janwX-BqYJobFi0dvVNW-zTnCUba_jxkBcT2pRj4fg,225
2
- pastastore/base.py,sha256=CHg7mKkdaQGTvQdVnbaPK6WslKZjkYhMMs84nrmMxvs,62290
3
- pastastore/connectors.py,sha256=riiSPX_N6Tcmn-_jQgDbw32hkq1iGLLHcH0U9wueMG8,28727
4
- pastastore/datasets.py,sha256=hg-HPAWG1pdFwt_FaXGOrbwF7QORcFrKj54t8L5htog,6631
5
- pastastore/plotting.py,sha256=RDj48TxVLfjF3cnd5CgzsP68Heg8RAJphEcI3srM75U,41622
6
- pastastore/store.py,sha256=gqr1qi9sdUlmSQfkn3CC-ZKmqOro7bUw0-E-VlZRads,34126
7
- pastastore/util.py,sha256=HJ8O6Xcd0Zg3rG51b637Uobkkbw5vgie6bDdGPjRA94,31203
8
- pastastore/version.py,sha256=yC-mZTJkCs0p4e12ha8VOsQ0BiogUULca9rg5g8Hfzg,203
9
- pastastore/yaml_interface.py,sha256=9nep4ALV9IomAeVuaafsPzlGDcmi6gL0rNHAjHiPbMc,29490
10
- pastastore-1.2.1.dist-info/LICENSE,sha256=DtHftfUEm99KzgwLr3rQUTg8H3kAS0Z-p5WWJgLf_OY,1082
11
- pastastore-1.2.1.dist-info/METADATA,sha256=wJQYPumQ2OZq-X2Bl5AxawsBEL8v4GEGSLDG6bXyon4,7722
12
- pastastore-1.2.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
13
- pastastore-1.2.1.dist-info/top_level.txt,sha256=QKfonr1KJZN46MFsj8eGRBw9Mg-jO-HFvgE2orVX7Sk,11
14
- pastastore-1.2.1.dist-info/RECORD,,