AeroViz 0.1.3__py3-none-any.whl → 0.1.4__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/__init__.py +7 -5
- AeroViz/{config → data}/DEFAULT_DATA.csv +1 -1
- AeroViz/dataProcess/Chemistry/__init__.py +40 -40
- AeroViz/dataProcess/Chemistry/_calculate.py +15 -15
- AeroViz/dataProcess/Chemistry/_isoropia.py +72 -68
- AeroViz/dataProcess/Chemistry/_mass_volume.py +158 -161
- AeroViz/dataProcess/Chemistry/_ocec.py +109 -109
- AeroViz/dataProcess/Chemistry/_partition.py +19 -18
- AeroViz/dataProcess/Chemistry/_teom.py +9 -11
- AeroViz/dataProcess/Chemistry/isrpia.cnf +21 -0
- AeroViz/dataProcess/Optical/Angstrom_exponent.py +20 -0
- AeroViz/dataProcess/Optical/_IMPROVE.py +40 -41
- AeroViz/dataProcess/Optical/__init__.py +29 -44
- AeroViz/dataProcess/Optical/_absorption.py +21 -47
- AeroViz/dataProcess/Optical/_extinction.py +31 -25
- AeroViz/dataProcess/Optical/_mie.py +5 -7
- AeroViz/dataProcess/Optical/_mie_sd.py +89 -90
- AeroViz/dataProcess/Optical/_scattering.py +19 -20
- AeroViz/dataProcess/SizeDistr/__init__.py +39 -39
- AeroViz/dataProcess/SizeDistr/__merge.py +159 -158
- AeroViz/dataProcess/SizeDistr/_merge.py +155 -154
- AeroViz/dataProcess/SizeDistr/_merge_v1.py +162 -161
- AeroViz/dataProcess/SizeDistr/_merge_v2.py +153 -152
- AeroViz/dataProcess/SizeDistr/_merge_v3.py +327 -327
- AeroViz/dataProcess/SizeDistr/_merge_v4.py +273 -275
- AeroViz/dataProcess/SizeDistr/_size_distr.py +51 -51
- AeroViz/dataProcess/VOC/__init__.py +9 -9
- AeroViz/dataProcess/VOC/_potential_par.py +53 -55
- AeroViz/dataProcess/__init__.py +28 -6
- AeroViz/dataProcess/core/__init__.py +59 -65
- AeroViz/plot/__init__.py +7 -2
- AeroViz/plot/bar.py +126 -0
- AeroViz/plot/box.py +69 -0
- AeroViz/plot/distribution/distribution.py +421 -427
- AeroViz/plot/meteorology/meteorology.py +240 -292
- AeroViz/plot/optical/__init__.py +0 -1
- AeroViz/plot/optical/optical.py +230 -230
- AeroViz/plot/pie.py +198 -0
- AeroViz/plot/regression.py +196 -0
- AeroViz/plot/scatter.py +165 -0
- AeroViz/plot/templates/__init__.py +2 -4
- AeroViz/plot/templates/ammonium_rich.py +34 -0
- AeroViz/plot/templates/contour.py +25 -25
- AeroViz/plot/templates/corr_matrix.py +86 -93
- AeroViz/plot/templates/diurnal_pattern.py +28 -26
- AeroViz/plot/templates/koschmieder.py +59 -123
- AeroViz/plot/templates/metal_heatmap.py +135 -37
- AeroViz/plot/timeseries/__init__.py +1 -0
- AeroViz/plot/timeseries/template.py +47 -0
- AeroViz/plot/timeseries/timeseries.py +324 -264
- AeroViz/plot/utils/__init__.py +2 -1
- AeroViz/plot/utils/_color.py +57 -57
- AeroViz/plot/utils/_unit.py +48 -48
- AeroViz/plot/utils/plt_utils.py +92 -0
- AeroViz/plot/utils/sklearn_utils.py +49 -0
- AeroViz/plot/utils/units.json +5 -0
- AeroViz/plot/violin.py +80 -0
- AeroViz/process/__init__.py +17 -17
- AeroViz/process/core/DataProc.py +9 -9
- AeroViz/process/core/SizeDist.py +81 -81
- AeroViz/process/method/PyMieScatt_update.py +488 -488
- AeroViz/process/method/mie_theory.py +231 -229
- AeroViz/process/method/prop.py +40 -40
- AeroViz/process/script/AbstractDistCalc.py +103 -103
- AeroViz/process/script/Chemical.py +168 -167
- AeroViz/process/script/IMPACT.py +40 -40
- AeroViz/process/script/IMPROVE.py +152 -152
- AeroViz/process/script/Others.py +45 -45
- AeroViz/process/script/PSD.py +26 -26
- AeroViz/process/script/PSD_dry.py +69 -70
- AeroViz/process/script/retrieve_RI.py +50 -51
- AeroViz/rawDataReader/__init__.py +53 -58
- AeroViz/rawDataReader/config/supported_instruments.py +155 -0
- AeroViz/rawDataReader/core/__init__.py +233 -356
- AeroViz/rawDataReader/script/AE33.py +17 -18
- AeroViz/rawDataReader/script/AE43.py +18 -21
- AeroViz/rawDataReader/script/APS_3321.py +30 -30
- AeroViz/rawDataReader/script/Aurora.py +23 -24
- AeroViz/rawDataReader/script/BC1054.py +36 -40
- AeroViz/rawDataReader/script/EPA_vertical.py +37 -9
- AeroViz/rawDataReader/script/GRIMM.py +16 -23
- AeroViz/rawDataReader/script/IGAC.py +90 -0
- AeroViz/rawDataReader/script/MA350.py +32 -39
- AeroViz/rawDataReader/script/Minion.py +103 -0
- AeroViz/rawDataReader/script/NEPH.py +69 -74
- AeroViz/rawDataReader/script/SMPS_TH.py +25 -25
- AeroViz/rawDataReader/script/SMPS_aim11.py +32 -32
- AeroViz/rawDataReader/script/SMPS_genr.py +31 -31
- AeroViz/rawDataReader/script/Sunset_OCEC.py +60 -0
- AeroViz/rawDataReader/script/TEOM.py +30 -28
- AeroViz/rawDataReader/script/Table.py +13 -14
- AeroViz/rawDataReader/script/VOC.py +26 -0
- AeroViz/rawDataReader/script/__init__.py +18 -20
- AeroViz/tools/database.py +64 -66
- AeroViz/tools/dataclassifier.py +106 -106
- AeroViz/tools/dataprinter.py +51 -51
- AeroViz/tools/datareader.py +38 -38
- {AeroViz-0.1.3.dist-info → AeroViz-0.1.4.dist-info}/METADATA +5 -4
- AeroViz-0.1.4.dist-info/RECORD +112 -0
- AeroViz/plot/improve/__init__.py +0 -1
- AeroViz/plot/improve/improve.py +0 -240
- AeroViz/plot/optical/aethalometer.py +0 -77
- AeroViz/plot/templates/event_evolution.py +0 -65
- AeroViz/plot/templates/regression.py +0 -256
- AeroViz/plot/templates/scatter.py +0 -130
- AeroViz/plot/templates/templates.py +0 -398
- AeroViz/plot/utils/_decorator.py +0 -74
- AeroViz/rawDataReader/script/IGAC_TH.py +0 -104
- AeroViz/rawDataReader/script/IGAC_ZM.py +0 -90
- AeroViz/rawDataReader/script/OCEC_LCRES.py +0 -34
- AeroViz/rawDataReader/script/OCEC_RES.py +0 -28
- AeroViz/rawDataReader/script/VOC_TH.py +0 -30
- AeroViz/rawDataReader/script/VOC_ZM.py +0 -37
- AeroViz/rawDataReader/utils/__init__.py +0 -0
- AeroViz/rawDataReader/utils/config.py +0 -169
- AeroViz-0.1.3.dist-info/RECORD +0 -111
- /AeroViz/{config → data}/DEFAULT_PNSD_DATA.csv +0 -0
- /AeroViz/{config → rawDataReader/config}/__init__.py +0 -0
- {AeroViz-0.1.3.dist-info → AeroViz-0.1.4.dist-info}/LICENSE +0 -0
- {AeroViz-0.1.3.dist-info → AeroViz-0.1.4.dist-info}/WHEEL +0 -0
- {AeroViz-0.1.3.dist-info → AeroViz-0.1.4.dist-info}/top_level.txt +0 -0
AeroViz/plot/utils/_color.py
CHANGED
|
@@ -9,63 +9,63 @@ __all__ = ['Color']
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Color:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
12
|
+
color_cycle = cycler(color=['b', 'g', 'r', 'c', 'm', 'y', 'k'])
|
|
13
|
+
|
|
14
|
+
linecolor = [{'line': '#1a56db', 'edge': '#0F50A6', 'face': '#5983D9'},
|
|
15
|
+
{'line': '#046c4e', 'edge': '#1B591F', 'face': '#538C4A'},
|
|
16
|
+
{'line': '#c81e1e', 'edge': '#f05252', 'face': '#f98080'}]
|
|
17
|
+
|
|
18
|
+
# colors = ['#FF3333', '#33FF33', '#FFFF33', '#5555FF', '#B94FFF', '#AAAAAA', '#748690'] # the last one is "unknown"
|
|
19
|
+
|
|
20
|
+
colors1 = ['#A65E58', '#A5BF6B', '#F2BF5E', '#3F83BF', '#B777C2', '#D1CFCB']
|
|
21
|
+
colors2 = ['#A65E58', '#A5BF6B', '#F2BF5E', '#3F83BF', '#B777C2', '#D1CFCB', '#96c8e6']
|
|
22
|
+
colors3 = ['#A65E58', '#A5BF6B', '#a6710d', '#F2BF5E', '#3F83BF', '#B777C2', '#D1CFCB', '#96c8e6'] # POC SOC
|
|
23
|
+
|
|
24
|
+
colors_mutiWater = ['#A65E58', '#c18e8a', '#A5BF6B', '#c5d6a0', '#F2BF5E', '#3F83BF', '#c089ca', '#d3acda',
|
|
25
|
+
'#D1CFCB']
|
|
26
|
+
colors_mutiWater2 = ['#A65E58', '#96c8e6', '#A5BF6B', '#96c8e6', '#F2BF5E', '#3F83BF', '#c089ca', '#96c8e6',
|
|
27
|
+
'#D1CFCB'] # water
|
|
28
|
+
|
|
29
|
+
color_choose = {'Clean': ['#1d4a9f', '#84a7e9'],
|
|
30
|
+
'Transition': ['#4a9f1d', '#a7e984'],
|
|
31
|
+
'Event': ['#9f1d4a', '#e984a7']}
|
|
32
|
+
|
|
33
|
+
paired = [plt.get_cmap('Paired')(i) for i in range(4)]
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def getColor(num: int = 6, cmap: str = 'jet_r'):
|
|
37
|
+
category_colors = plt.colormaps[cmap](np.linspace(0.1, 0.9, num))
|
|
38
|
+
return [plc.to_hex(category_colors[i]) for i in range(num)]
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def palplot(*args, **kwargs):
|
|
42
|
+
sns.palplot(*args, **kwargs)
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def adjust_opacity(colors: str | list[str], alpha: float):
|
|
46
|
+
if isinstance(colors, str):
|
|
47
|
+
colors = [colors]
|
|
48
|
+
|
|
49
|
+
adjusted_colors = []
|
|
50
|
+
for color in colors:
|
|
51
|
+
# 將顏色轉換為RGB表示
|
|
52
|
+
r, g, b = int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16)
|
|
53
|
+
# 調整透明度
|
|
54
|
+
r_new = int(alpha * r + (1 - alpha) * 255)
|
|
55
|
+
g_new = int(alpha * g + (1 - alpha) * 255)
|
|
56
|
+
b_new = int(alpha * b + (1 - alpha) * 255)
|
|
57
|
+
# 轉換為新的色碼
|
|
58
|
+
new_color = '#{:02X}{:02X}{:02X}'.format(r_new, g_new, b_new)
|
|
59
|
+
adjusted_colors.append(new_color)
|
|
60
|
+
return adjusted_colors
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def color_maker(obj, cmap='Blues'):
|
|
64
|
+
colors = np.nan_to_num(obj, nan=0)
|
|
65
|
+
scalar_map = plt.cm.ScalarMappable(cmap=colormaps[cmap]) # create a scalar map for the colorbar
|
|
66
|
+
scalar_map.set_array(colors)
|
|
67
|
+
return scalar_map, colors
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
if __name__ == '__main__':
|
|
71
|
-
|
|
71
|
+
Color.palplot(Color.colors2)
|
AeroViz/plot/utils/_unit.py
CHANGED
|
@@ -5,51 +5,51 @@ __all__ = ['Unit']
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class Unit:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
8
|
+
file_path = Path(__file__).parent / 'units.json'
|
|
9
|
+
data = None
|
|
10
|
+
|
|
11
|
+
def __new__(cls, unit: str):
|
|
12
|
+
cls.data = cls.load_jsonfile()
|
|
13
|
+
try:
|
|
14
|
+
value = cls.data[unit]
|
|
15
|
+
return r'${}$'.format(value.replace(' ', r'\ '))
|
|
16
|
+
except KeyError:
|
|
17
|
+
print(f"Attribute '{unit}' not found. Using default value.")
|
|
18
|
+
return r'${}$'.format(unit.replace(' ', r'\ ')) if unit is not None else 'None'
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def load_jsonfile(cls):
|
|
22
|
+
""" 讀取 JSON 檔中數據并將其變成屬性 """
|
|
23
|
+
try:
|
|
24
|
+
with open(cls.file_path, 'r', encoding='utf-8') as f:
|
|
25
|
+
return json.load(f)
|
|
26
|
+
|
|
27
|
+
except FileNotFoundError:
|
|
28
|
+
print(f"JSON file '{cls.file_path}' not found.")
|
|
29
|
+
except json.JSONDecodeError:
|
|
30
|
+
print(f"Invalid JSON format in '{cls.file_path}'.")
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def update_jsonfile(cls, key, value):
|
|
34
|
+
""" 更新JSON檔 """
|
|
35
|
+
with open(cls.file_path, 'r', encoding='utf-8') as f:
|
|
36
|
+
old_data = json.load(f)
|
|
37
|
+
|
|
38
|
+
old_data[key] = value
|
|
39
|
+
|
|
40
|
+
with open(cls.file_path, 'w', encoding='utf-8') as f:
|
|
41
|
+
json.dump(old_data, f, indent=4)
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def del_jsonfile(cls, key):
|
|
45
|
+
""" 更新JSON檔 """
|
|
46
|
+
with open(cls.file_path, 'r', encoding='utf-8') as f:
|
|
47
|
+
old_data = json.load(f)
|
|
48
|
+
|
|
49
|
+
if key in old_data:
|
|
50
|
+
del old_data[key]
|
|
51
|
+
|
|
52
|
+
with open(cls.file_path, 'w', encoding='utf-8') as f:
|
|
53
|
+
json.dump(old_data, f, indent=4)
|
|
54
|
+
else:
|
|
55
|
+
print(f"Key '{key}' not found.")
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
from matplotlib.pyplot import Axes
|
|
6
|
+
|
|
7
|
+
__all__ = ['set_figure', 'combine_legends', 'auto_label_pct']
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def set_figure(func=None,
|
|
11
|
+
*,
|
|
12
|
+
figsize: tuple | None = None,
|
|
13
|
+
fs: int | None = None,
|
|
14
|
+
fw: str = None,
|
|
15
|
+
autolayout: bool = True):
|
|
16
|
+
# For more details please see https://matplotlib.org/stable/users/explain/customizing.html
|
|
17
|
+
def decorator(_func):
|
|
18
|
+
@wraps(_func)
|
|
19
|
+
def wrapper(*args, **kwargs):
|
|
20
|
+
print(f'\n\tPlot:\033[96m {_func.__name__}\033[0m')
|
|
21
|
+
|
|
22
|
+
plt.rcParams['mathtext.fontset'] = 'custom'
|
|
23
|
+
plt.rcParams['mathtext.rm'] = 'Times New Roman'
|
|
24
|
+
plt.rcParams['mathtext.it'] = 'Times New Roman: italic'
|
|
25
|
+
plt.rcParams['mathtext.bf'] = 'Times New Roman: bold'
|
|
26
|
+
plt.rcParams['mathtext.default'] = 'regular'
|
|
27
|
+
|
|
28
|
+
# The font properties used by `text.Text`.
|
|
29
|
+
# The text, annotate, label, title, ticks, are used to create text
|
|
30
|
+
plt.rcParams['font.family'] = 'Times New Roman'
|
|
31
|
+
plt.rcParams['font.weight'] = fw or 'normal'
|
|
32
|
+
plt.rcParams['font.size'] = fs or 8
|
|
33
|
+
|
|
34
|
+
plt.rcParams['axes.titlesize'] = 'large'
|
|
35
|
+
plt.rcParams['axes.titleweight'] = 'bold'
|
|
36
|
+
plt.rcParams['axes.labelweight'] = 'bold'
|
|
37
|
+
|
|
38
|
+
# color
|
|
39
|
+
plt.rcParams['axes.prop_cycle'] = plt.cycler(color=['b', 'g', 'r', 'c', 'm', 'y', 'k'])
|
|
40
|
+
|
|
41
|
+
plt.rcParams['xtick.labelsize'] = 'medium'
|
|
42
|
+
plt.rcParams['ytick.labelsize'] = 'medium'
|
|
43
|
+
|
|
44
|
+
# matplotlib.font_manager.FontProperties ---> matplotlib.rcParams
|
|
45
|
+
plt.rcParams['legend.loc'] = 'best'
|
|
46
|
+
plt.rcParams['legend.frameon'] = False
|
|
47
|
+
plt.rcParams['legend.fontsize'] = 'small'
|
|
48
|
+
plt.rcParams['legend.title_fontsize'] = 'medium'
|
|
49
|
+
plt.rcParams['legend.handlelength'] = 1.5
|
|
50
|
+
plt.rcParams['legend.labelspacing'] = 0.7
|
|
51
|
+
|
|
52
|
+
plt.rcParams['figure.figsize'] = figsize or (4, 4)
|
|
53
|
+
plt.rcParams['figure.dpi'] = 200
|
|
54
|
+
plt.rcParams['figure.autolayout'] = autolayout
|
|
55
|
+
|
|
56
|
+
if not autolayout:
|
|
57
|
+
plt.rcParams['figure.subplot.left'] = 0.1
|
|
58
|
+
plt.rcParams['figure.subplot.right'] = 0.875
|
|
59
|
+
plt.rcParams['figure.subplot.top'] = 0.875
|
|
60
|
+
plt.rcParams['figure.subplot.bottom'] = 0.125
|
|
61
|
+
|
|
62
|
+
# plt.rcParams['figure.constrained_layout.use'] = True
|
|
63
|
+
|
|
64
|
+
plt.rcParams['savefig.transparent'] = True
|
|
65
|
+
|
|
66
|
+
return _func(*args, **kwargs)
|
|
67
|
+
|
|
68
|
+
return wrapper
|
|
69
|
+
|
|
70
|
+
if func is None:
|
|
71
|
+
return decorator
|
|
72
|
+
|
|
73
|
+
return decorator(func)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def combine_legends(axes_list: list[Axes]) -> tuple[list, list]:
|
|
77
|
+
return (
|
|
78
|
+
[legend for axes in axes_list for legend in axes.get_legend_handles_labels()[0]],
|
|
79
|
+
[label for axes in axes_list for label in axes.get_legend_handles_labels()[1]]
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def auto_label_pct(pct,
|
|
84
|
+
symbol: bool = True,
|
|
85
|
+
include_pct: bool = False,
|
|
86
|
+
ignore: Literal["inner", "outer"] = 'inner',
|
|
87
|
+
value: float = 2):
|
|
88
|
+
if not symbol:
|
|
89
|
+
return ''
|
|
90
|
+
cond = pct <= value if ignore == 'inner' else pct > value
|
|
91
|
+
label = '' if cond else '{:.1f}'.format(pct)
|
|
92
|
+
return '' if label == '' else label + '%' if include_pct else label
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from sklearn.linear_model import LinearRegression
|
|
3
|
+
from tabulate import tabulate
|
|
4
|
+
|
|
5
|
+
__all__ = ['linear_regression_base']
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def linear_regression_base(x_array: np.ndarray,
|
|
9
|
+
y_array: np.ndarray,
|
|
10
|
+
columns: str | list[str] | None = None,
|
|
11
|
+
positive: bool = True,
|
|
12
|
+
fit_intercept: bool = True):
|
|
13
|
+
if len(x_array.shape) > 1 and x_array.shape[1] >= 2:
|
|
14
|
+
model = LinearRegression(positive=positive, fit_intercept=fit_intercept).fit(x_array, y_array)
|
|
15
|
+
|
|
16
|
+
coefficients = model.coef_[0].round(3)
|
|
17
|
+
intercept = model.intercept_[0].round(3) if fit_intercept else 'None'
|
|
18
|
+
r_square = model.score(x_array, y_array).__round__(3)
|
|
19
|
+
y_predict = model.predict(x_array)
|
|
20
|
+
|
|
21
|
+
equation = ' + '.join([f'{coeff:.3f} * {col}' for coeff, col in zip(coefficients, columns)])
|
|
22
|
+
equation = equation.replace(' + 0.000 * Const', '') # Remove terms with coefficient 0
|
|
23
|
+
|
|
24
|
+
text = 'y = ' + str(equation) + '\n' + r'$\bf R^2 = $' + str(r_square)
|
|
25
|
+
tab = tabulate([[*coefficients, intercept, r_square]], headers=[*columns, 'intercept', 'R^2'], floatfmt=".3f",
|
|
26
|
+
tablefmt="fancy_grid")
|
|
27
|
+
print('\n' + tab)
|
|
28
|
+
|
|
29
|
+
return text, y_predict, coefficients
|
|
30
|
+
|
|
31
|
+
else:
|
|
32
|
+
x_array = x_array.reshape(-1, 1)
|
|
33
|
+
y_array = y_array.reshape(-1, 1)
|
|
34
|
+
|
|
35
|
+
model = LinearRegression(positive=positive, fit_intercept=fit_intercept).fit(x_array, y_array)
|
|
36
|
+
|
|
37
|
+
slope = model.coef_[0][0].round(3)
|
|
38
|
+
intercept = model.intercept_[0].round(3) if fit_intercept else 'None'
|
|
39
|
+
r_square = model.score(x_array, y_array).__round__(3)
|
|
40
|
+
y_predict = model.predict(x_array)
|
|
41
|
+
|
|
42
|
+
text = np.poly1d([slope, intercept])
|
|
43
|
+
text = 'y = ' + str(text).replace('\n', "") + '\n' + r'$\bf R^2 = $' + str(r_square)
|
|
44
|
+
|
|
45
|
+
tab = tabulate([[slope, intercept, r_square]], headers=['slope', 'intercept', 'R^2'], floatfmt=".3f",
|
|
46
|
+
tablefmt="fancy_grid")
|
|
47
|
+
print('\n' + tab)
|
|
48
|
+
|
|
49
|
+
return text, y_predict, slope
|
AeroViz/plot/utils/units.json
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
"T_OC": "OC (\u00b5g/m^3)",
|
|
7
7
|
"PM1": "PM_{1} (\u00b5g/m^3)",
|
|
8
8
|
"PM25": "PM_{2.5} (\u00b5g/m^3)",
|
|
9
|
+
"PM2.5": "PM_{2.5} (\u00b5g/m^3)",
|
|
10
|
+
"PM10": "PM_{10} (\u00b5g/m^3)",
|
|
9
11
|
"SIA": "SIA (\u00b5g/m^3)",
|
|
10
12
|
"POC": "POC (\u00b5g/m^3)",
|
|
11
13
|
"SOC": "SOC (\u00b5g/m^3)",
|
|
@@ -20,12 +22,15 @@
|
|
|
20
22
|
"Babs": "Mie Amb Absorption (1/Mm)",
|
|
21
23
|
"Babs_dry": "Mie Dry Absorption (1/Mm)",
|
|
22
24
|
"Absorption": "Absorption (1/Mm)",
|
|
25
|
+
"abs": "Absorption (1/Mm)",
|
|
23
26
|
"Bext": "Mie Amb Extinction (1/Mm)",
|
|
24
27
|
"Bext_dry": "Mie Dry Extinction (1/Mm)",
|
|
25
28
|
"Extinction": "Extinction (1/Mm)",
|
|
29
|
+
"ext": "Extinction (1/Mm)",
|
|
26
30
|
"Bsca": "Mie Amb Scattering (1/Mm)",
|
|
27
31
|
"Bsca_dry": "Mie Dry Scattering (1/Mm)",
|
|
28
32
|
"Scattering": "Scattering (1/Mm)",
|
|
33
|
+
"sca": "Scattering (1/Mm)",
|
|
29
34
|
"Diurnal": "Hour",
|
|
30
35
|
"PBLH": "PBLH (m)",
|
|
31
36
|
"VC": "VC (m²/s)",
|
AeroViz/plot/violin.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import seaborn as sns
|
|
5
|
+
from matplotlib.pyplot import Figure, Axes
|
|
6
|
+
from pandas import DataFrame
|
|
7
|
+
|
|
8
|
+
from AeroViz.plot.utils import *
|
|
9
|
+
|
|
10
|
+
__all__ = ['violin']
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@set_figure(fw='bold')
|
|
14
|
+
def violin(df: DataFrame | dict,
|
|
15
|
+
unit: str,
|
|
16
|
+
ax: Axes | None = None,
|
|
17
|
+
**kwargs
|
|
18
|
+
) -> tuple[Figure, Axes]:
|
|
19
|
+
"""
|
|
20
|
+
Generate a violin plot for multiple data sets.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
df : pd.DataFrame or dict
|
|
25
|
+
A mapping from category names to pandas DataFrames containing the data.
|
|
26
|
+
unit : str
|
|
27
|
+
The unit for the data being plotted.
|
|
28
|
+
ax : matplotlib.axes.Axes, optional
|
|
29
|
+
The Axes object to draw the plot onto. If not provided, a new figure will be created.
|
|
30
|
+
**kwargs : dict
|
|
31
|
+
Additional keyword arguments to be passed to the violinplot function.
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
fig : Figure
|
|
36
|
+
The matplotlib Figure object.
|
|
37
|
+
ax : Axes
|
|
38
|
+
The matplotlib Axes object with the scatter plot.
|
|
39
|
+
|
|
40
|
+
"""
|
|
41
|
+
fig, ax = plt.subplots(**kwargs.get('fig_kws', {})) if ax is None else (ax.get_figure(), ax)
|
|
42
|
+
|
|
43
|
+
data = df.to_numpy()
|
|
44
|
+
|
|
45
|
+
data = data[~np.isnan(data).any(axis=1)]
|
|
46
|
+
|
|
47
|
+
grps = data.shape[1]
|
|
48
|
+
|
|
49
|
+
width = 0.6
|
|
50
|
+
block = width / 2
|
|
51
|
+
x_position = np.arange(grps)
|
|
52
|
+
|
|
53
|
+
plt.boxplot(data, positions=x_position, widths=0.15,
|
|
54
|
+
showfliers=False, showmeans=True, meanline=False, patch_artist=True,
|
|
55
|
+
capprops=dict(linewidth=0),
|
|
56
|
+
whiskerprops=dict(linewidth=1.5, color='k', alpha=1),
|
|
57
|
+
boxprops=dict(linewidth=1.5, color='k', facecolor='#4778D3', alpha=1),
|
|
58
|
+
meanprops=dict(marker='o', markeredgecolor='black', markerfacecolor='white', markersize=6),
|
|
59
|
+
medianprops=dict(linewidth=1.5, ls='-', color='k', alpha=1))
|
|
60
|
+
|
|
61
|
+
sns.violinplot(data=data, density_norm='area', color='#4778D3', inner=None)
|
|
62
|
+
|
|
63
|
+
for violin, alpha in zip(ax.collections[:], [0.5] * len(ax.collections[:])):
|
|
64
|
+
violin.set_alpha(alpha)
|
|
65
|
+
violin.set_edgecolor(None)
|
|
66
|
+
|
|
67
|
+
plt.scatter(x_position, data.mean(), marker='o', facecolor='white', edgecolor='k', s=10)
|
|
68
|
+
|
|
69
|
+
xlim = kwargs.get('xlim') or (x_position[0] - (width / 2 + block), x_position[-1] + (width / 2 + block))
|
|
70
|
+
ylim = kwargs.get('ylim') or (0, None)
|
|
71
|
+
xlabel = kwargs.get('xlabel') or ''
|
|
72
|
+
ylabel = kwargs.get('ylabel') or Unit(unit)
|
|
73
|
+
xticks = kwargs.get('xticks') or [x.replace('-', '\n') for x in list(df.keys())]
|
|
74
|
+
|
|
75
|
+
ax.set(xlim=xlim, ylim=ylim, xlabel=xlabel, ylabel=ylabel, title=kwargs.get('title'))
|
|
76
|
+
ax.set_xticks(x_position, xticks, fontweight='bold', fontsize=12)
|
|
77
|
+
|
|
78
|
+
plt.show()
|
|
79
|
+
|
|
80
|
+
return fig, ax
|
AeroViz/process/__init__.py
CHANGED
|
@@ -3,29 +3,29 @@ from pathlib import Path
|
|
|
3
3
|
from pandas import read_csv, concat
|
|
4
4
|
|
|
5
5
|
from AeroViz.process.script import (ImpactProc, ImproveProc, ChemicalProc, ParticleSizeDistProc,
|
|
6
|
-
|
|
6
|
+
ExtinctionDistProc, OthersProc)
|
|
7
7
|
|
|
8
|
-
__all__ = ['
|
|
8
|
+
__all__ = ['DataProcessor', 'ImpactProc', 'ImproveProc', 'ChemicalProc', 'ParticleSizeDistProc', 'ExtinctionDistProc', ]
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
class DataProcessor:
|
|
12
|
+
def __new__(cls, file_path, reset: bool = False, save_file: Path | str = 'All_data.csv'):
|
|
13
|
+
file_path = Path(file_path)
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
print(f'\t\t \033[96m --- Processing Data --- \033[0m')
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if file_path.exists() and not reset:
|
|
18
|
+
return read_csv(file_path, parse_dates=['Time'], index_col='Time',
|
|
19
|
+
na_values=('-', 'E', 'F'), low_memory=False)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
processor = [ImpactProc, ChemicalProc, ImproveProc, ParticleSizeDistProc, ExtinctionDistProc, OthersProc]
|
|
22
|
+
reset = [False, False, False, False, False, False]
|
|
23
|
+
save_filename = ['IMPACT.csv', 'chemical.csv', 'revised_IMPROVE.csv', 'PSD.csv', 'PESD.csv', 'Others.csv']
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
_df = concat([processor().process_data(reset, save_filename) for processor, reset, save_filename in
|
|
26
|
+
zip(processor, reset, save_filename)], axis=1)
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
# 7. save result
|
|
29
|
+
_df.to_csv(file_path)
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
return _df
|
AeroViz/process/core/DataProc.py
CHANGED
|
@@ -7,13 +7,13 @@ __all__ = ['DataProc']
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class DataProc(ABC):
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
def __init__(self):
|
|
11
|
+
pass
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def process_data(self,
|
|
15
|
+
reset: bool = False,
|
|
16
|
+
save_filename: str | Path = None
|
|
17
|
+
) -> DataFrame:
|
|
18
|
+
""" Implementation of processing data """
|
|
19
|
+
pass
|