tsp 1.7.7__py3-none-any.whl → 1.8.1__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.
Files changed (92) hide show
  1. tsp/__init__.py +11 -11
  2. tsp/__meta__.py +1 -1
  3. tsp/concatenation.py +153 -0
  4. tsp/core.py +1162 -1035
  5. tsp/data/2023-01-06_755-test-Dataset_2031-Constant_Over_Interval-Hourly-Ground_Temperature-Thermistor_Automated.timeserie.csv +4 -4
  6. tsp/data/2023-01-06_755-test.metadata.txt +208 -208
  7. tsp/data/NTGS_example_csv.csv +6 -6
  8. tsp/data/NTGS_example_slash_dates.csv +6 -6
  9. tsp/data/example_geotop.csv +5240 -5240
  10. tsp/data/example_gtnp.csv +1298 -1298
  11. tsp/data/example_permos.csv +7 -7
  12. tsp/data/test_geotop_has_space.txt +5 -5
  13. tsp/dataloggers/AbstractReader.py +43 -43
  14. tsp/dataloggers/FG2.py +110 -110
  15. tsp/dataloggers/GP5W.py +114 -114
  16. tsp/dataloggers/Geoprecision.py +34 -34
  17. tsp/dataloggers/HOBO.py +914 -914
  18. tsp/dataloggers/RBRXL800.py +190 -190
  19. tsp/dataloggers/RBRXR420.py +308 -308
  20. tsp/dataloggers/__init__.py +15 -15
  21. tsp/dataloggers/logr.py +115 -115
  22. tsp/dataloggers/test_files/004448.DAT +2543 -2543
  23. tsp/dataloggers/test_files/004531.DAT +17106 -17106
  24. tsp/dataloggers/test_files/004531.HEX +3587 -3587
  25. tsp/dataloggers/test_files/004534.HEX +3587 -3587
  26. tsp/dataloggers/test_files/010252.dat +1731 -1731
  27. tsp/dataloggers/test_files/010252.hex +1739 -1739
  28. tsp/dataloggers/test_files/010274.hex +1291 -1291
  29. tsp/dataloggers/test_files/010278.hex +3544 -3544
  30. tsp/dataloggers/test_files/012064.dat +1286 -1286
  31. tsp/dataloggers/test_files/012064.hex +1294 -1294
  32. tsp/dataloggers/test_files/012081.hex +3532 -3532
  33. tsp/dataloggers/test_files/07B1592.DAT +1483 -1483
  34. tsp/dataloggers/test_files/07B1592.HEX +1806 -1806
  35. tsp/dataloggers/test_files/07B4450.DAT +2234 -2234
  36. tsp/dataloggers/test_files/07B4450.HEX +2559 -2559
  37. tsp/dataloggers/test_files/FG2_399.csv +9881 -9881
  38. tsp/dataloggers/test_files/GP5W.csv +1121 -1121
  39. tsp/dataloggers/test_files/GP5W_260.csv +1884 -1884
  40. tsp/dataloggers/test_files/GP5W_270.csv +2210 -2210
  41. tsp/dataloggers/test_files/H08-030-08_HOBOware.csv +998 -998
  42. tsp/dataloggers/test_files/RBR_01.dat +1046 -1046
  43. tsp/dataloggers/test_files/RBR_02.dat +2426 -2426
  44. tsp/dataloggers/test_files/RSTDT2055.csv +2152 -2152
  45. tsp/dataloggers/test_files/U23-001_HOBOware.csv +1001 -1001
  46. tsp/dataloggers/test_files/hobo-negative-2.txt +6396 -6396
  47. tsp/dataloggers/test_files/hobo-negative-3.txt +5593 -5593
  48. tsp/dataloggers/test_files/hobo-positive-number-1.txt +1000 -1000
  49. tsp/dataloggers/test_files/hobo-positive-number-2.csv +1003 -1003
  50. tsp/dataloggers/test_files/hobo-positive-number-3.csv +1133 -1133
  51. tsp/dataloggers/test_files/hobo-positive-number-4.csv +1209 -1209
  52. tsp/dataloggers/test_files/hobo2.csv +8702 -8702
  53. tsp/dataloggers/test_files/hobo_1_AB.csv +21732 -21732
  54. tsp/dataloggers/test_files/hobo_1_AB_Details.txt +133 -133
  55. tsp/dataloggers/test_files/hobo_1_AB_classic.csv +4373 -4373
  56. tsp/dataloggers/test_files/hobo_1_AB_defaults.csv +21732 -21732
  57. tsp/dataloggers/test_files/hobo_1_AB_minimal.txt +1358 -1358
  58. tsp/dataloggers/test_files/hobo_1_AB_var2.csv +3189 -3189
  59. tsp/dataloggers/test_files/hobo_1_AB_var3.csv +2458 -2458
  60. tsp/dataloggers/test_files/logR_ULogC16-32_1.csv +106 -106
  61. tsp/dataloggers/test_files/logR_ULogC16-32_2.csv +100 -100
  62. tsp/dataloggers/test_files/mon_3_Ta_2010-08-18_2013-02-08.txt +21724 -21724
  63. tsp/dataloggers/test_files/rbr_001.dat +1133 -1133
  64. tsp/dataloggers/test_files/rbr_001.hex +1139 -1139
  65. tsp/dataloggers/test_files/rbr_001_no_comment.dat +1132 -1132
  66. tsp/dataloggers/test_files/rbr_001_no_comment.hex +1138 -1138
  67. tsp/dataloggers/test_files/rbr_002.dat +1179 -1179
  68. tsp/dataloggers/test_files/rbr_002.hex +1185 -1185
  69. tsp/dataloggers/test_files/rbr_003.hex +1292 -1292
  70. tsp/dataloggers/test_files/rbr_003.xls +0 -0
  71. tsp/dataloggers/test_files/rbr_xl_001.DAT +1105 -1105
  72. tsp/dataloggers/test_files/rbr_xl_002.DAT +1126 -1126
  73. tsp/dataloggers/test_files/rbr_xl_003.DAT +4622 -4622
  74. tsp/dataloggers/test_files/rbr_xl_003.HEX +3587 -3587
  75. tsp/gtnp.py +148 -148
  76. tsp/labels.py +3 -3
  77. tsp/misc.py +90 -90
  78. tsp/physics.py +101 -101
  79. tsp/plots/static.py +373 -373
  80. tsp/readers.py +548 -548
  81. tsp/time.py +45 -45
  82. tsp/tspwarnings.py +14 -14
  83. tsp/utils.py +101 -101
  84. tsp/version.py +1 -1
  85. {tsp-1.7.7.dist-info → tsp-1.8.1.dist-info}/METADATA +30 -23
  86. tsp-1.8.1.dist-info/RECORD +94 -0
  87. {tsp-1.7.7.dist-info → tsp-1.8.1.dist-info}/WHEEL +5 -5
  88. {tsp-1.7.7.dist-info → tsp-1.8.1.dist-info/licenses}/LICENSE +674 -674
  89. tsp/dataloggers/test_files/CSc_CR1000_1.dat +0 -295
  90. tsp/scratch.py +0 -6
  91. tsp-1.7.7.dist-info/RECORD +0 -95
  92. {tsp-1.7.7.dist-info → tsp-1.8.1.dist-info}/top_level.txt +0 -0
tsp/__init__.py CHANGED
@@ -1,11 +1,11 @@
1
- from tsp.core import TSP, IndexedTSP
2
- from tsp.misc import _is_depth_column
3
-
4
- from tsp.plots.static import trumpet_curve, time_series, colour_contour
5
- from tsp.readers import read_gtnp, read_geotop, read_geoprecision, read_hoboware, read_ntgs, read_logr, read_csv, read_rbr
6
- from tsp.utils import resolve_duplicate_times
7
- from tsp.version import version as __version__
8
-
9
- #TSP.__module__ = "teaspoon"
10
-
11
- __all__ = ["TSP", "IndexedTSP"]
1
+ from tsp.core import TSP, IndexedTSP
2
+ from tsp.misc import _is_depth_column
3
+
4
+ from tsp.plots.static import trumpet_curve, time_series, colour_contour
5
+ from tsp.readers import read_gtnp, read_geotop, read_geoprecision, read_hoboware, read_ntgs, read_logr, read_csv, read_rbr
6
+ from tsp.utils import resolve_duplicate_times
7
+ from tsp.version import version as __version__
8
+
9
+ #TSP.__module__ = "teaspoon"
10
+
11
+ __all__ = ["TSP", "IndexedTSP"]
tsp/__meta__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # Automatically created. Please do not edit.
2
- __version__ = '1.7.7'
2
+ __version__ = '1.8.1'
3
3
  __author__ = 'Nick Brown'
tsp/concatenation.py ADDED
@@ -0,0 +1,153 @@
1
+ from __future__ import annotations
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+
6
+ from typing import Any, TYPE_CHECKING
7
+
8
+
9
+ if TYPE_CHECKING:
10
+ from tsp import TSP
11
+
12
+
13
+ def _tsp_concat(tsp_list: "list[TSP]", on_conflict="error", metadata='first') -> dict[str, Any]:
14
+ """ Helper for core.tsp_concat """
15
+ # Validate the TSPs in the list
16
+ _validate_tsp_list(tsp_list)
17
+
18
+ # Combine the TSPs
19
+ dfs = [t.wide for t in tsp_list]
20
+ combined_df = _concat_deduplicate(dfs, on_conflict=on_conflict)
21
+
22
+ # Combine metadata
23
+ if metadata == 'first':
24
+ metadata = {key:val for key, val in tsp_list[0].metadata.items()}
25
+ latitude = tsp_list[0].latitude
26
+ longitude = tsp_list[0].longitude
27
+ site_id = tsp_list[0].site_id
28
+
29
+ elif metadata == 'identical':
30
+ metadata = {key:val for key, val in tsp_list[0].metadata.items()}
31
+ for key, val in metadata.items():
32
+ for t in tsp_list[1:]:
33
+ if key not in t.metadata or t.metadata[key] != val:
34
+ _ = metadata.pop(key)
35
+ latitude = _none_if_not_identical([t.latitude for t in tsp_list])
36
+ longitude = _none_if_not_identical([t.longitude for t in tsp_list])
37
+ site_id = _none_if_not_identical([t.site_id for t in tsp_list])
38
+
39
+ elif metadata == 'none':
40
+ metadata = None
41
+ latitude, longitude, site_id = None, None, None
42
+
43
+ else:
44
+ raise ValueError(f"Unknown metadata method: {metadata}")
45
+
46
+ #final_tsp = TSP(times=combined_df.index, values=combined_df.values, depths=combined_df.columns,
47
+ # latitude=latitude, longitude=longitude,
48
+ # site_id=site_id, metadata=metadata)
49
+ try:
50
+ combined_df.drop('time', axis=1, inplace=True)
51
+ except KeyError:
52
+ Warning("Deprecation Error: The 'time' column is no longer used in TSP objects. Please update your code to avoid this warning.")
53
+
54
+ tsp_dict = {
55
+ 'times': combined_df.index,
56
+ 'values': combined_df.values,
57
+ 'depths': combined_df.columns,
58
+ 'latitude': latitude,
59
+ 'longitude': longitude,
60
+ 'site_id': site_id,
61
+ 'metadata': metadata
62
+ }
63
+ return tsp_dict
64
+
65
+
66
+ def _none_if_not_identical(list):
67
+ """Check if all elements in the list are identical. If they are, return the first element; otherwise, return None."""
68
+ first = list[0]
69
+ for item in list[1:]:
70
+ if item != first:
71
+ return None
72
+ return first
73
+
74
+
75
+ def _validate_tsp_list(tsp_list: "list[TSP]"):
76
+ """Check that all TSPs in the list have the same depths."""
77
+ depths0 = tsp_list[0].depths
78
+ for t in tsp_list[1:]:
79
+ if not np.array_equal(depths0, t.depths):
80
+ raise ValueError("All TSPs must have the same depths.")
81
+
82
+
83
+ def _concat_deduplicate(df_list, on_conflict='error'):
84
+ """
85
+ Concatenates a list of DataFrames, handling duplicate indices based on row values.
86
+
87
+ Args:
88
+ df_list (list): A list of pandas DataFrames. Assumes they have identical
89
+ column names.
90
+ on_conflict (str): Specifies how to handle duplicate indices with
91
+ unequal row values.
92
+ - 'error': Raise a ValueError (default).
93
+ - 'keep_first': Keep the row corresponding to the first
94
+ DataFrame in the list where the index appeared.
95
+
96
+ Returns:
97
+ pandas.DataFrame: The concatenated DataFrame with duplicates handled
98
+ according to the specified rules.
99
+
100
+ Raises:
101
+ ValueError: If df_list is empty.
102
+ ValueError: If on_conflict is not 'error' or 'keep_first'.
103
+ ValueError: If on_conflict='error' and duplicate indices with
104
+ non-identical row values are found.
105
+ """
106
+ if not df_list:
107
+ raise ValueError("Input DataFrame list cannot be empty.")
108
+
109
+ if on_conflict not in ['error', 'keep_first']:
110
+ raise ValueError("on_conflict must be either 'error' or 'keep_first'")
111
+
112
+ # Store original index name if it exists
113
+ original_index_name = df_list[0].index.name
114
+
115
+ # Concatenate all DataFrames. The order is preserved.
116
+ combined_df = pd.concat(df_list, ignore_index=False) # Keep original indices
117
+
118
+ temp_index_col = "__temp_index__"
119
+ combined_reset = combined_df.reset_index(names=temp_index_col)
120
+
121
+ # Drop rows that are duplicates based on *all* columns
122
+ deduplicated_reset = combined_reset.drop_duplicates(keep='first')
123
+
124
+ # Check for remaining duplicates *only* in the original index column.
125
+ remaining_duplicates_mask = deduplicated_reset.duplicated(subset=temp_index_col, keep=False)
126
+
127
+ if remaining_duplicates_mask.any():
128
+ # We have indices that appeared multiple times with different values.
129
+ if on_conflict == 'error':
130
+ conflicting_indices = deduplicated_reset.loc[remaining_duplicates_mask, temp_index_col].unique()
131
+ raise ValueError(
132
+ f"Duplicate indices with non-identical values found: "
133
+ f"{list(conflicting_indices)}. Use on_conflict='keep_first' to keep "
134
+ f"the first occurrence."
135
+ )
136
+ elif on_conflict == 'keep_first':
137
+ # Drop the later occurrences of these conflicting index values.
138
+ # Since 'deduplicated_reset' preserved the first unique (index, row_value)
139
+ # combination, dropping duplicates based solely on the index column
140
+ # while keeping the first achieves the desired outcome.
141
+ final_reset = deduplicated_reset.drop_duplicates(subset=temp_index_col, keep='first')
142
+ else:
143
+ pass
144
+ else:
145
+ # No conflicting duplicates (duplicate indices with different values) were found.
146
+ final_reset = deduplicated_reset
147
+
148
+ final_df = final_reset.set_index(temp_index_col)
149
+ final_df.index.name = original_index_name
150
+ # Sort by time, ascending
151
+ final_df.sort_index(inplace=True)
152
+
153
+ return final_df