AeroViz 0.1.3__py3-none-any.whl → 0.1.3b0__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 +4 -4
- AeroViz/dataProcess/Chemistry/__init__.py +38 -38
- AeroViz/dataProcess/Chemistry/_calculate.py +15 -15
- AeroViz/dataProcess/Chemistry/_isoropia.py +69 -68
- AeroViz/dataProcess/Chemistry/_mass_volume.py +158 -158
- AeroViz/dataProcess/Chemistry/_ocec.py +109 -109
- AeroViz/dataProcess/Chemistry/_partition.py +19 -18
- AeroViz/dataProcess/Chemistry/_teom.py +8 -11
- AeroViz/dataProcess/Optical/_IMPROVE.py +40 -39
- AeroViz/dataProcess/Optical/__init__.py +35 -35
- AeroViz/dataProcess/Optical/_absorption.py +35 -35
- AeroViz/dataProcess/Optical/_extinction.py +25 -24
- AeroViz/dataProcess/Optical/_mie.py +5 -6
- AeroViz/dataProcess/Optical/_mie_sd.py +89 -90
- AeroViz/dataProcess/Optical/_scattering.py +16 -16
- AeroViz/dataProcess/SizeDistr/__init__.py +37 -37
- 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 +326 -326
- AeroViz/dataProcess/SizeDistr/_merge_v4.py +272 -274
- AeroViz/dataProcess/SizeDistr/_size_distr.py +51 -51
- AeroViz/dataProcess/VOC/__init__.py +7 -7
- AeroViz/dataProcess/VOC/_potential_par.py +53 -55
- AeroViz/dataProcess/__init__.py +4 -4
- AeroViz/dataProcess/core/__init__.py +59 -58
- AeroViz/plot/__init__.py +6 -1
- AeroViz/plot/bar.py +126 -0
- AeroViz/plot/box.py +68 -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 +210 -0
- AeroViz/plot/scatter.py +99 -0
- AeroViz/plot/templates/__init__.py +0 -3
- AeroViz/plot/templates/contour.py +25 -25
- AeroViz/plot/templates/corr_matrix.py +86 -93
- AeroViz/plot/templates/diurnal_pattern.py +24 -24
- AeroViz/plot/templates/koschmieder.py +106 -106
- AeroViz/plot/templates/metal_heatmap.py +34 -34
- AeroViz/plot/timeseries/timeseries.py +53 -60
- 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/violin.py +79 -0
- AeroViz/process/__init__.py +15 -15
- 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 +166 -166
- 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 +57 -57
- AeroViz/rawDataReader/core/__init__.py +328 -326
- AeroViz/rawDataReader/script/AE33.py +18 -18
- AeroViz/rawDataReader/script/AE43.py +20 -20
- AeroViz/rawDataReader/script/APS_3321.py +30 -30
- AeroViz/rawDataReader/script/Aurora.py +23 -23
- AeroViz/rawDataReader/script/BC1054.py +40 -40
- AeroViz/rawDataReader/script/EPA_vertical.py +9 -9
- AeroViz/rawDataReader/script/GRIMM.py +21 -21
- AeroViz/rawDataReader/script/IGAC_TH.py +67 -67
- AeroViz/rawDataReader/script/IGAC_ZM.py +59 -59
- AeroViz/rawDataReader/script/MA350.py +39 -39
- AeroViz/rawDataReader/script/NEPH.py +74 -74
- AeroViz/rawDataReader/script/OCEC_LCRES.py +21 -21
- AeroViz/rawDataReader/script/OCEC_RES.py +16 -16
- 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/TEOM.py +28 -28
- AeroViz/rawDataReader/script/Table.py +12 -12
- AeroViz/rawDataReader/script/VOC_TH.py +16 -16
- AeroViz/rawDataReader/script/VOC_ZM.py +28 -28
- AeroViz/rawDataReader/script/__init__.py +20 -20
- AeroViz/rawDataReader/utils/config.py +161 -161
- AeroViz/tools/database.py +65 -65
- 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.3b0.dist-info}/METADATA +5 -4
- AeroViz-0.1.3b0.dist-info/RECORD +110 -0
- AeroViz/config/__init__.py +0 -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-0.1.3.dist-info/RECORD +0 -111
- {AeroViz-0.1.3.dist-info → AeroViz-0.1.3b0.dist-info}/LICENSE +0 -0
- {AeroViz-0.1.3.dist-info → AeroViz-0.1.3b0.dist-info}/WHEEL +0 -0
- {AeroViz-0.1.3.dist-info → AeroViz-0.1.3b0.dist-info}/top_level.txt +0 -0
AeroViz/plot/improve/improve.py
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import matplotlib.pyplot as plt
|
|
2
|
-
import numpy as np
|
|
3
|
-
import pandas as pd
|
|
4
|
-
from matplotlib.pyplot import Figure, Axes
|
|
5
|
-
from pandas import DataFrame, read_json
|
|
6
|
-
from scipy.optimize import curve_fit
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
from AeroViz import plot
|
|
10
|
-
from AeroViz.plot.utils import *
|
|
11
|
-
from AeroViz.tools import DataBase, DataReader, DataClassifier
|
|
12
|
-
|
|
13
|
-
# TODO: this file has to be reorganized
|
|
14
|
-
|
|
15
|
-
__all__ = ['chemical_enhancement',
|
|
16
|
-
'ammonium_rich',
|
|
17
|
-
'pie_IMPROVE',
|
|
18
|
-
'MLR_IMPROVE',
|
|
19
|
-
'fRH_plot',
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@set_figure
|
|
24
|
-
def chemical_enhancement(data_set: DataFrame = None,
|
|
25
|
-
data_std: DataFrame = None,
|
|
26
|
-
ax: Axes | None = None,
|
|
27
|
-
**kwargs
|
|
28
|
-
) -> tuple[Figure, Axes]:
|
|
29
|
-
fig, ax = plt.subplots() if ax is None else (ax.get_figure(), ax)
|
|
30
|
-
|
|
31
|
-
ser_grp_sta, ser_grp_sta_std = DataClassifier(DataBase('/Users/chanchihyu/NTU/2020能見度計畫/data/All_data.csv'),
|
|
32
|
-
by='State')
|
|
33
|
-
species = ['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC', 'ALWC']
|
|
34
|
-
data_set, data_std = ser_grp_sta.loc[:, species], ser_grp_sta_std.loc[:, species]
|
|
35
|
-
|
|
36
|
-
width = 0.20
|
|
37
|
-
block = width / 4
|
|
38
|
-
|
|
39
|
-
x = np.array([1, 2, 3, 4, 5, 6, 7])
|
|
40
|
-
for i, state in enumerate(['Clean', 'Transition', 'Event']):
|
|
41
|
-
val = np.array(data_set.iloc[i, :-1])
|
|
42
|
-
std = (0,) * 7, np.array(data_std.iloc[i, :-1])
|
|
43
|
-
|
|
44
|
-
plt.bar(x + (i + 1) * (width + block), val, yerr=std, width=width, color=Color.colors3[:-1],
|
|
45
|
-
alpha=0.6 + (0.2 * i),
|
|
46
|
-
edgecolor=None, capsize=None, label=state)
|
|
47
|
-
|
|
48
|
-
ax.set(xlabel=r'$\bf Chemical\ species$',
|
|
49
|
-
ylabel=r'$\bf Mass\ concentration\ ({\mu}g/m^3)$',
|
|
50
|
-
xticks=x + 2 * (width + block),
|
|
51
|
-
xticklabels=species,
|
|
52
|
-
ylim=(0, 25),
|
|
53
|
-
title=r'$\bf Chemical\ enhancement$')
|
|
54
|
-
|
|
55
|
-
ax.vlines(8, 0, 25, linestyles='--', colors='k')
|
|
56
|
-
|
|
57
|
-
ax2 = ax.twinx()
|
|
58
|
-
for i, state in enumerate(['Clean', 'Transition', 'Event']):
|
|
59
|
-
val = np.array(data_set.iloc[i, -1])
|
|
60
|
-
std = np.array([[0], [data_std.iloc[i, -1]]])
|
|
61
|
-
plt.bar(8 + (i + 1) * (width + block), val, yerr=std, width=width, color='#96c8e6',
|
|
62
|
-
alpha=0.6 + (0.2 * i), edgecolor=None, capsize=None, label=state)
|
|
63
|
-
|
|
64
|
-
ax2.set(ylabel=r'$\bf Mass\ concentration\ ({\mu}g/m^3)$',
|
|
65
|
-
ylim=(0, 100),
|
|
66
|
-
xticks=x + 2 * (width + block),
|
|
67
|
-
xticklabels=species
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
a = (np.array(data_set.loc['Event']) + np.array(data_set.loc['Transition'])) / 2
|
|
71
|
-
b = (np.array(data_set.loc['Transition']) + np.array(data_set.loc['Clean'])) / 2
|
|
72
|
-
c = np.array(data_set.loc['Event']) / np.array(data_set.loc['Transition'])
|
|
73
|
-
d = np.array(data_set.loc['Transition']) / np.array(data_set.loc['Clean'])
|
|
74
|
-
|
|
75
|
-
for i, (posa, posb, vala, valb) in enumerate(zip(a, b, c, d)):
|
|
76
|
-
if i < 7:
|
|
77
|
-
ax.text(i + 1.5, posa, '{:.2f}'.format(vala), fontsize=6, weight='bold', zorder=1)
|
|
78
|
-
ax.text(i + 1.25, posb, '{:.2f}'.format(valb), fontsize=6, weight='bold', zorder=1)
|
|
79
|
-
else:
|
|
80
|
-
ax2.text(i + 1.5, posa, '{:.2f}'.format(vala), fontsize=6, weight='bold', zorder=1)
|
|
81
|
-
ax2.text(i + 1.25, posb, '{:.2f}'.format(valb), fontsize=6, weight='bold', zorder=1)
|
|
82
|
-
|
|
83
|
-
plt.show()
|
|
84
|
-
|
|
85
|
-
return fig, ax
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
@set_figure
|
|
89
|
-
def ammonium_rich(df: DataFrame,
|
|
90
|
-
**kwargs
|
|
91
|
-
) -> tuple[Figure, Axes]:
|
|
92
|
-
df = df[['NH4+', 'SO42-', 'NO3-', 'PM25']].dropna().copy().div([18, 96, 62, 1])
|
|
93
|
-
df['required_ammonium'] = df['NO3-'] + 2 * df['SO42-']
|
|
94
|
-
|
|
95
|
-
fig, ax = plt.subplots()
|
|
96
|
-
|
|
97
|
-
scatter = ax.scatter(df['required_ammonium'].to_numpy(), df['NH4+'].to_numpy(), c=df['PM25'].to_numpy(),
|
|
98
|
-
vmin=0, vmax=70, cmap='jet', marker='o', s=10, alpha=1)
|
|
99
|
-
|
|
100
|
-
ax.axline((0, 0), slope=1., color='k', lw=2, ls='--', alpha=0.5, label='1:1')
|
|
101
|
-
plt.text(0.97, 0.97, r'$\bf 1:1\ Line$', color='k', ha='right', va='top', transform=ax.transAxes)
|
|
102
|
-
|
|
103
|
-
ax.set(xlim=(0, 1.2),
|
|
104
|
-
ylim=(0, 1.2),
|
|
105
|
-
xlabel=r'$\bf NO_{3}^{-}\ +\ 2\ \times\ SO_{4}^{2-}\ (mole\ m^{-3})$',
|
|
106
|
-
ylabel=r'$\bf NH_{4}^{+}\ (mole\ m^{-3})$',
|
|
107
|
-
title=kwargs.get('title', ''))
|
|
108
|
-
|
|
109
|
-
color_bar = plt.colorbar(scatter, label=Unit('PM25'), extend='both')
|
|
110
|
-
|
|
111
|
-
# fig.savefig(f'Ammonium_rich_{title}')
|
|
112
|
-
plt.show()
|
|
113
|
-
|
|
114
|
-
return fig, ax
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def pie_IMPROVE():
|
|
118
|
-
Species1 = ['AS_ext_dry', 'AN_ext_dry', 'OM_ext_dry', 'Soil_ext_dry', 'SS_ext_dry', 'EC_ext_dry']
|
|
119
|
-
Species2 = ['AS_ext_dry', 'AN_ext_dry', 'OM_ext_dry', 'Soil_ext_dry', 'SS_ext_dry', 'EC_ext_dry', 'ALWC_ext']
|
|
120
|
-
Species3 = ['AS_ext', 'AN_ext', 'OM_ext', 'Soil_ext', 'SS_ext', 'EC_ext']
|
|
121
|
-
|
|
122
|
-
ser_grp_sta, _ = DataClassifier(DataBase(), by='State')
|
|
123
|
-
|
|
124
|
-
ext_dry_dict = ser_grp_sta.loc[:, Species1]
|
|
125
|
-
ext_amb_dict = ser_grp_sta.loc[:, Species2]
|
|
126
|
-
ext_mix_dict = ser_grp_sta.loc[:, Species3]
|
|
127
|
-
|
|
128
|
-
plot.donuts(data_set=ext_dry_dict, labels=['AS', 'AN', 'OM', 'Soil', 'SS', 'BC'], unit='Extinction')
|
|
129
|
-
plot.donuts(data_set=ext_mix_dict, labels=['AS', 'AN', 'OM', 'Soil', 'SS', 'BC'], unit='Extinction')
|
|
130
|
-
plot.donuts(data_set=ext_amb_dict, labels=['AS', 'AN', 'OM', 'Soil', 'SS', 'BC', 'ALWC'],
|
|
131
|
-
unit='Extinction', colors=Color.colors2)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def MLR_IMPROVE(**kwargs):
|
|
135
|
-
"""
|
|
136
|
-
Perform multiple linear regression analysis and generate plots based on IMPROVE dataset.
|
|
137
|
-
|
|
138
|
-
Parameters
|
|
139
|
-
----------
|
|
140
|
-
**kwargs : dict
|
|
141
|
-
Additional keyword arguments for customization.
|
|
142
|
-
|
|
143
|
-
Returns
|
|
144
|
-
-------
|
|
145
|
-
None
|
|
146
|
-
|
|
147
|
-
Examples
|
|
148
|
-
--------
|
|
149
|
-
Example usage of MLR_IMPROVE function:
|
|
150
|
-
|
|
151
|
-
>>> MLR_IMPROVE()
|
|
152
|
-
|
|
153
|
-
Notes
|
|
154
|
-
-----
|
|
155
|
-
This function performs multiple linear regression analysis on the IMPROVE dataset and generates plots for analysis.
|
|
156
|
-
|
|
157
|
-
- The function first selects specific species from the dataset and drops NaN values.
|
|
158
|
-
- It calculates a 'Localized' value based on a multiplier and the sum of selected species.
|
|
159
|
-
- Data from 'modified_IMPROVE.csv' and 'revised_IMPROVE.csv' are read and concatenated with the dataset.
|
|
160
|
-
- Statistical analysis is performed using DataClassifier to calculate mean and standard deviation.
|
|
161
|
-
- Plots are generated using linear_regression for Extinction vs. Revised/Modified/Localized and Pie.donuts for a
|
|
162
|
-
pie chart showing the distribution of species based on Extinction.
|
|
163
|
-
|
|
164
|
-
"""
|
|
165
|
-
species = ['Extinction', 'Scattering', 'Absorption',
|
|
166
|
-
'total_ext_dry', 'AS_ext_dry', 'AN_ext_dry', 'OM_ext_dry', 'Soil_ext_dry', 'SS_ext_dry', 'EC_ext_dry',
|
|
167
|
-
'AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC', 'OM']
|
|
168
|
-
|
|
169
|
-
df = DataBase('/Users/chanchihyu/NTU/2020能見度計畫/data/All_data.csv')[species].dropna().copy()
|
|
170
|
-
|
|
171
|
-
# multiple_linear_regression(df, x=['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS'], y='Scattering', add_constant=True)
|
|
172
|
-
# multiple_linear_regression(df, x=['POC', 'SOC', 'EC'], y='Absorption', add_constant=True)
|
|
173
|
-
# multiple_linear_regression(df, x=['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC'], y='Extinction', add_constant=False)
|
|
174
|
-
|
|
175
|
-
multiplier = [2.675, 4.707, 11.6, 7.272, 0, 0.131, 10.638]
|
|
176
|
-
df['Localized'] = df[['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC']].mul(multiplier).sum(axis=1)
|
|
177
|
-
# TODO: remove name
|
|
178
|
-
modify_IMPROVE = DataReader('modified_IMPROVE.csv')['total_ext_dry'].rename('Modified')
|
|
179
|
-
revised_IMPROVE = DataReader('revised_IMPROVE.csv')['total_ext_dry'].rename('Revised')
|
|
180
|
-
|
|
181
|
-
df = pd.concat([df, revised_IMPROVE, modify_IMPROVE], axis=1)
|
|
182
|
-
|
|
183
|
-
n_df = df[['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC']].mul(multiplier)
|
|
184
|
-
mean, std = DataClassifier(n_df, 'State')
|
|
185
|
-
|
|
186
|
-
ser_grp_sta, _ = DataClassifier(DataBase(), by='State')
|
|
187
|
-
mass_comp = ser_grp_sta.loc[:, ['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC']]
|
|
188
|
-
|
|
189
|
-
# plot
|
|
190
|
-
plot.linear_regression(df, x='Extinction', y=['Revised', 'Modified', 'Localized'], xlim=[0, 400], ylim=[0, 400],
|
|
191
|
-
regression=True, diagonal=True)
|
|
192
|
-
plot.donuts(data_set=mass_comp, labels=['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC'],
|
|
193
|
-
unit='PM25', colors=Color.colors3)
|
|
194
|
-
plot.donuts(mean, labels=['AS', 'AN', 'POC', 'SOC', 'Soil', 'SS', 'EC'], unit='Extinction', colors=Color.colors3)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
@set_figure
|
|
198
|
-
def fRH_plot(**kwargs) -> tuple[Figure, Axes]:
|
|
199
|
-
frh = read_json(Path(__file__).parent.parent / 'utils' / 'fRH.json')
|
|
200
|
-
|
|
201
|
-
def fitting_func(RH, a, b, c):
|
|
202
|
-
f = a + b * (RH / 100) ** c
|
|
203
|
-
return f
|
|
204
|
-
|
|
205
|
-
x = frh.index.to_numpy()
|
|
206
|
-
y = frh['fRHs'].to_numpy()
|
|
207
|
-
|
|
208
|
-
result = curve_fit(fitting_func, x, y)
|
|
209
|
-
params = result[0].tolist()
|
|
210
|
-
val_fit = fitting_func(x, *params)
|
|
211
|
-
|
|
212
|
-
fig, ax = plt.subplots(figsize=(3, 3))
|
|
213
|
-
|
|
214
|
-
ax.plot(frh.index, frh['fRH'], 'k-o', ms=2, label='$f(RH)_{original}$')
|
|
215
|
-
ax.plot(frh.index, frh['fRHs'], 'g-o', ms=2, label='$f(RH)_{small\\ mode}$')
|
|
216
|
-
ax.plot(frh.index, frh['fRHl'], 'r-o', ms=2, label='$f(RH)_{large\\ mode}$')
|
|
217
|
-
ax.plot(frh.index, frh['fRHSS'], 'b-o', ms=2, label='$f(RH)_{sea\\ salt}$')
|
|
218
|
-
|
|
219
|
-
ax.set(xlim=(0, 100),
|
|
220
|
-
ylim=(1, None),
|
|
221
|
-
xlabel='$RH (\\%)$',
|
|
222
|
-
ylabel='$f(RH)$',
|
|
223
|
-
title=f'$Hygroscopic\\ growth\\ factor$'
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
ax.grid(axis='y', color='gray', linestyle='dashed', linewidth=0.4, alpha=0.4)
|
|
227
|
-
|
|
228
|
-
ax.legend()
|
|
229
|
-
|
|
230
|
-
plt.show()
|
|
231
|
-
# fig.savefig('fRH_plot')
|
|
232
|
-
|
|
233
|
-
return fig, ax
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if __name__ == '__main__':
|
|
237
|
-
# chemical_enhancement()
|
|
238
|
-
# MLR_IMPROVE()
|
|
239
|
-
# ammonium_rich()
|
|
240
|
-
fRH_plot()
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import matplotlib.pyplot as plt
|
|
2
|
-
import numpy as np
|
|
3
|
-
from pandas import date_range
|
|
4
|
-
|
|
5
|
-
from AeroViz.plot.utils import *
|
|
6
|
-
|
|
7
|
-
__all__ = ['plot_MA350',
|
|
8
|
-
'plot_MA3502',
|
|
9
|
-
'plot_day_night']
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@set_figure(figsize=(15, 5))
|
|
13
|
-
def plot_MA350(df, **kwargs):
|
|
14
|
-
fig, ax = plt.subplots()
|
|
15
|
-
|
|
16
|
-
# ax.scatter(df.index, df['UV BCc'], marker='o', c='purple', alpha=0.5, label='UV BCc')
|
|
17
|
-
# ax.scatter(df.index, df['Blue BCc'], c='b', alpha=0.5, label='Blue BCc')
|
|
18
|
-
# ax.scatter(df.index, df['Green BCc'], c='g', alpha=0.5, label='Green BCc')
|
|
19
|
-
# ax.scatter(df.index, df['Red BCc'], c='r', alpha=0.5, label='Red BCc')
|
|
20
|
-
mean, std = round(df.mean(), 2), round(df.std(), 2)
|
|
21
|
-
|
|
22
|
-
label1 = rf'$MA350-0171\ :\;{mean["MA350_0171 IR BCc"]}\;\pm\;{std["MA350_0171 IR BCc"]}\;(ng/m^3)$'
|
|
23
|
-
label2 = rf'$MA350-0176\ :\;{mean["MA350_0176 IR BCc"]}\;\pm\;{std["MA350_0176 IR BCc"]}\;(ng/m^3)$'
|
|
24
|
-
label3 = rf'$BC-1054\ :\;{mean["BC1054 IR BCc"]}\;\pm\;{std["BC1054 IR BCc"]}\;(ng/m^3)$'
|
|
25
|
-
ax.scatter(df.index, df['MA350_0171 IR BCc'], s=10, ls='-', marker='o', c='#a3b18a', alpha=0.5, label=label1)
|
|
26
|
-
ax.scatter(df.index, df['MA350_0176 IR BCc'], s=10, ls='-', marker='o', c='#3a5a40', alpha=0.5, label=label2)
|
|
27
|
-
ax.scatter(df.index, df['BC1054 IR BCc'], s=10, ls='-', marker='o', c='g', alpha=0.5, label=label3)
|
|
28
|
-
ax.legend(prop={'weight': 'bold'}, loc='upper left')
|
|
29
|
-
|
|
30
|
-
st_tm, fn_tm = df.index[0], df.index[-1]
|
|
31
|
-
tick_time = date_range(st_tm, fn_tm, freq=kwargs.get('freq', '10d'))
|
|
32
|
-
|
|
33
|
-
ax.set(xlabel=kwargs.get('xlabel', ''),
|
|
34
|
-
ylabel=kwargs.get('ylabel', r'$BC\ (ng/m^3)$'),
|
|
35
|
-
xticks=kwargs.get('xticks', tick_time),
|
|
36
|
-
xticklabels=kwargs.get('xticklabels', [_tm.strftime("%F") for _tm in tick_time]),
|
|
37
|
-
xlim=kwargs.get('xlim', (st_tm, fn_tm)),
|
|
38
|
-
ylim=kwargs.get('ylim', (0, None)),
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@set_figure
|
|
43
|
-
def plot_MA3502(df):
|
|
44
|
-
fig, ax = plt.subplots()
|
|
45
|
-
|
|
46
|
-
bins = np.array([375, 470, 528, 625, 880])
|
|
47
|
-
vals = df.dropna().iloc[:, -5:].values
|
|
48
|
-
|
|
49
|
-
ax.boxplot(vals, positions=bins, widths=20,
|
|
50
|
-
showfliers=False, showmeans=True, meanline=True, patch_artist=True,
|
|
51
|
-
boxprops=dict(facecolor='#f2c872', alpha=.7),
|
|
52
|
-
meanprops=dict(color='#000000', ls='none'),
|
|
53
|
-
medianprops=dict(ls='-', color='#000000'))
|
|
54
|
-
|
|
55
|
-
ax.set(xlim=(355, 900),
|
|
56
|
-
ylim=(0, None),
|
|
57
|
-
xlabel=r'$\lambda\ (nm)$',
|
|
58
|
-
ylabel=r'$Absorption\ (1/Mm)$', )
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
@set_figure(figsize=(6, 5))
|
|
62
|
-
def plot_day_night(df):
|
|
63
|
-
# Group by hour of day and calculate mean
|
|
64
|
-
df_grouped = df.groupby(df.index.hour).mean()
|
|
65
|
-
|
|
66
|
-
# Create figure and plot
|
|
67
|
-
fig, ax = plt.subplots()
|
|
68
|
-
ax.plot(df_grouped.index, df_grouped['MA350_0171 IR BCc'], marker='o', c='k', alpha=0.5, label='MA350-0171')
|
|
69
|
-
ax.plot(df_grouped.index, df_grouped['MA350_0176 IR BCc'], marker='o', c='r', alpha=0.5, label='MA350-0176')
|
|
70
|
-
ax.plot(df_grouped.index, df_grouped['BC1054 IR BCc'], marker='o', c='b', alpha=0.5, label='BC-1054')
|
|
71
|
-
|
|
72
|
-
ax.set(xlim=(0, 23),
|
|
73
|
-
xlabel='Hour of Day',
|
|
74
|
-
ylabel=r'$BC\ (ng/m^3)$',
|
|
75
|
-
title=f'Diurnal pattern', )
|
|
76
|
-
|
|
77
|
-
ax.legend()
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
from os.path import join as pth
|
|
2
|
-
|
|
3
|
-
import matplotlib.pyplot as plt
|
|
4
|
-
import numpy as np
|
|
5
|
-
from pandas import date_range, read_csv
|
|
6
|
-
|
|
7
|
-
from AeroViz.plot.utils import *
|
|
8
|
-
|
|
9
|
-
# TODO:
|
|
10
|
-
|
|
11
|
-
# read csv file
|
|
12
|
-
blh = read_csv(pth('事件分析.csv'), parse_dates=['Time'], index_col='Time')
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@set_figure(figsize=(12, 5))
|
|
16
|
-
def event_evolution(_df, **kwargs):
|
|
17
|
-
print(f'Plot : {_df.month[0]}')
|
|
18
|
-
|
|
19
|
-
st_tm, fn_tm = _df.index[0], _df.index[-1]
|
|
20
|
-
tick_time = date_range(st_tm, fn_tm, freq='1d') # set tick
|
|
21
|
-
|
|
22
|
-
# seperate day and night
|
|
23
|
-
_df_day = _df.between_time('6:00', '17:00').reindex(date_range(st_tm, fn_tm, freq='1h'))
|
|
24
|
-
_df_night = _df.between_time('18:00', '5:00').reindex(date_range(st_tm, fn_tm, freq='1h'))
|
|
25
|
-
|
|
26
|
-
## plot
|
|
27
|
-
fig, ax = plt.subplots()
|
|
28
|
-
|
|
29
|
-
## plot background
|
|
30
|
-
shade_value, _ = np.meshgrid(_df['PM2.5'], np.arange((1., 2500), 100))
|
|
31
|
-
ax.pcolormesh(_df.index, np.arange((1., 2500), 100), shade_value, cmap='binary', vmin=0, vmax=300,
|
|
32
|
-
shading='auto')
|
|
33
|
-
|
|
34
|
-
## plot day and night
|
|
35
|
-
ld = ax.scatter(_df.index[0:], _df_day['Ext'], s=50, c='#73b9ff', label='Day Ext', marker='o', alpha=.7)
|
|
36
|
-
ln = ax.scatter(_df.index[0:], _df_night['Ext'], s=50, c='#00238c', label='Night Ext', marker='o', alpha=.7)
|
|
37
|
-
|
|
38
|
-
ax2 = ax.twinx()
|
|
39
|
-
# ld, = ax2.plot(_df_day['VC'],c='#FF9797',label='day 06:00~18:00')
|
|
40
|
-
# ln, = ax2.plot(_df_night['VC'],c='#FF0000',label='night 18:00~06:00')
|
|
41
|
-
ld2 = ax2.scatter(_df.index, _df_day['VC'], s=50, c='#FF9797', label='Day VC', marker='o', alpha=.5)
|
|
42
|
-
ln2 = ax2.scatter(_df.index, _df_night['VC'], s=50, c='#FF0000', label='Night VC', marker='o', alpha=.5)
|
|
43
|
-
|
|
44
|
-
# add legend on the first axes
|
|
45
|
-
ax.legend(handles=[ld, ln, ld2, ln2], framealpha=0, prop={'weight': 'bold'}, loc='upper left')
|
|
46
|
-
|
|
47
|
-
# add xlabel, ylabel, suptitle
|
|
48
|
-
ax.set(xlabel='Date',
|
|
49
|
-
ylabel='Ext (1/Mm)',
|
|
50
|
-
xlim=(st_tm, fn_tm),
|
|
51
|
-
ylim=(1., 600),
|
|
52
|
-
xticks=tick_time,
|
|
53
|
-
xticklabels=[_tm.strftime("%F %H:00") for _tm in tick_time])
|
|
54
|
-
|
|
55
|
-
ax2.set(ylabel=r'$VC (m^{2}/s)$',
|
|
56
|
-
ylim=(1., 2500))
|
|
57
|
-
|
|
58
|
-
fig.suptitle(f'Event evolution ({st_tm.strftime("%F")}_{fn_tm.strftime("%F")})')
|
|
59
|
-
|
|
60
|
-
# save figure
|
|
61
|
-
fig.savefig(pth(f"event_evolution_{st_tm.strftime("%F")}_{fn_tm.strftime("%F")}"))
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if __name__ == '__main__':
|
|
65
|
-
event_evolution(blh)
|
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import matplotlib.pyplot as plt
|
|
2
|
-
import numpy as np
|
|
3
|
-
import pandas as pd
|
|
4
|
-
from matplotlib.pyplot import Figure, Axes
|
|
5
|
-
from sklearn.linear_model import LinearRegression
|
|
6
|
-
from tabulate import tabulate
|
|
7
|
-
|
|
8
|
-
from AeroViz.plot.utils import *
|
|
9
|
-
|
|
10
|
-
__all__ = [
|
|
11
|
-
'linear_regression',
|
|
12
|
-
'multiple_linear_regression',
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def _linear_regression(x_array: np.ndarray,
|
|
17
|
-
y_array: np.ndarray,
|
|
18
|
-
columns: str | list[str] | None = None,
|
|
19
|
-
positive: bool = True,
|
|
20
|
-
fit_intercept: bool = True):
|
|
21
|
-
if len(x_array.shape) > 1 and x_array.shape[1] >= 2:
|
|
22
|
-
model = LinearRegression(positive=positive, fit_intercept=fit_intercept).fit(x_array, y_array)
|
|
23
|
-
|
|
24
|
-
coefficients = model.coef_[0].round(3)
|
|
25
|
-
intercept = model.intercept_[0].round(3) if fit_intercept else 'None'
|
|
26
|
-
r_square = model.score(x_array, y_array).round(3)
|
|
27
|
-
y_predict = model.predict(x_array)
|
|
28
|
-
|
|
29
|
-
equation = ' + '.join([f'{coeff:.3f} * {col}' for coeff, col in zip(coefficients, columns)])
|
|
30
|
-
equation = equation.replace(' + 0.000 * Const', '') # Remove terms with coefficient 0
|
|
31
|
-
|
|
32
|
-
text = 'y = ' + str(equation) + '\n' + r'$\bf R^2 = $' + str(r_square)
|
|
33
|
-
tab = tabulate([[*coefficients, intercept, r_square]], headers=[*columns, 'intercept', 'R^2'], floatfmt=".3f",
|
|
34
|
-
tablefmt="fancy_grid")
|
|
35
|
-
print('\n' + tab)
|
|
36
|
-
|
|
37
|
-
return text, y_predict, coefficients
|
|
38
|
-
|
|
39
|
-
else:
|
|
40
|
-
x_array = x_array.reshape(-1, 1)
|
|
41
|
-
y_array = y_array.reshape(-1, 1)
|
|
42
|
-
|
|
43
|
-
model = LinearRegression(positive=positive, fit_intercept=fit_intercept).fit(x_array, y_array)
|
|
44
|
-
|
|
45
|
-
slope = model.coef_[0][0].round(3)
|
|
46
|
-
intercept = model.intercept_[0].round(3) if fit_intercept else 'None'
|
|
47
|
-
r_square = model.score(x_array, y_array).round(3)
|
|
48
|
-
y_predict = model.predict(x_array)
|
|
49
|
-
|
|
50
|
-
text = np.poly1d([slope, intercept])
|
|
51
|
-
text = 'y = ' + str(text).replace('\n', "") + '\n' + r'$\bf R^2 = $' + str(r_square)
|
|
52
|
-
|
|
53
|
-
tab = tabulate([[slope, intercept, r_square]], headers=['slope', 'intercept', 'R^2'], floatfmt=".3f",
|
|
54
|
-
tablefmt="fancy_grid")
|
|
55
|
-
print('\n' + tab)
|
|
56
|
-
|
|
57
|
-
return text, y_predict, slope
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@set_figure
|
|
61
|
-
def linear_regression(df: pd.DataFrame,
|
|
62
|
-
x: str | list[str],
|
|
63
|
-
y: str | list[str],
|
|
64
|
-
labels: str | list[str] = None,
|
|
65
|
-
ax: Axes | None = None,
|
|
66
|
-
diagonal=False,
|
|
67
|
-
positive: bool = True,
|
|
68
|
-
fit_intercept: bool = True,
|
|
69
|
-
**kwargs
|
|
70
|
-
) -> tuple[Figure, Axes]:
|
|
71
|
-
"""
|
|
72
|
-
Create a scatter plot with multiple regression lines for the given data.
|
|
73
|
-
|
|
74
|
-
Parameters
|
|
75
|
-
----------
|
|
76
|
-
df : DataFrame
|
|
77
|
-
Input DataFrame containing the data.
|
|
78
|
-
|
|
79
|
-
x : str or list of str
|
|
80
|
-
Column name(s) for the x-axis variable(s).
|
|
81
|
-
|
|
82
|
-
y : str or list of str
|
|
83
|
-
Column name(s) for the y-axis variable(s).
|
|
84
|
-
|
|
85
|
-
labels : str or list of str, optional
|
|
86
|
-
Labels for the y-axis variable(s). If None, column names are used as labels. Default is None.
|
|
87
|
-
|
|
88
|
-
ax : AxesSubplot, optional
|
|
89
|
-
Matplotlib AxesSubplot to use for the plot. If None, a new subplot is created. Default is None.
|
|
90
|
-
|
|
91
|
-
diagonal : bool, optional
|
|
92
|
-
If True, a diagonal line (1:1 line) is added to the plot. Default is False.
|
|
93
|
-
|
|
94
|
-
positive : bool, optional
|
|
95
|
-
Whether to let coefficient positive. Default is True.
|
|
96
|
-
|
|
97
|
-
fit_intercept: bool, optional
|
|
98
|
-
Whether to fit intercept. Default is True.
|
|
99
|
-
|
|
100
|
-
**kwargs
|
|
101
|
-
Additional keyword arguments to customize the plot.
|
|
102
|
-
|
|
103
|
-
Returns
|
|
104
|
-
-------
|
|
105
|
-
AxesSubplot
|
|
106
|
-
Matplotlib AxesSubplot containing the scatter plot.
|
|
107
|
-
|
|
108
|
-
Notes
|
|
109
|
-
-----
|
|
110
|
-
- The function creates a scatter plot with the option to include multiple regression lines.
|
|
111
|
-
- If regression is True, regression lines are fitted for each y variable.
|
|
112
|
-
- Additional customization can be done using the **kwargs.
|
|
113
|
-
|
|
114
|
-
Example
|
|
115
|
-
-------
|
|
116
|
-
>>> linear_regression(df, x='X', y=['Y1', 'Y2'], labels=['Label1', 'Label2'],
|
|
117
|
-
... regression=True, diagonal=True, xlim=(0, 10), ylim=(0, 20),
|
|
118
|
-
... xlabel="X-axis", ylabel="Y-axis", title="Scatter Plot with Regressions")
|
|
119
|
-
"""
|
|
120
|
-
fig, ax = plt.subplots(**kwargs.get('fig_kws', {})) if ax is None else (ax.get_figure(), ax)
|
|
121
|
-
|
|
122
|
-
if not isinstance(x, str):
|
|
123
|
-
x = x[0]
|
|
124
|
-
|
|
125
|
-
if not isinstance(y, list):
|
|
126
|
-
y = [y]
|
|
127
|
-
|
|
128
|
-
if labels is None:
|
|
129
|
-
labels = y
|
|
130
|
-
|
|
131
|
-
df = df.dropna(subset=[x, *y])
|
|
132
|
-
x_array = df[[x]].to_numpy()
|
|
133
|
-
|
|
134
|
-
color_cycle = Color.linecolor
|
|
135
|
-
|
|
136
|
-
handles, text_list = [], []
|
|
137
|
-
|
|
138
|
-
for i, y_var in enumerate(y):
|
|
139
|
-
y_array = df[[y_var]].to_numpy()
|
|
140
|
-
|
|
141
|
-
color = color_cycle[i % len(color_cycle)]
|
|
142
|
-
|
|
143
|
-
scatter = ax.scatter(x_array, y_array, s=25, color=color['face'], edgecolors=color['edge'], alpha=0.8,
|
|
144
|
-
label=labels[i])
|
|
145
|
-
handles.append(scatter)
|
|
146
|
-
|
|
147
|
-
text, y_predict, slope = _linear_regression(x_array, y_array,
|
|
148
|
-
columns=labels[i],
|
|
149
|
-
positive=positive,
|
|
150
|
-
fit_intercept=fit_intercept)
|
|
151
|
-
|
|
152
|
-
text_list.append(f'{labels[i]}: {text}')
|
|
153
|
-
plt.plot(x_array, y_predict, linewidth=3, color=color['line'], alpha=1, zorder=3)
|
|
154
|
-
|
|
155
|
-
ax.set(xlim=kwargs.get('xlim'), ylim=kwargs.get('ylim'), xlabel=Unit(x), ylabel=Unit(y[0]),
|
|
156
|
-
title=kwargs.get('title'))
|
|
157
|
-
|
|
158
|
-
# Add regression info to the legend
|
|
159
|
-
leg = plt.legend(handles=handles, labels=text_list, loc='upper left', prop={'weight': 'bold', 'size': 10})
|
|
160
|
-
|
|
161
|
-
for text, color in zip(leg.get_texts(), [color['line'] for color in color_cycle]):
|
|
162
|
-
text.set_color(color)
|
|
163
|
-
|
|
164
|
-
if diagonal:
|
|
165
|
-
ax.axline((0, 0), slope=1., color='k', lw=2, ls='--', alpha=0.5, label='1:1')
|
|
166
|
-
plt.text(0.97, 0.97, r'$\bf 1:1\ Line$', color='k', ha='right', va='top', transform=ax.transAxes)
|
|
167
|
-
|
|
168
|
-
plt.show()
|
|
169
|
-
|
|
170
|
-
return fig, ax
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
@set_figure
|
|
174
|
-
def multiple_linear_regression(df: pd.DataFrame,
|
|
175
|
-
x: str | list[str],
|
|
176
|
-
y: str | list[str],
|
|
177
|
-
labels: str | list[str] = None,
|
|
178
|
-
ax: Axes | None = None,
|
|
179
|
-
diagonal=False,
|
|
180
|
-
positive: bool = True,
|
|
181
|
-
fit_intercept: bool = True,
|
|
182
|
-
**kwargs
|
|
183
|
-
) -> tuple[Figure, Axes]:
|
|
184
|
-
"""
|
|
185
|
-
Perform multiple linear regression analysis and plot the results.
|
|
186
|
-
|
|
187
|
-
Parameters
|
|
188
|
-
----------
|
|
189
|
-
df : pandas.DataFrame
|
|
190
|
-
Input DataFrame containing the data.
|
|
191
|
-
|
|
192
|
-
x : str or list of str
|
|
193
|
-
Column name(s) for the independent variable(s). Can be a single string or a list of strings.
|
|
194
|
-
|
|
195
|
-
y : str or list of str
|
|
196
|
-
Column name(s) for the dependent variable(s). Can be a single string or a list of strings.
|
|
197
|
-
|
|
198
|
-
labels : str or list of str, optional
|
|
199
|
-
Labels for the dependent variable(s). If None, column names are used as labels. Default is None.
|
|
200
|
-
|
|
201
|
-
ax : matplotlib.axes.Axes or None, optional
|
|
202
|
-
Matplotlib Axes object to use for the plot. If None, a new subplot is created. Default is None.
|
|
203
|
-
|
|
204
|
-
diagonal : bool, optional
|
|
205
|
-
Whether to include a diagonal line (1:1 line) in the plot. Default is False.
|
|
206
|
-
|
|
207
|
-
positive : bool, optional
|
|
208
|
-
Whether to let coefficient positive. Default is True.
|
|
209
|
-
|
|
210
|
-
fit_intercept: bool, optional
|
|
211
|
-
Whether to fit intercept. Default is True.
|
|
212
|
-
|
|
213
|
-
**kwargs
|
|
214
|
-
Additional keyword arguments to customize the plot.
|
|
215
|
-
|
|
216
|
-
Returns
|
|
217
|
-
-------
|
|
218
|
-
matplotlib.axes.Axes
|
|
219
|
-
Matplotlib Axes object containing the regression plot.
|
|
220
|
-
|
|
221
|
-
Notes
|
|
222
|
-
-----
|
|
223
|
-
This function performs multiple linear regression analysis using the input DataFrame.
|
|
224
|
-
It supports multiple independent variables and can plot the regression results.
|
|
225
|
-
|
|
226
|
-
Example
|
|
227
|
-
-------
|
|
228
|
-
>>> multiple_linear_regression(df, x=['X1', 'X2'], y='Y', labels=['Y1', 'Y2'],
|
|
229
|
-
... diagonal=True, add_constant=True,
|
|
230
|
-
... xlabel="X-axis", ylabel="Y-axis", title="Multiple Linear Regression Plot")
|
|
231
|
-
"""
|
|
232
|
-
fig, ax = plt.subplots(**kwargs.get('fig_kws', {})) if ax is None else (ax.get_figure(), ax)
|
|
233
|
-
|
|
234
|
-
if not isinstance(x, list):
|
|
235
|
-
x = [x]
|
|
236
|
-
|
|
237
|
-
if not isinstance(y, str):
|
|
238
|
-
y = y[0]
|
|
239
|
-
|
|
240
|
-
if labels is None:
|
|
241
|
-
labels = x
|
|
242
|
-
|
|
243
|
-
df = df[[*x, y]].dropna()
|
|
244
|
-
x_array = df[[*x]].to_numpy()
|
|
245
|
-
y_array = df[[y]].to_numpy()
|
|
246
|
-
|
|
247
|
-
text, y_predict, coefficients = _linear_regression(x_array, y_array,
|
|
248
|
-
columns=labels,
|
|
249
|
-
positive=positive,
|
|
250
|
-
fit_intercept=fit_intercept)
|
|
251
|
-
|
|
252
|
-
df = pd.DataFrame(np.concatenate([y_array, y_predict], axis=1), columns=['y_actual', 'y_predict'])
|
|
253
|
-
|
|
254
|
-
linear_regression(df, x='y_actual', y='y_predict', ax=ax, regression=True, diagonal=diagonal)
|
|
255
|
-
|
|
256
|
-
return fig, ax
|