hydrotoolbox 2.3.0__tar.gz → 2.3.2__tar.gz

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.
Files changed (124) hide show
  1. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.gitmodules +2 -1
  2. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/CHANGELOG.md +8 -0
  3. {hydrotoolbox-2.3.0/src/hydrotoolbox.egg-info → hydrotoolbox-2.3.2}/PKG-INFO +1 -1
  4. hydrotoolbox-2.3.2/VERSION +1 -0
  5. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/pyproject.toml +1 -1
  6. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/readers/wdm.py +4 -2
  7. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/tsutils.py +49 -50
  8. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/utils.py +1 -1
  9. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_read.py +0 -1
  10. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_wdm.py +18 -17
  11. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2/src/hydrotoolbox.egg-info}/PKG-INFO +1 -1
  12. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox.egg-info/SOURCES.txt +0 -1
  13. hydrotoolbox-2.3.0/VERSION +0 -1
  14. hydrotoolbox-2.3.0/pytest.ini +0 -2
  15. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.deepsource.toml +0 -0
  16. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.github/dependabot.yml +0 -0
  17. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.github/workflows/clean-workflow-runs.yml +0 -0
  18. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.github/workflows/pypi-package.yml +0 -0
  19. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.github/workflows/tests.yml +0 -0
  20. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.gitignore +0 -0
  21. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.pre-commit-config.yaml +0 -0
  22. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/.sourcery.yaml +0 -0
  23. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/AUTHORS.rst +0 -0
  24. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/BADGES.rst +0 -0
  25. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/CONTRIBUTING.rst +0 -0
  26. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/LICENSE.txt +0 -0
  27. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/README.rst +0 -0
  28. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/Makefile +0 -0
  29. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/authors.rst +0 -0
  30. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/command_line.rst +0 -0
  31. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/conf.py +0 -0
  32. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/contributing.rst +0 -0
  33. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/function_summary.rst +0 -0
  34. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/index.rst +0 -0
  35. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/license.rst +0 -0
  36. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/make.bat +0 -0
  37. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/docs/readme.rst +0 -0
  38. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/setup.cfg +0 -0
  39. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/__init__.py +0 -0
  40. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/__init__.py +0 -0
  41. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/comparison.py +0 -0
  42. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/example.csv +0 -0
  43. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/__init__.py +0 -0
  44. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/boughton.py +0 -0
  45. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/chapman.py +0 -0
  46. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/chapman_maxwell.py +0 -0
  47. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/eckhardt.py +0 -0
  48. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/ewma.py +0 -0
  49. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/five_day.py +0 -0
  50. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/fixed.py +0 -0
  51. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/furey.py +0 -0
  52. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/general_form.py +0 -0
  53. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/ihacres.py +0 -0
  54. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/local.py +0 -0
  55. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/lyne_hollick.py +0 -0
  56. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/slide.py +0 -0
  57. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/strict.py +0 -0
  58. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/ukih.py +0 -0
  59. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/methods/willems.py +0 -0
  60. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/param_estimate.py +0 -0
  61. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/separation.py +0 -0
  62. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow/utils.py +0 -0
  63. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/baseflow_sep.py +0 -0
  64. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/hydrotoolbox.py +0 -0
  65. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/indices/__init__.py +0 -0
  66. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/indices/indices.py +0 -0
  67. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/docs/conf.py +0 -0
  68. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/__init__.py +0 -0
  69. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/readers/__init__.py +0 -0
  70. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/readers/hbn.py +0 -0
  71. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/readers/plotgen.py +0 -0
  72. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/src/toolbox_utils/readers/utils.py +0 -0
  73. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_asbestfreq.py +0 -0
  74. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_date_slice.py +0 -0
  75. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_dateparse.py +0 -0
  76. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_extract.py +0 -0
  77. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_hbn.py +0 -0
  78. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_make_list.py +0 -0
  79. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_period_timestamp.py +0 -0
  80. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_plotgen.py +0 -0
  81. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/toolbox_utils/tests/test_range_to_numlist.py +0 -0
  82. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox/utils.py +0 -0
  83. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox.egg-info/dependency_links.txt +0 -0
  84. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox.egg-info/entry_points.txt +0 -0
  85. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox.egg-info/requires.txt +0 -0
  86. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/src/hydrotoolbox.egg-info/top_level.txt +0 -0
  87. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/BEC_test.sh +0 -0
  88. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/Q_BEC_BE_6500.csv +0 -0
  89. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/Q_BEC_BE_6500.ssf +0 -0
  90. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/black_earth_creek_05406500_flow.csv +0 -0
  91. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/black_earth_creek_05406500_test.sh +0 -0
  92. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data.csv +0 -0
  93. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_02239501.csv +0 -0
  94. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_boughton.csv +0 -0
  95. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_chapman.csv +0 -0
  96. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_chapman_maxwell.csv +0 -0
  97. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_eckhardt.csv +0 -0
  98. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_ewma.csv +0 -0
  99. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_five_day.csv +0 -0
  100. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_furey.csv +0 -0
  101. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_ihacres.csv +0 -0
  102. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_lyne_hollick.csv +0 -0
  103. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_strict.csv +0 -0
  104. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_ukih.csv +0 -0
  105. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_usgs_hysep_fixed.csv +0 -0
  106. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_usgs_hysep_local.csv +0 -0
  107. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_usgs_hysep_slide.csv +0 -0
  108. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_baseflow_willems.csv +0 -0
  109. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_percentile_test.csv +0 -0
  110. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_short.csv +0 -0
  111. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/data_test_storm_events.csv +0 -0
  112. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/gtable.out +0 -0
  113. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/gtable_1955.out +0 -0
  114. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/hydrotoolbox_indices.txt +0 -0
  115. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/run_test.sh +0 -0
  116. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/test_baseflow_sep.py +0 -0
  117. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/test_exceedance_time.py +0 -0
  118. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/test_flow_duration.py +0 -0
  119. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/test_indices.py +0 -0
  120. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/test_recession.py +0 -0
  121. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/test_storm_events.py +0 -0
  122. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/tsproc_hydrologic_indices.inp +0 -0
  123. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/tsproc_hydrologic_indices.rec +0 -0
  124. {hydrotoolbox-2.3.0 → hydrotoolbox-2.3.2}/tests/tsproc_hydrologic_indices_percentile_test.inp +0 -0
@@ -1,3 +1,4 @@
1
1
  [submodule "src/hydrotoolbox/toolbox_utils"]
2
2
  path = src/hydrotoolbox/toolbox_utils
3
- url = http://github.com/timcera/toolbox_utils
3
+ url = git@github.com:timcera/toolbox_utils.git
4
+ branch = main
@@ -1,3 +1,11 @@
1
+ ## v2.3.2 (2026-06-11)
2
+
3
+ ### Fix
4
+
5
+ - update toolbox_utils to support numpy 1.*
6
+
7
+ ## v2.3.1 (2026-06-11)
8
+
1
9
  ## v2.3.0 (2026-06-09)
2
10
 
3
11
  ### Feat
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydrotoolbox
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Command line script and Python library for analysis of flow time-series.
5
5
  Author-email: Tim Cera <tim@cerazone.net>
6
6
  License: BSD-3-Clause
@@ -0,0 +1 @@
1
+ 2.3.2
@@ -65,7 +65,7 @@ github = "https://github.com/timcera/hydrotoolbox"
65
65
  name = "cz_conventional_commits"
66
66
  tag_format = "v$version"
67
67
  update_changelog_on_bump = true
68
- version = "2.3.0"
68
+ version = "2.3.2"
69
69
  version_files = ["VERSION"]
70
70
 
71
71
  [tool.isort]
@@ -143,10 +143,12 @@ def wdm_extract(wdmfile, *idsn):
143
143
  tgroup = dattr["TGROUP"]
144
144
  tstep = dattr["TSSTEP"]
145
145
  tcode = dattr["TCODE"]
146
- cindex = pd.date_range(start=start, periods=len(records) + 1, freq=freq[tgroup])
146
+ cindex = pd.date_range(
147
+ start=start, periods=len(records) + 1, freq=freq[tgroup]
148
+ ).astype("datetime64[ns]")
147
149
  tindex = pd.date_range(
148
150
  start=start, end=cindex[-1], freq=str(tstep) + freq[tcode]
149
- )
151
+ ).astype("datetime64[ns]")
150
152
  counts = np.diff(np.searchsorted(tindex, cindex))
151
153
 
152
154
  # Get timeseries data
@@ -1730,19 +1730,21 @@ def asbestfreq(data: DataFrame, force_freq: Optional[str] = None) -> DataFrame:
1730
1730
  if force_freq:
1731
1731
  return _replace_nan_with_na(data, freq=force_freq)
1732
1732
 
1733
+ ndata = data.dropna(how="all")
1734
+
1733
1735
  # Since pandas doesn't set data.index.freq and data.index.freqstr when
1734
1736
  # using .asfreq, this function returns that PANDAS time offset alias code
1735
1737
  # also. Not ideal at all.
1736
1738
  #
1737
1739
  # This gets most of the frequencies...
1738
- if data.index.inferred_freq:
1740
+ if ndata.index.inferred_freq:
1739
1741
  with suppress(ValueError):
1740
1742
  return _replace_nan_with_na(data, freq=data.index.inferred_freq)
1741
1743
 
1742
1744
  # pd.infer_freq would fail if given a large dataset
1743
- slic = slice(None, 999) if len(data.index) > 1000 else slice(None, None)
1745
+ slic = slice(None, 999) if len(ndata.index) > 1000 else slice(None, None)
1744
1746
  try:
1745
- infer_freq = pd.infer_freq(data.index[slic])
1747
+ infer_freq = pd.infer_freq(ndata.index[slic])
1746
1748
  except ValueError:
1747
1749
  infer_freq = None
1748
1750
  if infer_freq:
@@ -1750,8 +1752,9 @@ def asbestfreq(data: DataFrame, force_freq: Optional[str] = None) -> DataFrame:
1750
1752
 
1751
1753
  data.index = data.index.astype("datetime64[ns]")
1752
1754
  ndiff = (
1753
- data.index.astype("int64").values[1:] - data.index.astype("int64").values[:-1]
1754
- )
1755
+ ndata.index.astype("datetime64[ns]").values[1:]
1756
+ - ndata.index.astype("datetime64[ns]").values[:-1]
1757
+ ).astype("int64")
1755
1758
 
1756
1759
  if np.any(ndiff <= 0):
1757
1760
  raise ValueError(
@@ -1770,57 +1773,53 @@ def asbestfreq(data: DataFrame, force_freq: Optional[str] = None) -> DataFrame:
1770
1773
  # Use the minimum of the intervals to test a new interval.
1771
1774
  # Should work for fixed intervals.
1772
1775
  ndiff = sorted(set(ndiff))
1773
- ngcd = (
1774
- ndiff[0].astype("int64")
1775
- if len(ndiff) == 1
1776
- else reduce(np.gcd, [i.astype("int64") for i in ndiff])
1777
- )
1778
- if ngcd < 1000:
1779
- infer_freq = f"{ngcd}{pandas_offset_by_version('ns')}"
1780
- elif ngcd < 1000000:
1781
- infer_freq = f"{ngcd // 1000}{pandas_offset_by_version('us')}"
1782
- elif ngcd < 1000000000:
1783
- infer_freq = f"{ngcd // 1000000}{pandas_offset_by_version('ms')}"
1784
- elif ngcd < 60000000000:
1785
- infer_freq = f"{ngcd // 1000000000}{pandas_offset_by_version('s')}"
1786
- elif ngcd < 3600000000000:
1787
- infer_freq = f"{ngcd // 60000000000}{pandas_offset_by_version('min')}"
1788
- elif ngcd < 86400000000000:
1789
- infer_freq = f"{ngcd // 3600000000000}{pandas_offset_by_version('h')}"
1790
- elif ngcd < 604800000000000:
1791
- infer_freq = f"{ngcd // 86400000000000}D"
1792
- elif ngcd < 2419200000000000:
1793
- infer_freq = f"{ngcd // 604800000000000}W"
1794
- if np.all(data.index.dayofweek == data.index[0].dayofweek):
1795
- infer_freq = f"{infer_freq}-{_WEEKLIES[data.index[0].dayofweek]}"
1796
- else:
1797
- infer_freq = "D"
1798
- if infer_freq:
1799
- return _replace_nan_with_na(data, freq=infer_freq)
1800
-
1801
- # At this point pd.infer_freq failed probably because of missing values.
1802
- # The following algorithm would not capture things like BQ, BQS
1803
- # ...etc.
1804
- if np.all(data.index.is_month_start):
1805
- if np.all(data.index.month == data.index[0].month):
1806
- # Actually yearly with different start
1807
- infer_freq = f"YE-{_ANNUALS[data.index[0].month - 1]}"
1808
- else:
1809
- infer_freq = "MS"
1810
- elif np.all(data.index.is_month_end):
1776
+ ngcd = ndiff[0] if len(ndiff) == 1 else reduce(np.gcd, ndiff)
1777
+ ndiff = np.array(ndiff)
1778
+ # ngcd is the greatest common divisor of the intervals in nanoseconds.
1779
+ infer_freq = f"{ngcd}{pandas_offset_by_version('ns')}"
1780
+ if data.index.is_month_end.all() and all(ndiff >= 2_419_200_000_000_000):
1781
+ infer_freq = pandas_offset_by_version("ME")
1811
1782
  if np.all(data.index.month == data.index[0].month):
1812
1783
  # Actually yearly with different ends
1813
- infer_freq = f"YE-{_ANNUALS[data.index[0].month]}"
1814
- else:
1815
- infer_freq = "ME"
1816
- elif np.all(data.index.is_quarter_end):
1784
+ infer_freq = (
1785
+ f"{pandas_offset_by_version('YE')}-{_ANNUALS[data.index[0].month]}"
1786
+ )
1787
+ elif data.index.is_month_start.all() and all(ndiff >= 2_419_200_000_000_000):
1788
+ infer_freq = pandas_offset_by_version("MS")
1789
+ if np.all(data.index.month == data.index[0].month):
1790
+ # Actually yearly with different start
1791
+ infer_freq = (
1792
+ f"{pandas_offset_by_version('YS')}-{_ANNUALS[data.index[0].month - 1]}"
1793
+ )
1794
+ elif data.index.is_quarter_end.all() and all(ndiff >= 7_257_600_000_000_000):
1817
1795
  infer_freq = pandas_offset_by_version("QE")
1818
- elif np.all(data.index.is_quarter_start):
1796
+ elif data.index.is_quarter_start.all() and all(ndiff >= 7_257_600_000_000_000):
1819
1797
  infer_freq = pandas_offset_by_version("QS")
1820
- elif np.all(data.index.is_year_end):
1798
+ elif data.index.is_year_end.all() and all(ndiff >= 31_536_000_000_000_000):
1821
1799
  infer_freq = pandas_offset_by_version("YE")
1822
- elif np.all(data.index.is_year_start):
1800
+ elif data.index.is_year_start.all() and all(ndiff >= 31_536_000_000_000_000):
1823
1801
  infer_freq = pandas_offset_by_version("YS")
1802
+ elif ngcd < 1_000:
1803
+ infer_freq = f"{ngcd}{pandas_offset_by_version('ns')}"
1804
+ elif ngcd % 604_800_000_000_000 == 0:
1805
+ infer_freq = f"{ngcd // 604_800_000_000_000}W"
1806
+ if np.all(data.index.dayofweek == data.index[0].dayofweek):
1807
+ infer_freq = f"{infer_freq}-{_WEEKLIES[data.index[0].dayofweek]}"
1808
+ elif ngcd % 86_400_000_000_000 == 0:
1809
+ infer_freq = f"{ngcd // 86_400_000_000_000}D"
1810
+ elif ngcd % 3_600_000_000_000 == 0:
1811
+ infer_freq = f"{ngcd // 3_600_000_000_000}{pandas_offset_by_version('h')}"
1812
+ elif ngcd % 60_000_000_000 == 0:
1813
+ infer_freq = f"{ngcd // 60_000_000_000}{pandas_offset_by_version('min')}"
1814
+ elif ngcd % 1_000_000_000 == 0:
1815
+ infer_freq = f"{ngcd // 1_000_000_000}{pandas_offset_by_version('s')}"
1816
+ elif ngcd % 1_000_000 == 0:
1817
+ infer_freq = f"{ngcd // 1_000_000}{pandas_offset_by_version('ms')}"
1818
+ elif ngcd % 1_000 == 0:
1819
+ infer_freq = f"{ngcd // 1_000}{pandas_offset_by_version('us')}"
1820
+
1821
+ if infer_freq:
1822
+ return _replace_nan_with_na(data, freq=infer_freq)
1824
1823
 
1825
1824
  return _replace_nan_with_na(data, freq=infer_freq)
1826
1825
 
@@ -41,7 +41,7 @@ def pandas_period_by_version(new_offset: str) -> str:
41
41
  new_to_old_period = {}
42
42
  major, minor = pd.__version__.split(".")[:2]
43
43
  if (int(major) + int(minor) / 10) < 2.2:
44
- new_to_old_freq = {
44
+ new_to_old_period = {
45
45
  "Y": "A",
46
46
  "h": "H",
47
47
  "min": "T",
@@ -11,7 +11,6 @@ class TestRead(TestCase):
11
11
  dr = pandas.date_range("2000-01-01", periods=2, freq="D")
12
12
 
13
13
  ts = pandas.Series([4.5, 4.6], index=dr)
14
- print(ts.index.dtype)
15
14
 
16
15
  self.read_direct = pandas.DataFrame(ts, columns=["Value"])
17
16
  self.read_direct.index.name = "Datetime"
@@ -21,7 +21,7 @@ class TestWDM(TestCase):
21
21
  ret2 = tsutils.asbestfreq(
22
22
  pd.read_csv("tests/data_wdm_1.csv", index_col=0, parse_dates=True)
23
23
  )
24
- assert_frame_equal(ret1, ret2, check_dtype=False)
24
+ assert_frame_equal(ret1, ret2, check_dtype=False, check_index_type=False)
25
25
 
26
26
  def test_extract2(self):
27
27
  ret1 = tsutils.common_kwds("tests/data.wdm,2")
@@ -34,14 +34,13 @@ class TestWDM(TestCase):
34
34
  def test_extract_range(self):
35
35
  ret1 = tsutils.common_kwds("tests/data.wdm,1:2")
36
36
  ret1.columns = ["data.wdm_1", "data.wdm_2"]
37
+
38
+ ret2 = pd.read_csv("tests/data_wdm_1.csv", index_col=0, parse_dates=True)
37
39
  ret2 = tsutils.asbestfreq(
38
- pd.read_csv("tests/data_wdm_1.csv", index_col=0, parse_dates=True)
39
- )
40
- ret2 = ret2.join(
41
- tsutils.asbestfreq(
42
- pd.read_csv("tests/data_wdm_2.csv", index_col=0, parse_dates=True)
43
- ),
44
- how="outer",
40
+ ret2.join(
41
+ pd.read_csv("tests/data_wdm_2.csv", index_col=0, parse_dates=True),
42
+ how="outer",
43
+ )
45
44
  )
46
45
  try:
47
46
  ret1 = ret1.replace(np.nan, pd.NA)
@@ -51,20 +50,20 @@ class TestWDM(TestCase):
51
50
  ret2 = ret2.replace(np.nan, pd.NA)
52
51
  except RecursionError:
53
52
  pass
54
- assert_frame_equal(ret1, ret2, check_dtype=False, rtol=1e-7)
53
+ assert_frame_equal(
54
+ ret1, ret2, check_dtype=False, rtol=1e-7, check_index_type=False
55
+ )
55
56
 
56
57
  def test_extract_range_plus(self):
57
58
  ret1 = tsutils.common_kwds("tests/data.wdm,1+2")
58
59
  ret1.columns = ["data.wdm_1", "data.wdm_2"]
59
60
  ret1[ret1.isnull()] = np.nan
61
+ ret2 = pd.read_csv("tests/data_wdm_1.csv", index_col=0, parse_dates=True)
60
62
  ret2 = tsutils.asbestfreq(
61
- pd.read_csv("tests/data_wdm_1.csv", index_col=0, parse_dates=True)
62
- )
63
- ret2 = ret2.join(
64
- tsutils.asbestfreq(
65
- pd.read_csv("tests/data_wdm_2.csv", index_col=0, parse_dates=True)
66
- ),
67
- how="outer",
63
+ ret2.join(
64
+ pd.read_csv("tests/data_wdm_2.csv", index_col=0, parse_dates=True),
65
+ how="outer",
66
+ )
68
67
  )
69
68
  try:
70
69
  ret1 = ret1.replace(np.nan, pd.NA)
@@ -74,4 +73,6 @@ class TestWDM(TestCase):
74
73
  ret2 = ret2.replace(np.nan, pd.NA)
75
74
  except RecursionError:
76
75
  pass
77
- assert_frame_equal(ret1, ret2, check_dtype=False, rtol=1e-7)
76
+ assert_frame_equal(
77
+ ret1, ret2, check_dtype=False, rtol=1e-7, check_index_type=False
78
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydrotoolbox
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Command line script and Python library for analysis of flow time-series.
5
5
  Author-email: Tim Cera <tim@cerazone.net>
6
6
  License: BSD-3-Clause
@@ -11,7 +11,6 @@ LICENSE.txt
11
11
  README.rst
12
12
  VERSION
13
13
  pyproject.toml
14
- pytest.ini
15
14
  .github/dependabot.yml
16
15
  .github/workflows/clean-workflow-runs.yml
17
16
  .github/workflows/pypi-package.yml
@@ -1 +0,0 @@
1
- 2.3.0
@@ -1,2 +0,0 @@
1
- [pytest]
2
- testpaths = tests
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes