AeroViz 0.1.13__py3-none-any.whl → 0.1.15__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.
Potentially problematic release.
This version of AeroViz might be problematic. Click here for more details.
- AeroViz/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/dataProcess/Chemistry/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/dataProcess/Optical/__pycache__/PyMieScatt_update.cpython-312.pyc +0 -0
- AeroViz/dataProcess/Optical/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/dataProcess/Optical/__pycache__/mie_theory.cpython-312.pyc +0 -0
- AeroViz/dataProcess/Optical/_absorption.py +2 -0
- AeroViz/dataProcess/SizeDistr/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/dataProcess/VOC/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/dataProcess/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/dataProcess/core/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/bar.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/box.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/pie.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/radar.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/regression.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/scatter.cpython-312.pyc +0 -0
- AeroViz/plot/__pycache__/violin.cpython-312.pyc +0 -0
- AeroViz/plot/distribution/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/distribution/__pycache__/distribution.cpython-312.pyc +0 -0
- AeroViz/plot/meteorology/__pycache__/CBPF.cpython-312.pyc +0 -0
- AeroViz/plot/meteorology/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/meteorology/__pycache__/hysplit.cpython-312.pyc +0 -0
- AeroViz/plot/meteorology/__pycache__/wind_rose.cpython-312.pyc +0 -0
- AeroViz/plot/optical/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/optical/__pycache__/optical.cpython-312.pyc +0 -0
- AeroViz/plot/templates/__init__.py +1 -1
- AeroViz/plot/templates/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/templates/__pycache__/ammonium_rich.cpython-312.pyc +0 -0
- AeroViz/plot/templates/__pycache__/contour.cpython-312.pyc +0 -0
- AeroViz/plot/templates/__pycache__/corr_matrix.cpython-312.pyc +0 -0
- AeroViz/plot/templates/__pycache__/diurnal_pattern.cpython-312.pyc +0 -0
- AeroViz/plot/templates/__pycache__/koschmieder.cpython-312.pyc +0 -0
- AeroViz/plot/templates/__pycache__/metal_heatmap.cpython-312.pyc +0 -0
- AeroViz/plot/templates/corr_matrix.py +168 -2
- AeroViz/plot/templates/koschmieder.py +1 -1
- AeroViz/plot/templates/metal_heatmap.py +15 -6
- AeroViz/plot/timeseries/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/timeseries/__pycache__/template.cpython-312.pyc +0 -0
- AeroViz/plot/timeseries/__pycache__/timeseries.cpython-312.pyc +0 -0
- AeroViz/plot/timeseries/timeseries.py +96 -52
- AeroViz/plot/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/plot/utils/__pycache__/_color.cpython-312.pyc +0 -0
- AeroViz/plot/utils/__pycache__/_unit.cpython-312.pyc +0 -0
- AeroViz/plot/utils/__pycache__/plt_utils.cpython-312.pyc +0 -0
- AeroViz/plot/utils/__pycache__/sklearn_utils.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/__init__.py +154 -59
- AeroViz/rawDataReader/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/config/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/config/__pycache__/supported_instruments.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/config/supported_instruments.py +7 -4
- AeroViz/rawDataReader/core/__init__.py +176 -86
- AeroViz/rawDataReader/core/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/core/__pycache__/logger.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/core/__pycache__/qc.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/core/logger.py +14 -10
- AeroViz/rawDataReader/core/qc.py +1 -1
- AeroViz/rawDataReader/script/AE33.py +1 -1
- AeroViz/rawDataReader/script/BAM1020.py +35 -0
- AeroViz/rawDataReader/script/NEPH.py +6 -10
- AeroViz/rawDataReader/script/SMPS.py +20 -6
- AeroViz/rawDataReader/script/TEOM.py +15 -3
- AeroViz/rawDataReader/script/__init__.py +1 -0
- AeroViz/rawDataReader/script/__pycache__/AE33.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/AE43.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/APS.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/Aurora.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/BAM1020.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/BC1054.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/EPA.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/GRIMM.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/IGAC.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/MA350.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/Minion.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/NEPH.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/OCEC.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/SMPS.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/TEOM.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/VOC.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/XRF.cpython-312.pyc +0 -0
- AeroViz/rawDataReader/script/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/tools/__pycache__/__init__.cpython-312.pyc +0 -0
- AeroViz/tools/__pycache__/database.cpython-312.pyc +0 -0
- AeroViz/tools/__pycache__/dataclassifier.cpython-312.pyc +0 -0
- {AeroViz-0.1.13.dist-info → AeroViz-0.1.15.dist-info}/METADATA +14 -15
- {AeroViz-0.1.13.dist-info → AeroViz-0.1.15.dist-info}/RECORD +89 -87
- {AeroViz-0.1.13.dist-info → AeroViz-0.1.15.dist-info}/WHEEL +1 -1
- {AeroViz-0.1.13.dist-info → AeroViz-0.1.15.dist-info}/LICENSE +0 -0
- {AeroViz-0.1.13.dist-info → AeroViz-0.1.15.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Literal
|
|
4
4
|
|
|
5
5
|
from pandas import Grouper, Timedelta
|
|
6
6
|
|
|
@@ -10,66 +10,124 @@ from AeroViz.rawDataReader.script import *
|
|
|
10
10
|
__all__ = ['RawDataReader']
|
|
11
11
|
|
|
12
12
|
SUPPORTED_INSTRUMENTS = [
|
|
13
|
-
NEPH, Aurora, SMPS,
|
|
14
|
-
MA350, TEOM, OCEC, IGAC, VOC, EPA, Minion
|
|
13
|
+
NEPH, Aurora, SMPS, APS, GRIMM, AE33, AE43, BC1054,
|
|
14
|
+
MA350, BAM1020, TEOM, OCEC, IGAC, VOC, EPA, Minion
|
|
15
15
|
]
|
|
16
16
|
|
|
17
|
+
SIZE_RANGE_INSTRUMENTS = ['SMPS', 'APS', 'GRIMM']
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
def RawDataReader(instrument: str,
|
|
19
21
|
path: Path | str,
|
|
20
|
-
reset: bool = False,
|
|
22
|
+
reset: bool | str = False,
|
|
21
23
|
qc: bool | str = True,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
append_data: bool = False,
|
|
25
|
-
start: datetime = None,
|
|
26
|
-
end: datetime = None,
|
|
24
|
+
start: datetime | str = None,
|
|
25
|
+
end: datetime | str = None,
|
|
27
26
|
mean_freq: str = '1h',
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
size_range: tuple[float, float] | None = None,
|
|
28
|
+
suppress_warnings: bool = False,
|
|
29
|
+
log_level: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR'] = 'INFO',
|
|
30
|
+
**kwargs):
|
|
30
31
|
"""
|
|
31
32
|
Factory function to instantiate the appropriate reader module for a given instrument and
|
|
32
33
|
return the processed data over the specified time range.
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
instrument : str
|
|
38
|
+
The instrument name for which to read data, must be a valid key in the meta dictionary
|
|
39
|
+
|
|
40
|
+
path : Path or str
|
|
41
|
+
The directory where raw data files for the instrument are stored
|
|
42
|
+
|
|
43
|
+
reset : bool or str
|
|
44
|
+
Data processing control mode:
|
|
45
|
+
False (default) - Use existing processed data if available
|
|
46
|
+
True - Force reprocess all data from raw files
|
|
47
|
+
'append' - Add new data to existing processed data
|
|
48
|
+
|
|
49
|
+
qc : bool or str
|
|
50
|
+
Quality control and rate calculation mode:
|
|
51
|
+
True (default) - Apply QC and calculate overall rates
|
|
52
|
+
False - Skip QC and return raw data only
|
|
53
|
+
str - Calculate rates at specified intervals:
|
|
54
|
+
'W' - Weekly rates
|
|
55
|
+
'MS' - Month start rates
|
|
56
|
+
'QS' - Quarter start rates
|
|
57
|
+
'YS' - Year start rates
|
|
58
|
+
Can add number prefix (e.g., '2MS' for bi-monthly)
|
|
59
|
+
|
|
60
|
+
start : datetime
|
|
61
|
+
Start time for filtering the data
|
|
62
|
+
|
|
63
|
+
end : datetime
|
|
64
|
+
End time for filtering the data
|
|
65
|
+
|
|
66
|
+
mean_freq : str
|
|
67
|
+
Resampling frequency for averaging the data (e.g., '1h' for hourly mean)
|
|
68
|
+
|
|
69
|
+
size_range : tuple[float, float], optional
|
|
70
|
+
Size range in nanometers (min_size, max_size) for SMPS/APS data filtering
|
|
71
|
+
|
|
72
|
+
suppress_warnings : bool, optional
|
|
73
|
+
Whether to suppress warning messages (default: False)
|
|
74
|
+
|
|
75
|
+
log_level : {'DEBUG', 'INFO', 'WARNING', 'ERROR'}
|
|
76
|
+
Logging level (default: 'INFO')
|
|
77
|
+
|
|
78
|
+
**kwargs
|
|
79
|
+
Additional arguments to pass to the reader module
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
pd.DataFrame
|
|
84
|
+
Processed data with specified QC and time range
|
|
85
|
+
|
|
86
|
+
Raises
|
|
87
|
+
------
|
|
88
|
+
ValueError
|
|
89
|
+
If instrument name is invalid
|
|
90
|
+
If path does not exist
|
|
91
|
+
If QC frequency is invalid
|
|
92
|
+
If time range is invalid
|
|
93
|
+
If mean_freq format is invalid
|
|
94
|
+
|
|
95
|
+
Examples
|
|
96
|
+
--------
|
|
97
|
+
>>> from AeroViz import RawDataReader
|
|
98
|
+
>>>
|
|
99
|
+
>>> # Using string inputs
|
|
100
|
+
>>> df_ae33 = RawDataReader(
|
|
101
|
+
... instrument='AE33',
|
|
102
|
+
... path='/path/to/your/data/folder',
|
|
103
|
+
... reset=True,
|
|
104
|
+
... qc='1MS',
|
|
105
|
+
... start='2024-01-01',
|
|
106
|
+
... end='2024-06-30',
|
|
107
|
+
... mean_freq='1h',
|
|
108
|
+
... )
|
|
109
|
+
|
|
110
|
+
>>> # Using Path and datetime objects
|
|
58
111
|
>>> from pathlib import Path
|
|
59
112
|
>>> from datetime import datetime
|
|
60
113
|
>>>
|
|
61
|
-
>>>
|
|
62
|
-
...
|
|
63
|
-
... path=Path('/path/to/data'),
|
|
64
|
-
...
|
|
65
|
-
...
|
|
114
|
+
>>> df_ae33 = RawDataReader(
|
|
115
|
+
... instrument='AE33',
|
|
116
|
+
... path=Path('/path/to/your/data/folder'),
|
|
117
|
+
... reset=True,
|
|
118
|
+
... qc='1MS',
|
|
119
|
+
... start=datetime(2024, 1, 1),
|
|
120
|
+
... end=datetime(2024, 6, 30),
|
|
121
|
+
... mean_freq='1h',
|
|
122
|
+
... )
|
|
66
123
|
"""
|
|
124
|
+
|
|
67
125
|
# Mapping of instrument names to their respective classes
|
|
68
126
|
instrument_class_map = {cls.__name__.split('.')[-1]: cls for cls in SUPPORTED_INSTRUMENTS}
|
|
69
127
|
|
|
70
128
|
# Check if the instrument name is in the map
|
|
71
|
-
if
|
|
72
|
-
raise ValueError(f"Instrument name '{
|
|
129
|
+
if instrument not in meta.keys():
|
|
130
|
+
raise ValueError(f"Instrument name '{instrument}' is not valid. \nMust be one of: {list(meta.keys())}")
|
|
73
131
|
|
|
74
132
|
# Check if path exists and is a directory
|
|
75
133
|
if not isinstance(path, Path):
|
|
@@ -78,22 +136,38 @@ def RawDataReader(instrument_name: str,
|
|
|
78
136
|
raise FileNotFoundError(f"The specified path '{path}' does not exist or is not a directory.")
|
|
79
137
|
|
|
80
138
|
# Validate the QC frequency
|
|
81
|
-
if
|
|
139
|
+
if isinstance(qc, str):
|
|
82
140
|
try:
|
|
83
|
-
Grouper(freq=
|
|
84
|
-
except ValueError
|
|
85
|
-
raise ValueError(f"Invalid frequency: {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if start and end:
|
|
90
|
-
if end.hour == 0 and end.minute == 0 and end.second == 0:
|
|
91
|
-
end = end.replace(hour=23, minute=59, second=59)
|
|
92
|
-
else:
|
|
141
|
+
Grouper(freq=qc)
|
|
142
|
+
except (ValueError, TypeError):
|
|
143
|
+
raise ValueError(f"Invalid frequency: {qc}. Must be one of: "
|
|
144
|
+
f"W (week), MS (month start), QS (quarter start), YS (year start)")
|
|
145
|
+
|
|
146
|
+
# Convert and verify input times
|
|
147
|
+
if not (start and end):
|
|
93
148
|
raise ValueError("Both start and end times must be provided.")
|
|
149
|
+
|
|
150
|
+
# Convert start time if it's a string
|
|
151
|
+
if isinstance(start, str):
|
|
152
|
+
try:
|
|
153
|
+
start = datetime.fromisoformat(start.replace('Z', '+00:00'))
|
|
154
|
+
except ValueError as e:
|
|
155
|
+
raise ValueError(
|
|
156
|
+
f"Invalid start time format. Please use ISO format (YYYY-MM-DD or YYYY-MM-DD HH:MM:SS): {e}")
|
|
157
|
+
|
|
158
|
+
# Convert end time if it's a string
|
|
159
|
+
if isinstance(end, str):
|
|
160
|
+
try:
|
|
161
|
+
end = datetime.fromisoformat(end.replace('Z', '+00:00'))
|
|
162
|
+
except ValueError as e:
|
|
163
|
+
raise ValueError(
|
|
164
|
+
f"Invalid end time format. Please use ISO format (YYYY-MM-DD or YYYY-MM-DD HH:MM:SS): {e}")
|
|
165
|
+
|
|
94
166
|
if end <= start:
|
|
95
167
|
raise ValueError(f"Invalid time range: start {start} is after end {end}")
|
|
96
168
|
|
|
169
|
+
end = end.replace(hour=23, minute=59, second=59) if end.hour == 0 and end.minute == 0 else end
|
|
170
|
+
|
|
97
171
|
# Verify that mean_freq format
|
|
98
172
|
try:
|
|
99
173
|
Timedelta(mean_freq)
|
|
@@ -101,19 +175,40 @@ def RawDataReader(instrument_name: str,
|
|
|
101
175
|
raise ValueError(
|
|
102
176
|
f"Invalid mean_freq: '{mean_freq}'. It should be a valid frequency string (e.g., '1h', '30min', '1D').")
|
|
103
177
|
|
|
178
|
+
# Validate size range
|
|
179
|
+
if size_range is not None:
|
|
180
|
+
if instrument not in SIZE_RANGE_INSTRUMENTS:
|
|
181
|
+
raise ValueError(f"Size range filtering is only supported for {SIZE_RANGE_INSTRUMENTS}")
|
|
182
|
+
|
|
183
|
+
min_size, max_size = size_range
|
|
184
|
+
if not isinstance(min_size, (int, float)) or not isinstance(max_size, (int, float)):
|
|
185
|
+
raise ValueError("Size range values must be numeric")
|
|
186
|
+
if min_size >= max_size:
|
|
187
|
+
raise ValueError("Minimum size must be less than maximum size")
|
|
188
|
+
|
|
189
|
+
if instrument == 'SMPS':
|
|
190
|
+
if not (1 <= min_size <= 1000) or not (1 <= max_size <= 1000):
|
|
191
|
+
raise ValueError("SMPS size range must be between 1 and 1000 nm")
|
|
192
|
+
elif instrument == 'APS':
|
|
193
|
+
if not (500 <= min_size <= 20000) or not (500 <= max_size <= 20000):
|
|
194
|
+
raise ValueError("APS size range must be between 500 and 20000 nm")
|
|
195
|
+
|
|
196
|
+
kwargs.update({'size_range': size_range})
|
|
197
|
+
|
|
198
|
+
kwargs.update({
|
|
199
|
+
'suppress_warnings': suppress_warnings,
|
|
200
|
+
'log_level': log_level
|
|
201
|
+
})
|
|
202
|
+
|
|
104
203
|
# Instantiate the class and return the instance
|
|
105
|
-
reader_module = instrument_class_map[
|
|
204
|
+
reader_module = instrument_class_map[instrument].Reader(
|
|
106
205
|
path=path,
|
|
107
206
|
reset=reset,
|
|
108
207
|
qc=qc,
|
|
109
|
-
qc_freq=qc_freq,
|
|
110
|
-
rate=rate,
|
|
111
|
-
append_data=append_data,
|
|
112
208
|
**kwargs
|
|
113
209
|
)
|
|
114
210
|
return reader_module(
|
|
115
211
|
start=start,
|
|
116
212
|
end=end,
|
|
117
213
|
mean_freq=mean_freq,
|
|
118
|
-
csv_out=csv_out,
|
|
119
214
|
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -58,6 +58,13 @@ meta = {
|
|
|
58
58
|
"deter_key": {"BC Mass Conc. (880 nm)": ["BC5"]},
|
|
59
59
|
},
|
|
60
60
|
|
|
61
|
+
"BAM1020": {
|
|
62
|
+
"pattern": ["*.csv"],
|
|
63
|
+
"freq": "1h",
|
|
64
|
+
"deter_key": {
|
|
65
|
+
"Mass Conc.": ["Conc"]},
|
|
66
|
+
},
|
|
67
|
+
|
|
61
68
|
"TEOM": {
|
|
62
69
|
"pattern": ["*.csv"],
|
|
63
70
|
"freq": "6min",
|
|
@@ -71,10 +78,6 @@ meta = {
|
|
|
71
78
|
"pattern": ["*LCRes.csv"],
|
|
72
79
|
"freq": "1h",
|
|
73
80
|
"deter_key": {
|
|
74
|
-
"Thermal OC": ["Thermal_OC"],
|
|
75
|
-
"Thermal EC": ["Thermal_EC"],
|
|
76
|
-
"Optical OC": ["Optical_OC"],
|
|
77
|
-
"Optical EC": ["Optical_EC"],
|
|
78
81
|
"Thermal OC & EC": ["Thermal_OC", "Thermal_EC"],
|
|
79
82
|
"Optical OC & EC": ["Optical_OC", "Optical_EC"],
|
|
80
83
|
},
|