AeroViz 0.1.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.

Potentially problematic release.


This version of AeroViz might be problematic. Click here for more details.

Files changed (102) hide show
  1. AeroViz/__init__.py +15 -0
  2. AeroViz/dataProcess/Chemistry/__init__.py +63 -0
  3. AeroViz/dataProcess/Chemistry/_calculate.py +27 -0
  4. AeroViz/dataProcess/Chemistry/_isoropia.py +99 -0
  5. AeroViz/dataProcess/Chemistry/_mass_volume.py +175 -0
  6. AeroViz/dataProcess/Chemistry/_ocec.py +184 -0
  7. AeroViz/dataProcess/Chemistry/_partition.py +29 -0
  8. AeroViz/dataProcess/Chemistry/_teom.py +16 -0
  9. AeroViz/dataProcess/Optical/_IMPROVE.py +61 -0
  10. AeroViz/dataProcess/Optical/__init__.py +62 -0
  11. AeroViz/dataProcess/Optical/_absorption.py +54 -0
  12. AeroViz/dataProcess/Optical/_extinction.py +36 -0
  13. AeroViz/dataProcess/Optical/_mie.py +16 -0
  14. AeroViz/dataProcess/Optical/_mie_sd.py +143 -0
  15. AeroViz/dataProcess/Optical/_scattering.py +30 -0
  16. AeroViz/dataProcess/SizeDistr/__init__.py +61 -0
  17. AeroViz/dataProcess/SizeDistr/__merge.py +250 -0
  18. AeroViz/dataProcess/SizeDistr/_merge.py +245 -0
  19. AeroViz/dataProcess/SizeDistr/_merge_v1.py +254 -0
  20. AeroViz/dataProcess/SizeDistr/_merge_v2.py +243 -0
  21. AeroViz/dataProcess/SizeDistr/_merge_v3.py +518 -0
  22. AeroViz/dataProcess/SizeDistr/_merge_v4.py +424 -0
  23. AeroViz/dataProcess/SizeDistr/_size_distr.py +93 -0
  24. AeroViz/dataProcess/VOC/__init__.py +19 -0
  25. AeroViz/dataProcess/VOC/_potential_par.py +76 -0
  26. AeroViz/dataProcess/__init__.py +11 -0
  27. AeroViz/dataProcess/core/__init__.py +92 -0
  28. AeroViz/plot/__init__.py +7 -0
  29. AeroViz/plot/distribution/__init__.py +1 -0
  30. AeroViz/plot/distribution/distribution.py +582 -0
  31. AeroViz/plot/improve/__init__.py +1 -0
  32. AeroViz/plot/improve/improve.py +240 -0
  33. AeroViz/plot/meteorology/__init__.py +1 -0
  34. AeroViz/plot/meteorology/meteorology.py +317 -0
  35. AeroViz/plot/optical/__init__.py +2 -0
  36. AeroViz/plot/optical/aethalometer.py +77 -0
  37. AeroViz/plot/optical/optical.py +388 -0
  38. AeroViz/plot/templates/__init__.py +8 -0
  39. AeroViz/plot/templates/contour.py +47 -0
  40. AeroViz/plot/templates/corr_matrix.py +108 -0
  41. AeroViz/plot/templates/diurnal_pattern.py +42 -0
  42. AeroViz/plot/templates/event_evolution.py +65 -0
  43. AeroViz/plot/templates/koschmieder.py +156 -0
  44. AeroViz/plot/templates/metal_heatmap.py +57 -0
  45. AeroViz/plot/templates/regression.py +256 -0
  46. AeroViz/plot/templates/scatter.py +130 -0
  47. AeroViz/plot/templates/templates.py +398 -0
  48. AeroViz/plot/timeseries/__init__.py +1 -0
  49. AeroViz/plot/timeseries/timeseries.py +317 -0
  50. AeroViz/plot/utils/__init__.py +3 -0
  51. AeroViz/plot/utils/_color.py +71 -0
  52. AeroViz/plot/utils/_decorator.py +74 -0
  53. AeroViz/plot/utils/_unit.py +55 -0
  54. AeroViz/process/__init__.py +31 -0
  55. AeroViz/process/core/DataProc.py +19 -0
  56. AeroViz/process/core/SizeDist.py +90 -0
  57. AeroViz/process/core/__init__.py +4 -0
  58. AeroViz/process/method/PyMieScatt_update.py +567 -0
  59. AeroViz/process/method/__init__.py +2 -0
  60. AeroViz/process/method/mie_theory.py +258 -0
  61. AeroViz/process/method/prop.py +62 -0
  62. AeroViz/process/script/AbstractDistCalc.py +143 -0
  63. AeroViz/process/script/Chemical.py +176 -0
  64. AeroViz/process/script/IMPACT.py +49 -0
  65. AeroViz/process/script/IMPROVE.py +161 -0
  66. AeroViz/process/script/Others.py +65 -0
  67. AeroViz/process/script/PSD.py +103 -0
  68. AeroViz/process/script/PSD_dry.py +94 -0
  69. AeroViz/process/script/__init__.py +5 -0
  70. AeroViz/process/script/retrieve_RI.py +70 -0
  71. AeroViz/rawDataReader/__init__.py +68 -0
  72. AeroViz/rawDataReader/core/__init__.py +397 -0
  73. AeroViz/rawDataReader/script/AE33.py +31 -0
  74. AeroViz/rawDataReader/script/AE43.py +34 -0
  75. AeroViz/rawDataReader/script/APS_3321.py +47 -0
  76. AeroViz/rawDataReader/script/Aurora.py +38 -0
  77. AeroViz/rawDataReader/script/BC1054.py +46 -0
  78. AeroViz/rawDataReader/script/EPA_vertical.py +18 -0
  79. AeroViz/rawDataReader/script/GRIMM.py +35 -0
  80. AeroViz/rawDataReader/script/IGAC_TH.py +104 -0
  81. AeroViz/rawDataReader/script/IGAC_ZM.py +90 -0
  82. AeroViz/rawDataReader/script/MA350.py +45 -0
  83. AeroViz/rawDataReader/script/NEPH.py +57 -0
  84. AeroViz/rawDataReader/script/OCEC_LCRES.py +34 -0
  85. AeroViz/rawDataReader/script/OCEC_RES.py +28 -0
  86. AeroViz/rawDataReader/script/SMPS_TH.py +41 -0
  87. AeroViz/rawDataReader/script/SMPS_aim11.py +51 -0
  88. AeroViz/rawDataReader/script/SMPS_genr.py +51 -0
  89. AeroViz/rawDataReader/script/TEOM.py +46 -0
  90. AeroViz/rawDataReader/script/Table.py +28 -0
  91. AeroViz/rawDataReader/script/VOC_TH.py +30 -0
  92. AeroViz/rawDataReader/script/VOC_ZM.py +37 -0
  93. AeroViz/rawDataReader/script/__init__.py +22 -0
  94. AeroViz/tools/__init__.py +3 -0
  95. AeroViz/tools/database.py +94 -0
  96. AeroViz/tools/dataclassifier.py +117 -0
  97. AeroViz/tools/datareader.py +66 -0
  98. AeroViz-0.1.0.dist-info/LICENSE +21 -0
  99. AeroViz-0.1.0.dist-info/METADATA +117 -0
  100. AeroViz-0.1.0.dist-info/RECORD +102 -0
  101. AeroViz-0.1.0.dist-info/WHEEL +5 -0
  102. AeroViz-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,397 @@
1
+ import json as jsn
2
+ import pickle as pkl
3
+ from abc import ABC, abstractmethod
4
+ from datetime import datetime as dtm, timedelta as dtmdt
5
+ from pathlib import Path
6
+
7
+ import numpy as np
8
+ from pandas import DataFrame, date_range, concat, to_numeric, to_datetime
9
+
10
+ from ..utils.config import meta
11
+
12
+ __all__ = ['AbstractReader']
13
+
14
+
15
+ class AbstractReader(ABC):
16
+ nam = 'AbstractReader'
17
+
18
+ # initial config
19
+ # input : file path, reset switch
20
+
21
+ # list the file in the path and read pickle file if it exists, else read raw data and dump the pickle file the
22
+ # pickle file will be generated after read raw data first time, if you want to re-read the rawdata, please set
23
+ # 'reset=True'
24
+
25
+ def __init__(self, _path, QC=True, csv_raw=True, reset=False, rate=False, append_data=False, update_meta=None):
26
+ # logging.info(f'\n{self.nam}')
27
+ # print('='*65)
28
+ # logger.info(f"Reading file and process data")
29
+
30
+ # class parameter
31
+ # self.index = lambda _freq: date_range(_sta, _fin, freq=_freq)
32
+ self.path = Path(_path)
33
+ self.meta = meta[self.nam]
34
+
35
+ if update_meta is not None:
36
+ self.meta.update(update_meta)
37
+
38
+ self.reset = reset
39
+ self.rate = rate
40
+ self.qc = QC
41
+ self.csv = csv_raw
42
+ self.apnd = append_data & reset
43
+
44
+ self.pkl_nam = f'_read_{self.nam.lower()}.pkl'
45
+ self.csv_nam = f'_read_{self.nam.lower()}.csv'
46
+
47
+ self.pkl_nam_raw = f'_read_{self.nam.lower()}_raw.pkl'
48
+ self.csv_nam_raw = f'_read_{self.nam.lower()}_raw.csv'
49
+
50
+ self.csv_out = f'output_{self.nam.lower()}.csv'
51
+
52
+ # print(f" from {_sta.strftime('%Y-%m-%d %X')} to {_fin.strftime('%Y-%m-%d %X')}")
53
+ # print('='*65)
54
+ # print(f"{dtm.now().strftime('%m/%d %X')}")
55
+
56
+ # get data
57
+ def __call__(self,
58
+ start: dtm | None = None,
59
+ end: dtm | None = None,
60
+ mean_freq='1h',
61
+ csv_out=True,
62
+ **kwarg):
63
+
64
+ self._oth_set = kwarg
65
+
66
+ if start and end and end <= start:
67
+ raise ValueError(
68
+ f'\nPlease check out input time : \n\tstart : {start.strftime("%Y-%m-%d %X")}\n\tend : {end.strftime("%Y-%m-%d %X")}')
69
+
70
+ fout = self._run(start, end)
71
+
72
+ if fout is not None:
73
+ if mean_freq is not None:
74
+ fout = fout.resample(mean_freq).mean()
75
+
76
+ if csv_out:
77
+ fout.to_csv(self.path / self.csv_out)
78
+
79
+ return fout
80
+
81
+ # dependency injection function
82
+ @abstractmethod
83
+ def _raw_reader(self, _file):
84
+ # customize each instrument
85
+ pass
86
+
87
+ @abstractmethod
88
+ def _QC(self, df: DataFrame):
89
+ # customize each instrument
90
+ return df
91
+
92
+ # set each to true datetime(18:30:01 -> 18:30:00) and rindex data
93
+ def _raw_process(self, _df):
94
+ # get time from df and set time to whole time to create time index
95
+ _st, _ed = _df.index.sort_values()[[0, -1]]
96
+ _tm_index = date_range(_st.strftime('%Y%m%d %H00'),
97
+ (_ed + dtmdt(hours=1)).strftime('%Y%m%d %H00'),
98
+ freq=self.meta['freq'])
99
+ _tm_index.name = 'time'
100
+
101
+ return _df.apply(to_numeric, errors='coerce').resample(self.meta['freq']).mean().reindex(_tm_index)
102
+
103
+ # acquisition rate and yield rate
104
+ def _rate_calculate(self, _fout_raw, _fout_qc, _st_raw, _ed_raw):
105
+
106
+ if self.meta['deter_key'] is not None:
107
+ _start, _end = _fout_qc.index[[0, -1]]
108
+
109
+ _drop_how = 'any'
110
+ _the_size = len(_fout_raw.resample('1h').mean().index)
111
+
112
+ _f_pth = (self.path / f'{self.nam}.log')
113
+ _f = _f_pth.open('r+' if _f_pth.exists() else 'w+')
114
+
115
+ _cont = _f.read()
116
+ _f.seek(0)
117
+
118
+ _f.write(f"\n{dtm.now().strftime('%Y/%m/%d %X')}\n")
119
+ _f.write(f"{'-' * 60}\n")
120
+ _f.write(f"rawdata time : \n\t{_st_raw.strftime('%Y-%m-%d %X')} ~ {_ed_raw.strftime('%Y-%m-%d %X')}\n")
121
+ _f.write(f"output time : \n\t{_start.strftime('%Y-%m-%d %X')} ~ {_end.strftime('%Y-%m-%d %X')}\n")
122
+ _f.write(f"{'-' * 60}\n")
123
+ print(f"\n\t\tfrom {_start.strftime('%Y-%m-%d %X')} to {_end.strftime('%Y-%m-%d %X')}\n")
124
+
125
+ for _nam, _key in self.meta['deter_key'].items():
126
+
127
+ if _key == ['all']:
128
+ _key, _drop_how = _fout_qc.keys(), 'all'
129
+
130
+ _real_size = len(_fout_raw[_key].resample('1h').mean().copy().dropna(how=_drop_how).index)
131
+ _QC_size = len(_fout_qc[_key].resample('1h').mean().copy().dropna(how=_drop_how).index)
132
+
133
+ try:
134
+ _acq_rate = round((_real_size / _the_size) * 100, 1)
135
+ _yid_rate = round((_QC_size / _real_size) * 100, 1)
136
+ except ZeroDivisionError:
137
+ _acq_rate, _yid_rate = 0, 0
138
+
139
+ _f.write(f'{_nam} : \n')
140
+ _f.write(f"\tacquisition rate : {_acq_rate}%\n")
141
+ _f.write(f'\tyield rate : {_yid_rate}%\n')
142
+
143
+ print(f'\t\t{_nam} : ')
144
+ print(f'\t\t\tacquisition rate : \033[91m{_acq_rate}%\033[0m')
145
+ print(f'\t\t\tyield rate : \033[91m{_yid_rate}%\033[0m')
146
+
147
+ _f.write(f"{'=' * 40}\n")
148
+ _f.write(_cont)
149
+
150
+ _f.close()
151
+
152
+ # process time index
153
+ @staticmethod
154
+ def _tmidx_process(_start, _end, _df):
155
+ _st, _ed = _df.index.sort_values()[[0, -1]]
156
+ _start, _end = to_datetime(_start) or _st, to_datetime(_end) or _ed
157
+ _idx = date_range(_start, _end, freq=_df.index.freq.copy())
158
+ _idx.name = 'time'
159
+
160
+ return _df.reindex(_idx), _st, _ed
161
+
162
+ # append new data to exist pkl
163
+ @staticmethod
164
+ def _apnd_prcs(_df_done, _df_apnd):
165
+
166
+ if _df_apnd is not None:
167
+ _df = concat([_df_apnd.dropna(how='all').copy(), _df_done.dropna(how='all').copy()])
168
+
169
+ _idx = date_range(*_df.index.sort_values()[[0, -1]], freq=_df_done.index.freq.copy())
170
+ _idx.name = 'time'
171
+
172
+ return _df.loc[~_df.index.duplicated()].copy().reindex(_idx)
173
+
174
+ return _df_done
175
+
176
+ # remove outlier
177
+ def _outlier_prcs(self, _df):
178
+
179
+ if (self.path / 'outlier.json') not in self.path.glob('*.json'):
180
+ return _df
181
+
182
+ with (self.path / 'outlier.json').open('r', encoding='utf-8', errors='ignore') as f:
183
+ self.outlier = jsn.load(f)
184
+
185
+ for _st, _ed in self.outlier.values():
186
+ _df.loc[_st:_ed] = np.nan
187
+
188
+ return _df
189
+
190
+ # save pickle file
191
+ def _save_dt(self, _save_raw, _save_qc):
192
+ # dump pickle file
193
+ _check = True
194
+ while _check:
195
+ try:
196
+ with (self.path / self.pkl_nam).open('wb') as f:
197
+ pkl.dump(_save_qc, f, protocol=pkl.HIGHEST_PROTOCOL)
198
+
199
+ # dump csv file
200
+ if self.csv:
201
+ _save_qc.to_csv(self.path / self.csv_nam)
202
+
203
+ # output raw data if qc file
204
+ if self.meta['deter_key'] is not None:
205
+ with (self.path / self.pkl_nam_raw).open('wb') as f:
206
+ pkl.dump(_save_raw, f, protocol=pkl.HIGHEST_PROTOCOL)
207
+
208
+ if self.csv:
209
+ _save_raw.to_csv(self.path / self.csv_nam_raw)
210
+
211
+ _check = False
212
+
213
+ except PermissionError as _err:
214
+ print('\n', _err)
215
+ input('\t\t\33[41m Please Close The File And Press "Enter" \33[0m\n')
216
+
217
+ # read pickle file
218
+ def _read_pkl(self, ):
219
+ with (self.path / self.pkl_nam).open('rb') as f:
220
+ _fout_qc = pkl.load(f)
221
+
222
+ if (self.path / self.pkl_nam_raw).exists():
223
+ with (self.path / self.pkl_nam_raw).open('rb') as f:
224
+ _fout_raw = pkl.load(f)
225
+ else:
226
+ _fout_raw = _fout_qc
227
+
228
+ return _fout_raw, _fout_qc
229
+
230
+ # read raw data
231
+ def _read_raw(self, ):
232
+ _df_con, _f_list = None, list(self.path.glob(self.meta['pattern']))
233
+
234
+ for file in _f_list:
235
+ if file.name in [self.csv_out, self.csv_nam, self.csv_nam_raw, f'{self.nam}.log']:
236
+ continue
237
+
238
+ print(f"\r\t\treading {file.name}", end='')
239
+
240
+ _df = self._raw_reader(file)
241
+
242
+ # concat the concated list
243
+ if _df is not None:
244
+ _df_con = concat([_df_con, _df]) if _df_con is not None else _df
245
+
246
+ if _df_con is None:
247
+ print(f"\t\t\033[31mNo File in '{self.path}' Could Read, Please Check Out the Current Path\033[0m")
248
+ return None, None
249
+
250
+ # QC
251
+ _fout_raw = self._raw_process(_df_con)
252
+ _fout_qc = self._QC(_fout_raw)
253
+
254
+ return _fout_raw, _fout_qc
255
+
256
+ # main flow
257
+ def _run(self, _start, _end):
258
+
259
+ _f_raw_done, _f_qc_done = None, None
260
+
261
+ # read pickle if pickle file exists and 'reset=False' or process raw data or append new data
262
+ _pkl_exist = self.path / self.pkl_nam in list(self.path.glob('*.pkl'))
263
+ if _pkl_exist & ((~self.reset) | self.apnd):
264
+ print(f"\n\t{dtm.now().strftime('%m/%d %X')} : Reading \033[96mPICKLE\033[0m file of {self.nam}")
265
+
266
+ _f_raw_done, _f_qc_done = self._read_pkl()
267
+
268
+ if not self.apnd:
269
+ _f_raw_done, _start_raw, _end_raw = self._tmidx_process(_start, _end, _f_raw_done)
270
+ _f_qc_done, _start_raw, _end_raw = self._tmidx_process(_start, _end, _f_qc_done)
271
+
272
+ _f_qc_done = self._outlier_prcs(_f_qc_done)
273
+
274
+ if self.rate:
275
+ self._rate_calculate(_f_raw_done, _f_qc_done, _start_raw, _end_raw)
276
+
277
+ return _f_qc_done if self.qc else _f_raw_done
278
+
279
+ # read raw data
280
+ print(f"\n\t{dtm.now().strftime('%m/%d %X')} : Reading \033[96mRAW DATA\033[0m of {self.nam} and process it")
281
+
282
+ _f_raw, _f_qc = self._read_raw()
283
+ if _f_raw is None:
284
+ return None
285
+
286
+ # append new data and pickle data
287
+ if self.apnd & _pkl_exist:
288
+ _f_raw = self._apnd_prcs(_f_raw_done, _f_raw)
289
+ _f_qc = self._apnd_prcs(_f_qc_done, _f_qc)
290
+
291
+ _f_qc = self._outlier_prcs(_f_qc)
292
+
293
+ # save
294
+ self._save_dt(_f_raw, _f_qc)
295
+
296
+ # process time index
297
+ # if (_start is not None)|(_end is not None):
298
+ _f_raw, _start_raw, _end_raw = self._tmidx_process(_start, _end, _f_raw)
299
+ _f_qc, _start_raw, _end_raw = self._tmidx_process(_start, _end, _f_qc)
300
+
301
+ self._rate_calculate(_f_raw, _f_qc, _start_raw, _end_raw)
302
+
303
+ return _f_qc if self.qc else _f_raw
304
+
305
+ # -------------------------------------------------------------------------------------
306
+ # old flow
307
+ # def __run(self, _start, _end):
308
+ #
309
+ # ## read pickle if pickle file exists and 'reset=False' or process raw data
310
+ # if (self.path / self.pkl_nam in list(self.path.glob('*.pkl'))) & (~self.reset):
311
+ # print(f"\n\t{dtm.now().strftime('%m/%d %X')} : Reading \033[96mPICKLE\033[0m file of {self.nam}")
312
+ #
313
+ # with (self.path / self.pkl_nam).open('rb') as f:
314
+ # _fout_qc = pkl.load(f)
315
+ #
316
+ # _exist = (self.path / self.pkl_nam_raw).exists()
317
+ # if _exist:
318
+ # with (self.path / self.pkl_nam_raw).open('rb') as f:
319
+ # _fout_raw = pkl.load(f)
320
+ # else:
321
+ # _fout_raw = _fout_qc
322
+ #
323
+ # _start, _end = to_datetime(_start) or _fout_qc.index[0], to_datetime(_end) or _fout_qc.index[-1]
324
+ # _idx = date_range(_start, _end, freq=_fout_qc.index.freq.copy())
325
+ # _idx.name = 'time'
326
+ #
327
+ # _fout_raw, _fout_qc = _fout_raw.reindex(_idx), _fout_qc.reindex(_idx)
328
+ # if (self.rate) & (_exist):
329
+ # self._rate_calculate(_fout_raw, _fout_qc)
330
+ #
331
+ # return _fout_qc if self.qc else _fout_raw
332
+ # else:
333
+ # print(
334
+ # f"\n\t{dtm.now().strftime('%m/%d %X')} : Reading \033[96mRAW DATA\033[0m of {self.nam} and process it")
335
+ #
336
+ # ##=================================================================================================================
337
+ # ## read raw data
338
+ # _df_con, _f_list = None, list(self.path.glob(self.meta['pattern']))
339
+ #
340
+ # if len(_f_list) == 0:
341
+ # print(f"\t\t\033[31mNo File in '{self.path}' Could Read, Please Check Out the Current Path\033[0m")
342
+ # return None
343
+ #
344
+ # for file in _f_list:
345
+ # if file.name in [self.csv_out, self.csv_nam, self.csv_nam_raw, f'{self.nam}.log']: continue
346
+ #
347
+ # print(f"\r\t\treading {file.name}", end='')
348
+ #
349
+ # _df = self._raw_reader(file)
350
+ #
351
+ # ## concat the concated list
352
+ # if _df is not None:
353
+ # _df_con = concat([_df_con, _df]) if _df_con is not None else _df
354
+ # print()
355
+ #
356
+ # ## QC
357
+ # _save_raw = self._raw_process(_df_con)
358
+ # _save_qc = self._QC(_save_raw)
359
+ #
360
+ # _start, _end = to_datetime(_start) or _save_raw.index[0], to_datetime(_end) or _save_raw.index[-1]
361
+ # _idx = date_range(_start, _end, freq=_save_raw.index.freq.copy())
362
+ # _idx.name = 'time'
363
+ #
364
+ # _fout_raw, _fout_qc = _save_raw.reindex(_idx).copy(), _save_qc.reindex(_idx).copy()
365
+ #
366
+ # self._rate_calculate(_fout_raw, _fout_qc)
367
+ #
368
+ # ##=================================================================================================================
369
+ # ## dump pickle file
370
+ # _check = True
371
+ # while _check:
372
+ #
373
+ # try:
374
+ # with (self.path / self.pkl_nam).open('wb') as f:
375
+ # pkl.dump(_save_qc, f, protocol=pkl.HIGHEST_PROTOCOL)
376
+ #
377
+ # ## dump csv file
378
+ # if self.csv:
379
+ # _save_qc.to_csv(self.path / self.csv_nam)
380
+ #
381
+ # ## output raw data if qc file
382
+ # if self.meta['deter_key'] is not None:
383
+ # with (self.path / self.pkl_nam_raw).open('wb') as f:
384
+ # pkl.dump(_save_raw, f, protocol=pkl.HIGHEST_PROTOCOL)
385
+ #
386
+ # if self.csv:
387
+ # _save_raw.to_csv(self.path / self.csv_nam_raw)
388
+ #
389
+ # return _fout_qc if self.qc else _fout_raw
390
+ #
391
+ # _check = False
392
+ #
393
+ # except PermissionError as _err:
394
+ # print('\n', _err)
395
+ # input('\t\t\33[41m Please Close The File And Press "Enter" \33[0m\n')
396
+ #
397
+ # return _fout_qc
@@ -0,0 +1,31 @@
1
+ from pandas import read_table
2
+
3
+ from AeroViz.rawDataReader.core import AbstractReader
4
+
5
+
6
+ class Reader(AbstractReader):
7
+ nam = 'AE33'
8
+
9
+ def _raw_reader(self, _file):
10
+ _df = read_table(_file, parse_dates={'time': [0, 1]}, index_col='time',
11
+ delimiter=r'\s+', skiprows=5, usecols=range(67))
12
+ _df.columns = _df.columns.str.strip(';')
13
+
14
+ # remove data without Status=0, 128 (Not much filter tape), 256 (Not much filter tape)
15
+ if not self._oth_set.get('ignore_err', False):
16
+ _df = _df.where((_df['Status'] != 0) | (_df['Status'] != 128) | (_df['Status'] != 256)).copy()
17
+
18
+ return _df[['BC1', 'BC2', 'BC3', 'BC4', 'BC5', 'BC6', 'BC7', 'Status']]
19
+
20
+ def _QC(self, _df):
21
+ # remove negative value
22
+ _df = _df[['BC1', 'BC2', 'BC3', 'BC4', 'BC5', 'BC6', 'BC7']].mask((_df < 0).copy())
23
+
24
+ # QC data in 5 min
25
+ def _QC_func(df):
26
+ _df_ave, _df_std = df.mean(), df.std()
27
+ _df_lowb, _df_highb = df < (_df_ave - _df_std * 1.5), df > (_df_ave + _df_std * 1.5)
28
+
29
+ return df.mask(_df_lowb | _df_highb).copy()
30
+
31
+ return _df.resample('5min').apply(_QC_func).resample('1h').mean()
@@ -0,0 +1,34 @@
1
+ from pandas import read_csv
2
+
3
+ from AeroViz.rawDataReader.core import AbstractReader
4
+
5
+
6
+ class Reader(AbstractReader):
7
+ nam = 'AE43'
8
+
9
+ def _raw_reader(self, _file):
10
+ _df = read_csv(_file, parse_dates={'time': ['StartTime']}, index_col='time')
11
+ _df_id = _df['SetupID'].iloc[-1]
12
+
13
+ # get last SetupID data
14
+ _df = _df.groupby('SetupID').get_group(_df_id)[
15
+ ['BC1', 'BC2', 'BC3', 'BC4', 'BC5', 'BC6', 'BC7', 'Status']].copy()
16
+
17
+ # remove data without Status=0
18
+ _df = _df.where(_df['Status'] == 0).copy()
19
+
20
+ return _df[['BC1', 'BC2', 'BC3', 'BC4', 'BC5', 'BC6', 'BC7']]
21
+
22
+ # QC data
23
+ def _QC(self, _df):
24
+ # remove negative value
25
+ _df = _df.mask((_df < 0).copy())
26
+
27
+ # QC data in 5 min
28
+ def _QC_func(df):
29
+ _df_ave, _df_std = df.mean(), df.std()
30
+ _df_lowb, _df_highb = df < (_df_ave - _df_std * 1.5), df > (_df_ave + _df_std * 1.5)
31
+
32
+ return df.mask(_df_lowb | _df_highb).copy()
33
+
34
+ return _df.resample('5min').apply(_QC_func).resample('1h').mean()
@@ -0,0 +1,47 @@
1
+ import numpy as n
2
+ from pandas import to_datetime, read_table
3
+
4
+ from AeroViz.rawDataReader.core import AbstractReader
5
+
6
+
7
+ class Reader(AbstractReader):
8
+ nam = 'APS_3321'
9
+
10
+ def _raw_reader(self, _file):
11
+ with open(_file, 'r', encoding='utf-8', errors='ignore') as f:
12
+ _df = read_table(f, skiprows=6, parse_dates={'Time': ['Date', 'Start Time']}).set_index('Time')
13
+ _key = list(_df.keys()[3:54]) ## 542 ~ 1981
14
+
15
+ ## create new keys
16
+ _newkey = {}
17
+ for _k in _key:
18
+ _newkey[_k] = float(_k).__round__(4)
19
+ # _newkey['Mode(m)'] = 'mode'
20
+
21
+ ## get new dataframe
22
+ _df = _df[_newkey.keys()].rename(_newkey, axis=1)
23
+ # _df['total'] = _df[list(_newkey.values())[:-1]].sum(axis=1)*(n.diff(n.log(_df.keys()[:-1].to_numpy(float))).mean()).copy()
24
+
25
+ _df_idx = to_datetime(_df.index, errors='coerce')
26
+
27
+ return _df.set_index(_df_idx).loc[_df_idx.dropna()]
28
+
29
+ ## QC data
30
+ def _QC(self, _df):
31
+ ## mask out the data size lower than 7
32
+ _df['total'] = _df.sum(axis=1, min_count=1) * (n.diff(n.log(_df.keys().to_numpy(float)))).mean()
33
+ _df_size = _df['total'].dropna().resample('1h').size().resample(_df.index.freq).ffill()
34
+ _df = _df.mask(_df_size < 7)
35
+
36
+ ## remove total conc. lower than 700
37
+ _df = _df.mask(_df['total'] > 700)
38
+
39
+ # not confirmed
40
+ """
41
+ ## remove the bin over 4000 nm which num. conc. larger than 1
42
+ # _df_remv_ky = _df.keys()[:-2][_df.keys()[:-2]>=4.]
43
+
44
+ # _df_1hr[_df_remv_ky] = _df_1hr[_df_remv_ky].copy().mask(_df_1hr[_df_remv_ky]>1.)
45
+ # """
46
+
47
+ return _df[_df.keys()[:-1]]
@@ -0,0 +1,38 @@
1
+ from pandas import to_datetime, read_csv
2
+
3
+ from AeroViz.rawDataReader.core import AbstractReader
4
+
5
+
6
+ class Reader(AbstractReader):
7
+ nam = 'Aurora'
8
+
9
+ def _raw_reader(self, _file):
10
+ with (_file).open('r', encoding='utf-8-sig', errors='ignore') as f:
11
+ _df = read_csv(f, low_memory=False, index_col=0)
12
+
13
+ _df.index = to_datetime(_df.index, errors='coerce', format=self._oth_set.get('date_format') or 'mixed')
14
+ _df.index.name = 'time'
15
+
16
+ _df.columns = _df.keys().str.strip(' ')
17
+
18
+ _df = _df.loc[
19
+ _df.index.dropna(), ['0°σspB', '0°σspG', '0°σspR', '90°σspB', '90°σspG', '90°σspR', 'RH']].copy()
20
+ _df.columns = ['B', 'G', 'R', 'BB', 'BG', 'BR', 'RH']
21
+
22
+ return _df
23
+
24
+ ## QC data
25
+ def _QC(self, _df):
26
+ ## remove negative value
27
+ _df = _df.mask((_df <= 0).copy())
28
+
29
+ ## call by _QC function
30
+ ## QC data in 1 hr
31
+ def _QC_func(_df_1hr):
32
+ _df_ave = _df_1hr.mean()
33
+ _df_std = _df_1hr.std()
34
+ _df_lowb, _df_highb = _df_1hr < (_df_ave - _df_std * 1.5), _df_1hr > (_df_ave + _df_std * 1.5)
35
+
36
+ return _df_1hr.mask(_df_lowb | _df_highb).copy()
37
+
38
+ return _df.resample('1h', group_keys=False).apply(_QC_func)
@@ -0,0 +1,46 @@
1
+ from pandas import read_csv
2
+
3
+ from AeroViz.rawDataReader.core import AbstractReader
4
+
5
+
6
+ class Reader(AbstractReader):
7
+ nam = 'BC1054'
8
+
9
+ def _raw_reader(self, _file):
10
+ with open(_file, 'r', encoding='utf-8', errors='ignore') as f:
11
+ _df = read_csv(f, parse_dates=['Time'], index_col='Time')
12
+
13
+ _df = _df.rename(columns={
14
+ 'BC1(ng/m3)': 'BC1',
15
+ 'BC2(ng/m3)': 'BC2',
16
+ 'BC3(ng/m3)': 'BC3',
17
+ 'BC4(ng/m3)': 'BC4',
18
+ 'BC5(ng/m3)': 'BC5',
19
+ 'BC6(ng/m3)': 'BC6',
20
+ 'BC7(ng/m3)': 'BC7',
21
+ 'BC8(ng/m3)': 'BC8',
22
+ 'BC9(ng/m3)': 'BC9',
23
+ 'BC10(ng/m3)': 'BC10'
24
+ })
25
+
26
+ # remove data without Status=32 (Automatic Tape Advance), 65536 (Tape Move)
27
+ # if not self._oth_set.get('ignore_err', False):
28
+ # _df = _df.where((_df['Status'] != 32) | (_df['Status'] != 65536)).copy()
29
+
30
+ return _df[['BC1', 'BC2', 'BC3', 'BC4', 'BC5', 'BC6', 'BC7', 'BC8', 'BC9', 'BC10', 'Status']]
31
+
32
+ # QC data
33
+ def _QC(self, _df):
34
+ # remove negative value
35
+ _df = _df[['BC1', 'BC2', 'BC3', 'BC4', 'BC5', 'BC6', 'BC7', 'BC8', 'BC9', 'BC10']].mask((_df < 0).copy())
36
+
37
+ # call by _QC function
38
+ # QC data in 1 hr
39
+ def _QC_func(_df_1hr):
40
+ _df_ave = _df_1hr.mean()
41
+ _df_std = _df_1hr.std()
42
+ _df_lowb, _df_highb = _df_1hr < (_df_ave - _df_std * 1.5), _df_1hr > (_df_ave + _df_std * 1.5)
43
+
44
+ return _df_1hr.mask(_df_lowb | _df_highb).copy()
45
+
46
+ return _df.resample('1h', group_keys=False).apply(_QC_func).resample('5min').mean()
@@ -0,0 +1,18 @@
1
+ from pandas import read_csv, to_numeric
2
+
3
+ from AeroViz.rawDataReader.core import AbstractReader
4
+
5
+
6
+ class Reader(AbstractReader):
7
+ nam = 'EPA_vertical'
8
+
9
+ def _raw_reader(self, _file):
10
+ with _file.open('r', encoding='big5', errors='ignore') as f:
11
+ _df = read_csv(f, names=['time', 'station', 'comp', 'data', None], skiprows=1, na_values=['-'],
12
+ parse_dates=['time'], index_col='time')
13
+ _df['data'] = to_numeric(_df['data'], errors='coerce')
14
+
15
+ _df_piv = _df.pivot_table(values='data', columns='comp', index='time')
16
+ _df_piv.index.name = 'time'
17
+
18
+ return _df_piv
@@ -0,0 +1,35 @@
1
+ from pandas import to_datetime, read_csv
2
+
3
+ from AeroViz.rawDataReader.core import AbstractReader
4
+
5
+
6
+ class Reader(AbstractReader):
7
+ nam = 'GRIMM'
8
+
9
+ def _raw_reader(self, _file):
10
+
11
+ _df = read_csv(_file, header=233, delimiter='\t', index_col=0, parse_dates=[0], encoding='ISO-8859-1',
12
+ dayfirst=True).rename_axis("Time")
13
+ _df.index = to_datetime(_df.index, format="%d/%m/%Y %H:%M:%S", dayfirst=True)
14
+
15
+ if _file.name.startswith("A407ST"):
16
+ _df.drop(_df.columns[0:11].tolist() + _df.columns[128:].tolist(), axis=1, inplace=True)
17
+ else:
18
+ _df.drop(_df.columns[0:11].tolist() + _df.columns[-5:].tolist(), axis=1, inplace=True)
19
+
20
+ if _df.empty:
21
+ print(_file, "is empty")
22
+ return None
23
+
24
+ return _df / 0.035
25
+
26
+ def _QC(self, _df):
27
+ # QC data in 1 hr
28
+ def _QC_func(_df_1hr):
29
+ _df_ave = _df_1hr.mean()
30
+ _df_std = _df_1hr.std()
31
+ _df_lowb, _df_highb = _df_1hr < (_df_ave - _df_std * 1.5), _df_1hr > (_df_ave + _df_std * 1.5)
32
+
33
+ return _df_1hr.mask(_df_lowb | _df_highb).copy()
34
+
35
+ return _df.resample('5min').apply(_QC_func).resample('1h').mean()