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.

Files changed (107) hide show
  1. AeroViz/__init__.py +4 -4
  2. AeroViz/dataProcess/Chemistry/__init__.py +38 -38
  3. AeroViz/dataProcess/Chemistry/_calculate.py +15 -15
  4. AeroViz/dataProcess/Chemistry/_isoropia.py +69 -68
  5. AeroViz/dataProcess/Chemistry/_mass_volume.py +158 -158
  6. AeroViz/dataProcess/Chemistry/_ocec.py +109 -109
  7. AeroViz/dataProcess/Chemistry/_partition.py +19 -18
  8. AeroViz/dataProcess/Chemistry/_teom.py +8 -11
  9. AeroViz/dataProcess/Optical/_IMPROVE.py +40 -39
  10. AeroViz/dataProcess/Optical/__init__.py +35 -35
  11. AeroViz/dataProcess/Optical/_absorption.py +35 -35
  12. AeroViz/dataProcess/Optical/_extinction.py +25 -24
  13. AeroViz/dataProcess/Optical/_mie.py +5 -6
  14. AeroViz/dataProcess/Optical/_mie_sd.py +89 -90
  15. AeroViz/dataProcess/Optical/_scattering.py +16 -16
  16. AeroViz/dataProcess/SizeDistr/__init__.py +37 -37
  17. AeroViz/dataProcess/SizeDistr/__merge.py +159 -158
  18. AeroViz/dataProcess/SizeDistr/_merge.py +155 -154
  19. AeroViz/dataProcess/SizeDistr/_merge_v1.py +162 -161
  20. AeroViz/dataProcess/SizeDistr/_merge_v2.py +153 -152
  21. AeroViz/dataProcess/SizeDistr/_merge_v3.py +326 -326
  22. AeroViz/dataProcess/SizeDistr/_merge_v4.py +272 -274
  23. AeroViz/dataProcess/SizeDistr/_size_distr.py +51 -51
  24. AeroViz/dataProcess/VOC/__init__.py +7 -7
  25. AeroViz/dataProcess/VOC/_potential_par.py +53 -55
  26. AeroViz/dataProcess/__init__.py +4 -4
  27. AeroViz/dataProcess/core/__init__.py +59 -58
  28. AeroViz/plot/__init__.py +6 -1
  29. AeroViz/plot/bar.py +126 -0
  30. AeroViz/plot/box.py +68 -0
  31. AeroViz/plot/distribution/distribution.py +421 -427
  32. AeroViz/plot/meteorology/meteorology.py +240 -292
  33. AeroViz/plot/optical/__init__.py +0 -1
  34. AeroViz/plot/optical/optical.py +230 -230
  35. AeroViz/plot/pie.py +198 -0
  36. AeroViz/plot/regression.py +210 -0
  37. AeroViz/plot/scatter.py +99 -0
  38. AeroViz/plot/templates/__init__.py +0 -3
  39. AeroViz/plot/templates/contour.py +25 -25
  40. AeroViz/plot/templates/corr_matrix.py +86 -93
  41. AeroViz/plot/templates/diurnal_pattern.py +24 -24
  42. AeroViz/plot/templates/koschmieder.py +106 -106
  43. AeroViz/plot/templates/metal_heatmap.py +34 -34
  44. AeroViz/plot/timeseries/timeseries.py +53 -60
  45. AeroViz/plot/utils/__init__.py +2 -1
  46. AeroViz/plot/utils/_color.py +57 -57
  47. AeroViz/plot/utils/_unit.py +48 -48
  48. AeroViz/plot/utils/plt_utils.py +92 -0
  49. AeroViz/plot/utils/sklearn_utils.py +49 -0
  50. AeroViz/plot/violin.py +79 -0
  51. AeroViz/process/__init__.py +15 -15
  52. AeroViz/process/core/DataProc.py +9 -9
  53. AeroViz/process/core/SizeDist.py +81 -81
  54. AeroViz/process/method/PyMieScatt_update.py +488 -488
  55. AeroViz/process/method/mie_theory.py +231 -229
  56. AeroViz/process/method/prop.py +40 -40
  57. AeroViz/process/script/AbstractDistCalc.py +103 -103
  58. AeroViz/process/script/Chemical.py +166 -166
  59. AeroViz/process/script/IMPACT.py +40 -40
  60. AeroViz/process/script/IMPROVE.py +152 -152
  61. AeroViz/process/script/Others.py +45 -45
  62. AeroViz/process/script/PSD.py +26 -26
  63. AeroViz/process/script/PSD_dry.py +69 -70
  64. AeroViz/process/script/retrieve_RI.py +50 -51
  65. AeroViz/rawDataReader/__init__.py +57 -57
  66. AeroViz/rawDataReader/core/__init__.py +328 -326
  67. AeroViz/rawDataReader/script/AE33.py +18 -18
  68. AeroViz/rawDataReader/script/AE43.py +20 -20
  69. AeroViz/rawDataReader/script/APS_3321.py +30 -30
  70. AeroViz/rawDataReader/script/Aurora.py +23 -23
  71. AeroViz/rawDataReader/script/BC1054.py +40 -40
  72. AeroViz/rawDataReader/script/EPA_vertical.py +9 -9
  73. AeroViz/rawDataReader/script/GRIMM.py +21 -21
  74. AeroViz/rawDataReader/script/IGAC_TH.py +67 -67
  75. AeroViz/rawDataReader/script/IGAC_ZM.py +59 -59
  76. AeroViz/rawDataReader/script/MA350.py +39 -39
  77. AeroViz/rawDataReader/script/NEPH.py +74 -74
  78. AeroViz/rawDataReader/script/OCEC_LCRES.py +21 -21
  79. AeroViz/rawDataReader/script/OCEC_RES.py +16 -16
  80. AeroViz/rawDataReader/script/SMPS_TH.py +25 -25
  81. AeroViz/rawDataReader/script/SMPS_aim11.py +32 -32
  82. AeroViz/rawDataReader/script/SMPS_genr.py +31 -31
  83. AeroViz/rawDataReader/script/TEOM.py +28 -28
  84. AeroViz/rawDataReader/script/Table.py +12 -12
  85. AeroViz/rawDataReader/script/VOC_TH.py +16 -16
  86. AeroViz/rawDataReader/script/VOC_ZM.py +28 -28
  87. AeroViz/rawDataReader/script/__init__.py +20 -20
  88. AeroViz/rawDataReader/utils/config.py +161 -161
  89. AeroViz/tools/database.py +65 -65
  90. AeroViz/tools/dataclassifier.py +106 -106
  91. AeroViz/tools/dataprinter.py +51 -51
  92. AeroViz/tools/datareader.py +38 -38
  93. {AeroViz-0.1.3.dist-info → AeroViz-0.1.3b0.dist-info}/METADATA +5 -4
  94. AeroViz-0.1.3b0.dist-info/RECORD +110 -0
  95. AeroViz/config/__init__.py +0 -0
  96. AeroViz/plot/improve/__init__.py +0 -1
  97. AeroViz/plot/improve/improve.py +0 -240
  98. AeroViz/plot/optical/aethalometer.py +0 -77
  99. AeroViz/plot/templates/event_evolution.py +0 -65
  100. AeroViz/plot/templates/regression.py +0 -256
  101. AeroViz/plot/templates/scatter.py +0 -130
  102. AeroViz/plot/templates/templates.py +0 -398
  103. AeroViz/plot/utils/_decorator.py +0 -74
  104. AeroViz-0.1.3.dist-info/RECORD +0 -111
  105. {AeroViz-0.1.3.dist-info → AeroViz-0.1.3b0.dist-info}/LICENSE +0 -0
  106. {AeroViz-0.1.3.dist-info → AeroViz-0.1.3b0.dist-info}/WHEEL +0 -0
  107. {AeroViz-0.1.3.dist-info → AeroViz-0.1.3b0.dist-info}/top_level.txt +0 -0
@@ -2,79 +2,79 @@ __all__ = ['_basic']
2
2
 
3
3
 
4
4
  def _geometric_prop(_dp, _prop):
5
- import numpy as n
5
+ import numpy as n
6
6
 
7
- _prop_t = _prop.sum(axis=1)
8
- _prop_t = _prop_t.where(_prop_t > 0).copy()
7
+ _prop_t = _prop.sum(axis=1)
8
+ _prop_t = _prop_t.where(_prop_t > 0).copy()
9
9
 
10
- _dp = n.log(_dp)
11
- _gmd = (((_prop * _dp).sum(axis=1)) / _prop_t.copy())
10
+ _dp = n.log(_dp)
11
+ _gmd = (((_prop * _dp).sum(axis=1)) / _prop_t.copy())
12
12
 
13
- _dp_mesh, _gmd_mesh = n.meshgrid(_dp, _gmd)
14
- _gsd = ((((_dp_mesh - _gmd_mesh) ** 2) * _prop).sum(axis=1) / _prop_t.copy()) ** .5
13
+ _dp_mesh, _gmd_mesh = n.meshgrid(_dp, _gmd)
14
+ _gsd = ((((_dp_mesh - _gmd_mesh) ** 2) * _prop).sum(axis=1) / _prop_t.copy()) ** .5
15
15
 
16
- return _prop_t, _gmd.apply(n.exp), _gsd.apply(n.exp)
16
+ return _prop_t, _gmd.apply(n.exp), _gsd.apply(n.exp)
17
17
 
18
18
 
19
19
  def _basic(df, hybrid, unit, bin_rg, input_type):
20
- import numpy as n
21
- from pandas import DataFrame, concat
20
+ import numpy as n
21
+ from pandas import DataFrame
22
22
 
23
- ## get number conc. data and total, mode
24
- dN = df
25
- dN.columns = dN.keys().to_numpy(float)
23
+ ## get number conc. data and total, mode
24
+ dN = df
25
+ dN.columns = dN.keys().to_numpy(float)
26
26
 
27
- dN_ky = dN.keys()[(dN.keys() >= bin_rg[0]) & (dN.keys() <= bin_rg[-1])]
28
- dN = dN[dN_ky].copy()
27
+ dN_ky = dN.keys()[(dN.keys() >= bin_rg[0]) & (dN.keys() <= bin_rg[-1])]
28
+ dN = dN[dN_ky].copy()
29
29
 
30
- out_dic = {}
31
- ## diameter
32
- dp = dN.keys().to_numpy()
33
- if hybrid:
34
- dlog_dp = n.diff(n.log10(dp)).mean()
35
- else:
36
- dlog_dp = n.ones(dp.size)
37
- dlog_dp[:hybrid] = n.diff(n.log10(dp[:hybrid])).mean()
38
- dlog_dp[hybrid:] = n.diff(n.log10(dp[hybrid:])).mean()
30
+ out_dic = {}
31
+ ## diameter
32
+ dp = dN.keys().to_numpy()
33
+ if hybrid:
34
+ dlog_dp = n.diff(n.log10(dp)).mean()
35
+ else:
36
+ dlog_dp = n.ones(dp.size)
37
+ dlog_dp[:hybrid] = n.diff(n.log10(dp[:hybrid])).mean()
38
+ dlog_dp[hybrid:] = n.diff(n.log10(dp[hybrid:])).mean()
39
39
 
40
- ## calculate normalize and non-normalize data
41
- if input_type == 'norm':
42
- out_dic['number'] = (dN * dlog_dp).copy()
43
- out_dic['number_norm'] = dN.copy()
44
- else:
45
- out_dic['number'] = dN.copy()
46
- out_dic['number_norm'] = (dN / dlog_dp).copy()
40
+ ## calculate normalize and non-normalize data
41
+ if input_type == 'norm':
42
+ out_dic['number'] = (dN * dlog_dp).copy()
43
+ out_dic['number_norm'] = dN.copy()
44
+ else:
45
+ out_dic['number'] = dN.copy()
46
+ out_dic['number_norm'] = (dN / dlog_dp).copy()
47
47
 
48
- out_dic['surface'] = out_dic['number'] * n.pi * dp ** 2
49
- out_dic['volume'] = out_dic['number'] * n.pi * (dp ** 3) / 6
48
+ out_dic['surface'] = out_dic['number'] * n.pi * dp ** 2
49
+ out_dic['volume'] = out_dic['number'] * n.pi * (dp ** 3) / 6
50
50
 
51
- out_dic['surface_norm'] = out_dic['number_norm'] * n.pi * dp ** 2
52
- out_dic['volume_norm'] = out_dic['number_norm'] * n.pi * (dp ** 3) / 6
51
+ out_dic['surface_norm'] = out_dic['number_norm'] * n.pi * dp ** 2
52
+ out_dic['volume_norm'] = out_dic['number_norm'] * n.pi * (dp ** 3) / 6
53
53
 
54
- ## size range mode process
55
- df_oth = DataFrame(index=dN.index)
54
+ ## size range mode process
55
+ df_oth = DataFrame(index=dN.index)
56
56
 
57
- bound = n.array([(dp.min(), dp.max() + 1), (10, 25), (25, 100), (100, 1e3), (1e3, 2.5e3), ])
58
- if unit == 'um':
59
- bound[1:] /= 1e3
57
+ bound = n.array([(dp.min(), dp.max() + 1), (10, 25), (25, 100), (100, 1e3), (1e3, 2.5e3), ])
58
+ if unit == 'um':
59
+ bound[1:] /= 1e3
60
60
 
61
- for _tp_nam, _tp_dt in zip(['num', 'surf', 'vol'], [out_dic['number'], out_dic['surface'], out_dic['volume']]):
61
+ for _tp_nam, _tp_dt in zip(['num', 'surf', 'vol'], [out_dic['number'], out_dic['surface'], out_dic['volume']]):
62
62
 
63
- for _md_nam, _range in zip(['all', 'Nucleation', 'Aitken', 'Accumulation', 'Coarse'], bound):
63
+ for _md_nam, _range in zip(['all', 'Nucleation', 'Aitken', 'Accumulation', 'Coarse'], bound):
64
64
 
65
- _dia = dp[(dp >= _range[0]) & (dp < _range[-1])]
66
- if ~_dia.any(): continue
65
+ _dia = dp[(dp >= _range[0]) & (dp < _range[-1])]
66
+ if ~_dia.any(): continue
67
67
 
68
- _dt = _tp_dt[_dia].copy()
68
+ _dt = _tp_dt[_dia].copy()
69
69
 
70
- df_oth[f'total_{_tp_nam}_{_md_nam}'], df_oth[f'GMD_{_tp_nam}_{_md_nam}'], df_oth[
71
- f'GSD_{_tp_nam}_{_md_nam}'] = _geometric_prop(_dia, _dt)
72
- df_oth[f'mode_{_tp_nam}_{_md_nam}'] = _dt.idxmax(axis=1)
70
+ df_oth[f'total_{_tp_nam}_{_md_nam}'], df_oth[f'GMD_{_tp_nam}_{_md_nam}'], df_oth[
71
+ f'GSD_{_tp_nam}_{_md_nam}'] = _geometric_prop(_dia, _dt)
72
+ df_oth[f'mode_{_tp_nam}_{_md_nam}'] = _dt.idxmax(axis=1)
73
73
 
74
- ## out
75
- out_dic['other'] = df_oth
74
+ ## out
75
+ out_dic['other'] = df_oth
76
76
 
77
- return out_dic
77
+ return out_dic
78
78
 
79
79
  # old 20230113
80
80
 
@@ -2,18 +2,18 @@ from ..core import _writter, _run_process
2
2
 
3
3
  __all__ = [
4
4
 
5
- 'VOC',
5
+ 'VOC',
6
6
 
7
7
  ]
8
8
 
9
9
 
10
10
  class VOC(_writter):
11
11
 
12
- ## Reconstruction
13
- @_run_process('VOC - basic', 'voc_basic')
14
- def VOC_basic(self, _df_voc):
15
- from ._potential_par import _basic
12
+ ## Reconstruction
13
+ @_run_process('VOC - basic', 'voc_basic')
14
+ def VOC_basic(self, _df_voc):
15
+ from ._potential_par import _basic
16
16
 
17
- out = _basic(_df_voc)
17
+ out = _basic(_df_voc)
18
18
 
19
- return self, out
19
+ return self, out
@@ -1,76 +1,74 @@
1
- from datetime import datetime as dtm
2
- from pandas import DataFrame, to_datetime, read_json
3
- from pathlib import Path
4
1
  import pickle as pkl
2
+ from pathlib import Path
5
3
 
6
- import numpy as np
4
+ from pandas import DataFrame, read_json
7
5
 
8
6
 
9
7
  def _basic(_df_voc):
10
- ## parameter
11
- _keys = _df_voc.keys()
8
+ ## parameter
9
+ _keys = _df_voc.keys()
12
10
 
13
- with (Path(__file__).parent / 'voc_par.pkl').open('rb') as f:
14
- _par = pkl.load(f)
15
- _MW, _MIR, _SOAP, _KOH = _par.loc['MW', _keys], _par.loc['MIR', _keys], _par.loc['SOAP', _keys], _par.loc[
16
- 'KOH', _keys]
11
+ with (Path(__file__).parent / 'voc_par.pkl').open('rb') as f:
12
+ _par = pkl.load(f)
13
+ _MW, _MIR, _SOAP, _KOH = _par.loc['MW', _keys], _par.loc['MIR', _keys], _par.loc['SOAP', _keys], _par.loc[
14
+ 'KOH', _keys]
17
15
 
18
- with (Path(__file__).parent / 'voc_par.json').open('r', encoding='utf-8', errors='ignore') as f:
19
- _parr = read_json(f)
20
- _MW, _MIR, _SOAP, _KOH = _par.loc['MW', _keys], _par.loc['MIR', _keys], _par.loc['SOAP', _keys], _par.loc[
21
- 'KOH', _keys]
16
+ with (Path(__file__).parent / 'voc_par.json').open('r', encoding='utf-8', errors='ignore') as f:
17
+ _parr = read_json(f)
18
+ _MW, _MIR, _SOAP, _KOH = _par.loc['MW', _keys], _par.loc['MIR', _keys], _par.loc['SOAP', _keys], _par.loc[
19
+ 'KOH', _keys]
22
20
 
23
- _voc_clasfy = {
24
- 'alkane_total': ['Isopentane', 'n-Butane', '2-Methylhexane', 'Cyclopentane', '3-Methylpentane',
25
- '2,3-Dimethylbutane',
26
- '2-Methylheptane', 'n-Nonane', 'Methylcyclohexane', '2,4-Dimethylpentane', '2-Methylpentane',
27
- 'n-Decane',
28
- 'n-Heptane', 'Cyclohexane', 'n-Octane', 'Isobutane', '2,2-Dimethylbutane',
29
- 'Methylcyclopentane', 'n-Hexane',
30
- '2,3,4-Trimethylpentane', '3-Methylhexane', 'n-Undecane', '3-Methylheptane', 'Hexane',
31
- '2,2,4-Trimethylpentane', 'n-Pentane', 'Ethane', 'Propane'],
21
+ _voc_clasfy = {
22
+ 'alkane_total': ['Isopentane', 'n-Butane', '2-Methylhexane', 'Cyclopentane', '3-Methylpentane',
23
+ '2,3-Dimethylbutane',
24
+ '2-Methylheptane', 'n-Nonane', 'Methylcyclohexane', '2,4-Dimethylpentane', '2-Methylpentane',
25
+ 'n-Decane',
26
+ 'n-Heptane', 'Cyclohexane', 'n-Octane', 'Isobutane', '2,2-Dimethylbutane',
27
+ 'Methylcyclopentane', 'n-Hexane',
28
+ '2,3,4-Trimethylpentane', '3-Methylhexane', 'n-Undecane', '3-Methylheptane', 'Hexane',
29
+ '2,2,4-Trimethylpentane', 'n-Pentane', 'Ethane', 'Propane'],
32
30
 
33
- 'alkane_total': ['Isoprene', '1-Butene', 'cis-2-Butene', 'Propene', '1.3-Butadiene',
34
- 't-2-Butene', 'cis-2-Pentene', 'Propylene', 'isoprene', '1-Pentene',
35
- 'Ethylene', 't-2-Pentene', '1-Octene'],
31
+ 'alkane_total': ['Isoprene', '1-Butene', 'cis-2-Butene', 'Propene', '1.3-Butadiene',
32
+ 't-2-Butene', 'cis-2-Pentene', 'Propylene', 'isoprene', '1-Pentene',
33
+ 'Ethylene', 't-2-Pentene', '1-Octene'],
36
34
 
37
- 'aromatic_total': ['o-Ethyltoluene', '1,3,5-Trimethylbenzene', 'Ethylbenzene', 'm,p-Xylene', 'n-Propylbenzene',
38
- 'Benzene', 'Toluene', '1.2.4-TMB', 'Styrene', 'p-Ethyltoluene', 'o-Xylene',
39
- 'm-Diethylbenzene',
40
- '1.2.3-TMB', 'Isopropylbenzene', 'm-Ethyltoluene', '2-Ethyltoluene', '1.3.5-TMB',
41
- 'Iso-Propylbenzene',
42
- '3.4-Ethyltoluene', 'p-Diethylbenzene', '1,2,4-Trimethylbenzene', 'm.p-Xylene',
43
- '1,2,3-Trimethylbenzene'],
35
+ 'aromatic_total': ['o-Ethyltoluene', '1,3,5-Trimethylbenzene', 'Ethylbenzene', 'm,p-Xylene', 'n-Propylbenzene',
36
+ 'Benzene', 'Toluene', '1.2.4-TMB', 'Styrene', 'p-Ethyltoluene', 'o-Xylene',
37
+ 'm-Diethylbenzene',
38
+ '1.2.3-TMB', 'Isopropylbenzene', 'm-Ethyltoluene', '2-Ethyltoluene', '1.3.5-TMB',
39
+ 'Iso-Propylbenzene',
40
+ '3.4-Ethyltoluene', 'p-Diethylbenzene', '1,2,4-Trimethylbenzene', 'm.p-Xylene',
41
+ '1,2,3-Trimethylbenzene'],
44
42
 
45
- 'alkyne_total': ['Acetylene'],
43
+ 'alkyne_total': ['Acetylene'],
46
44
 
47
- 'OVOC': ['Acetaldehyde', 'Ethanol', 'Acetone', 'IPA', 'Ethyl Acetate', 'Butyl Acetate'],
45
+ 'OVOC': ['Acetaldehyde', 'Ethanol', 'Acetone', 'IPA', 'Ethyl Acetate', 'Butyl Acetate'],
48
46
 
49
- 'ClVOC': ['VCM', 'TCE', 'PCE', '1.4-DCB', '1.2-DCB'],
50
- }
47
+ 'ClVOC': ['VCM', 'TCE', 'PCE', '1.4-DCB', '1.2-DCB'],
48
+ }
51
49
 
52
- _df_MW = (_df_voc * _MW).copy()
53
- _df_dic = {
54
- 'Conc': _df_voc.copy(),
55
- 'OFP': _df_MW / 48 * _MIR,
56
- 'SOAP': _df_MW / 24.5 * _SOAP / 100 * 0.054,
57
- 'LOH': _df_MW / 24.5 / _MW * 0.602 * _KOH,
58
- }
50
+ _df_MW = (_df_voc * _MW).copy()
51
+ _df_dic = {
52
+ 'Conc': _df_voc.copy(),
53
+ 'OFP': _df_MW / 48 * _MIR,
54
+ 'SOAP': _df_MW / 24.5 * _SOAP / 100 * 0.054,
55
+ 'LOH': _df_MW / 24.5 / _MW * 0.602 * _KOH,
56
+ }
59
57
 
60
- ## calculate
61
- _out = {}
62
- for _nam, _df in _df_dic.items():
58
+ ## calculate
59
+ _out = {}
60
+ for _nam, _df in _df_dic.items():
63
61
 
64
- _df_out = DataFrame(index=_df_voc.index)
62
+ _df_out = DataFrame(index=_df_voc.index)
65
63
 
66
- for _voc_nam, _voc_lst in _voc_clasfy.items():
67
- _lst = list(set(_keys) & set(_voc_lst))
68
- if len(_lst) == 0: continue
64
+ for _voc_nam, _voc_lst in _voc_clasfy.items():
65
+ _lst = list(set(_keys) & set(_voc_lst))
66
+ if len(_lst) == 0: continue
69
67
 
70
- _df_out[_voc_nam] = _df[_lst].sum(axis=1, min_count=1)
68
+ _df_out[_voc_nam] = _df[_lst].sum(axis=1, min_count=1)
71
69
 
72
- _df_out['Total'] = _df.sum(axis=1, min_count=1)
70
+ _df_out['Total'] = _df.sum(axis=1, min_count=1)
73
71
 
74
- _out[_nam] = _df_out
72
+ _out[_nam] = _df_out
75
73
 
76
- return _out
74
+ return _out
@@ -4,8 +4,8 @@ from .SizeDistr import SizeDistr
4
4
  from .VOC import VOC
5
5
 
6
6
  __all__ = [
7
- 'Optical',
8
- 'SizeDistr',
9
- 'Chemistry',
10
- 'VOC',
7
+ 'Optical',
8
+ 'SizeDistr',
9
+ 'Chemistry',
10
+ 'VOC',
11
11
  ]
@@ -1,92 +1,93 @@
1
- from pandas import DatetimeIndex, DataFrame, concat
2
- from pathlib import Path
3
1
  import pickle as pkl
4
2
  from datetime import datetime as dtm
3
+ from pathlib import Path
4
+
5
+ from pandas import concat
5
6
 
6
7
 
7
8
  class _writter:
8
9
 
9
- def __init__(self, path_out=None, excel=True, csv=False):
10
+ def __init__(self, path_out=None, excel=True, csv=False):
10
11
 
11
- self.path_out = Path(path_out) if path_out is not None else path_out
12
- self.excel = excel
13
- self.csv = csv
12
+ self.path_out = Path(path_out) if path_out is not None else path_out
13
+ self.excel = excel
14
+ self.csv = csv
14
15
 
15
- def _pre_process(self, _out):
16
+ def _pre_process(self, _out):
16
17
 
17
- if type(_out) == dict:
18
- for _ky, _df in _out.items():
19
- _df.index.name = 'time'
20
- else:
21
- _out.index.name = 'time'
18
+ if type(_out) == dict:
19
+ for _ky, _df in _out.items():
20
+ _df.index.name = 'time'
21
+ else:
22
+ _out.index.name = 'time'
22
23
 
23
- return _out
24
+ return _out
24
25
 
25
- def _save_out(self, _nam, _out):
26
+ def _save_out(self, _nam, _out):
26
27
 
27
- _check = True
28
- while _check:
28
+ _check = True
29
+ while _check:
29
30
 
30
- try:
31
- if self.path_out is not None:
32
- self.path_out.mkdir(exist_ok=True, parents=True)
33
- with (self.path_out / f'{_nam}.pkl').open('wb') as f:
34
- pkl.dump(_out, f, protocol=pkl.HIGHEST_PROTOCOL)
31
+ try:
32
+ if self.path_out is not None:
33
+ self.path_out.mkdir(exist_ok=True, parents=True)
34
+ with (self.path_out / f'{_nam}.pkl').open('wb') as f:
35
+ pkl.dump(_out, f, protocol=pkl.HIGHEST_PROTOCOL)
35
36
 
36
- if self.excel:
37
- from pandas import ExcelWriter
38
- with ExcelWriter(self.path_out / f'{_nam}.xlsx') as f:
39
- if type(_out) == dict:
40
- for _key, _val in _out.items():
41
- _val.to_excel(f, sheet_name=f'{_key}')
42
- else:
43
- _out.to_excel(f, sheet_name=f'{_nam}')
37
+ if self.excel:
38
+ from pandas import ExcelWriter
39
+ with ExcelWriter(self.path_out / f'{_nam}.xlsx') as f:
40
+ if type(_out) == dict:
41
+ for _key, _val in _out.items():
42
+ _val.to_excel(f, sheet_name=f'{_key}')
43
+ else:
44
+ _out.to_excel(f, sheet_name=f'{_nam}')
44
45
 
45
- if self.csv:
46
- if type(_out) == dict:
47
- _path_out = self.path_out / _nam
48
- _path_out.mkdir(exist_ok=True, parents=True)
46
+ if self.csv:
47
+ if type(_out) == dict:
48
+ _path_out = self.path_out / _nam
49
+ _path_out.mkdir(exist_ok=True, parents=True)
49
50
 
50
- for _key, _val in _out.items():
51
- _val.to_csv(_path_out / f'{_key}.csv')
52
- else:
53
- _out.to_csv(self.path_out / f'{_nam}.csv')
51
+ for _key, _val in _out.items():
52
+ _val.to_csv(_path_out / f'{_key}.csv')
53
+ else:
54
+ _out.to_csv(self.path_out / f'{_nam}.csv')
54
55
 
55
- _check = False
56
+ _check = False
56
57
 
57
- except PermissionError as _err:
58
- print('\n', _err)
59
- input('\t\t\33[41m Please Close The File And Press "Enter" \33[0m\n')
58
+ except PermissionError as _err:
59
+ print('\n', _err)
60
+ input('\t\t\33[41m Please Close The File And Press "Enter" \33[0m\n')
60
61
 
61
62
 
62
63
  def _run_process(*_ini_set):
63
- def _decorator(_prcs_fc):
64
- def _wrap(*arg, **kwarg):
65
- _fc_name, _nam = _ini_set
64
+ def _decorator(_prcs_fc):
65
+ def _wrap(*arg, **kwarg):
66
+ _fc_name, _nam = _ini_set
66
67
 
67
- if kwarg.get('nam') is not None:
68
- _nam = kwarg.pop('nam')
68
+ if kwarg.get('nam') is not None:
69
+ _nam = kwarg.pop('nam')
69
70
 
70
- print(f"\n\t{dtm.now().strftime('%m/%d %X')} : Process \033[92m{_fc_name}\033[0m -> {_nam}")
71
+ print(f"\n\t{dtm.now().strftime('%m/%d %X')} : Process \033[92m{_fc_name}\033[0m -> {_nam}")
71
72
 
72
- _class, _out = _prcs_fc(*arg, **kwarg)
73
- _out = _class._pre_process(_out)
73
+ _class, _out = _prcs_fc(*arg, **kwarg)
74
+ _out = _class._pre_process(_out)
74
75
 
75
- _class._save_out(_nam, _out)
76
+ _class._save_out(_nam, _out)
76
77
 
77
- return _out
78
+ return _out
78
79
 
79
- return _wrap
80
+ return _wrap
80
81
 
81
- return _decorator
82
+ return _decorator
82
83
 
83
84
 
84
85
  def _union_index(*_df_arg):
85
- _idx = concat(_df_arg, axis=1).index
86
+ _idx = concat(_df_arg, axis=1).index
86
87
 
87
- # _idx = DatetimeIndex([])
88
+ # _idx = DatetimeIndex([])
88
89
 
89
- # for _df in _df_arg:
90
- # _idx = _idx.union(DataFrame(_df).index)
90
+ # for _df in _df_arg:
91
+ # _idx = _idx.union(DataFrame(_df).index)
91
92
 
92
- return [_df.reindex(_idx) if _df is not None else None for _df in _df_arg]
93
+ return [_df.reindex(_idx) if _df is not None else None for _df in _df_arg]
AeroViz/plot/__init__.py CHANGED
@@ -1,7 +1,12 @@
1
1
  from . import distribution
2
- from . import improve
3
2
  from . import meteorology
4
3
  from . import optical
5
4
  from . import timeseries
5
+ from .bar import bar
6
+ from .box import box
7
+ from .pie import pie, donuts
8
+ from .regression import linear_regression, multiple_linear_regression
9
+ from .scatter import scatter
6
10
  from .templates import *
7
11
  from .utils import *
12
+ from .violin import violin
AeroViz/plot/bar.py ADDED
@@ -0,0 +1,126 @@
1
+ from typing import Literal
2
+
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+ import pandas as pd
6
+ from matplotlib.pyplot import Figure, Axes
7
+ from pandas import DataFrame
8
+
9
+ from AeroViz.plot.utils import *
10
+
11
+ __all__ = ['bar']
12
+
13
+
14
+ @set_figure(fw='bold')
15
+ def bar(data_set: DataFrame | dict,
16
+ data_std: DataFrame | None,
17
+ labels: list[str],
18
+ unit: str,
19
+ style: Literal["stacked", "dispersed"] = "dispersed",
20
+ orientation: Literal["va", "ha"] = 'va',
21
+ ax: Axes | None = None,
22
+ symbol=True,
23
+ **kwargs
24
+ ) -> tuple[Figure, Axes]:
25
+ """
26
+ Parameters
27
+ ----------
28
+ data_set : pd.DataFrame or dict
29
+ A mapping from category names to a list of species mean or a DataFrame with columns as categories and values as means.
30
+ data_std : pd.DataFrame or None
31
+ A DataFrame with standard deviations corresponding to data_set, or None if standard deviations are not provided.
32
+ labels : list of str
33
+ The species names.
34
+ unit : str
35
+ The unit for the values.
36
+ style : {'stacked', 'dispersed'}, default 'dispersed'
37
+ Whether to display the bars stacked or dispersed.
38
+ orientation : {'va', 'ha'}, default 'va'
39
+ The orientation of the bars, 'va' for vertical and 'ha' for horizontal.
40
+ ax : plt.Axes or None, default None
41
+ The Axes object to plot on. If None, a new figure and Axes are created.
42
+ symbol : bool, default True
43
+ Whether to display values for each bar.
44
+ kwargs : dict
45
+ Additional keyword arguments passed to the barplot function.
46
+
47
+ Returns
48
+ -------
49
+ matplotlib.Axes
50
+ The Axes object containing the plot.
51
+
52
+ """
53
+ # data process
54
+ data = data_set.values
55
+
56
+ if data_std is None:
57
+ data_std = np.zeros(data.shape)
58
+ else:
59
+ data_std = data_std.values
60
+
61
+ groups, species = data.shape
62
+ groups_arr = np.arange(groups)
63
+ species_arr = np.arange(species)
64
+
65
+ total = np.array([data.sum(axis=1), ] * species).T
66
+
67
+ pct_data = data / total * 100
68
+ data_cum = pct_data.cumsum(axis=1)
69
+
70
+ # figure info
71
+ category_names = kwargs.get('ticks') or list(data_set.index)
72
+ title = kwargs.get('title', '')
73
+ colors = kwargs.get('colors') or (Color.colors1 if species == 6 else Color.getColor(num=species))
74
+
75
+ fig, ax = plt.subplots(**kwargs.get('fig_kws', {})) if ax is None else (ax.get_figure(), ax)
76
+
77
+ if style == "stacked":
78
+ for i in range(species):
79
+ widths = pct_data[:, i]
80
+ starts = data_cum[:, i] - pct_data[:, i]
81
+
82
+ if orientation == 'va':
83
+ _ = ax.bar(groups_arr, widths, bottom=starts, width=0.7, color=colors[i], label=labels[i],
84
+ edgecolor=None, capsize=None)
85
+ else:
86
+ _ = ax.barh(groups_arr, widths, left=starts, height=0.7, color=colors[i], label=labels[i],
87
+ edgecolor=None, capsize=None)
88
+ if symbol:
89
+ ax.bar_label(_, fmt=auto_label_pct, label_type='center', padding=0, fontsize=8, weight='bold')
90
+
91
+ if style == "dispersed":
92
+ width = 0.1
93
+ block = width / 4
94
+
95
+ for i in range(species):
96
+ val = data[:, i]
97
+ std = (0,) * groups, data_std[:, i]
98
+ if orientation == 'va':
99
+ _ = ax.bar(groups_arr + (i + 1) * (width + block), val, yerr=std, width=width, color=colors[i],
100
+ edgecolor=None, capsize=None)
101
+ else:
102
+ _ = ax.barh(groups_arr + (i + 1) * (width + block), val, xerr=std, height=width, color=colors[i],
103
+ edgecolor=None, capsize=None)
104
+ if symbol:
105
+ ax.bar_label(_, fmt=auto_label_pct, label_type='center', padding=0, fontsize=8, weight='bold')
106
+
107
+ if orientation == 'va':
108
+ xticks = groups_arr + (species / 2 + 0.5) * (width + block) if style == "dispersed" else groups_arr
109
+ ax.set_xticks(xticks, category_names, weight='bold')
110
+ ax.set_ylabel(Unit(unit) if style == "dispersed" else '$Contribution (\\%)$')
111
+ ax.set_ylim(0, None if style == "dispersed" else 100)
112
+ ax.legend(labels, bbox_to_anchor=(1, 1), loc='upper left', prop={'size': 8})
113
+
114
+ if orientation == 'ha':
115
+ ax.invert_yaxis()
116
+ yticks = groups_arr + 3.5 * (width + block) if style == "dispersed" else groups_arr
117
+ ax.set_yticks(yticks, category_names, weight='bold')
118
+ ax.set_xlabel(Unit(unit) if style == "dispersed" else '$Contribution (\\%)$')
119
+ ax.set_xlim(0, None if style == "dispersed" else 100)
120
+ ax.legend(labels, bbox_to_anchor=(1, 1), loc='upper left', prop={'size': 8})
121
+
122
+ # fig.savefig(f"Barplot_{title}")
123
+
124
+ plt.show()
125
+
126
+ return fig, ax
AeroViz/plot/box.py ADDED
@@ -0,0 +1,68 @@
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ import pandas as pd
4
+ from matplotlib.pyplot import Figure, Axes
5
+
6
+ from AeroViz.plot.utils import *
7
+
8
+ __all__ = ['box']
9
+
10
+
11
+ @set_figure
12
+ def box(df: pd.DataFrame,
13
+ x: str,
14
+ y: str,
15
+ x_bins: list | np.ndarray = None,
16
+ add_scatter: bool = True,
17
+ ax: Axes | None = None,
18
+ **kwargs) -> tuple[Figure, Axes]:
19
+ fig, ax = plt.subplots(**kwargs.get('fig_kws', {})) if ax is None else (ax.get_figure(), ax)
20
+
21
+ df = df.dropna(subset=[x, y]).copy()
22
+ x_data, y_data = df[x].to_numpy(), df[y].to_numpy()
23
+
24
+ bins = np.array(x_bins)
25
+ bins = np.round(bins)
26
+ wid = (bins + (bins[1] - bins[0]) / 2)[0:-1]
27
+
28
+ df[x + '_bin'] = pd.cut(x=x_data, bins=bins, labels=wid)
29
+
30
+ group = x + '_bin'
31
+ column = y
32
+ grouped = df.groupby(group, observed=False)
33
+
34
+ names, vals = [], []
35
+
36
+ for i, (name, subdf) in enumerate(grouped):
37
+ names.append('{:.0f}'.format(name))
38
+ vals.append(subdf[column].dropna().values)
39
+
40
+ plt.boxplot(vals, labels=names, positions=wid, widths=(bins[1] - bins[0]) / 3,
41
+ showfliers=False, showmeans=True, meanline=True, patch_artist=True,
42
+ boxprops=dict(facecolor='#f2c872', alpha=.7),
43
+ meanprops=dict(color='#000000', ls='none'),
44
+ medianprops=dict(ls='-', color='#000000'))
45
+
46
+ ax.set(xlim=kwargs.get('xlim', (x_data.min(), x_data.max())),
47
+ ylim=kwargs.get('ylim', (y_data.min(), y_data.max())),
48
+ xlabel=kwargs.get('xlabel', Unit(x)),
49
+ ylabel=kwargs.get('ylabel', Unit(y)),
50
+ title=kwargs.get('title', ''))
51
+
52
+ ax.set_xticks(bins, labels=bins.astype(int))
53
+
54
+ if add_scatter:
55
+ for i, (name, subdf) in enumerate(grouped):
56
+ jitter = np.random.normal(0, 0.5, len(subdf))
57
+ ax.scatter([name] * len(subdf) + jitter, subdf[column], s=10, c='gray', alpha=0.5)
58
+
59
+ plt.show()
60
+
61
+ return fig, ax
62
+
63
+
64
+ if __name__ == '__main__':
65
+ from AeroViz import DataBase
66
+
67
+ df = DataBase(load_data=True)
68
+ box(df, x='PM25', y='Extinction', x_bins=np.arange(0, 120, 10))