AeroViz 0.1.3b0__py3-none-any.whl → 0.1.5__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 (85) hide show
  1. AeroViz/__init__.py +5 -3
  2. AeroViz/{config → data}/DEFAULT_DATA.csv +1 -1
  3. AeroViz/dataProcess/Chemistry/__init__.py +28 -27
  4. AeroViz/dataProcess/Chemistry/_isoropia.py +11 -11
  5. AeroViz/dataProcess/Chemistry/_mass_volume.py +15 -18
  6. AeroViz/dataProcess/Chemistry/_ocec.py +21 -46
  7. AeroViz/dataProcess/Chemistry/_teom.py +2 -1
  8. AeroViz/dataProcess/Chemistry/isrpia.cnf +21 -0
  9. AeroViz/dataProcess/Chemistry/isrpia2.exe +0 -0
  10. AeroViz/dataProcess/Optical/Angstrom_exponent.py +20 -0
  11. AeroViz/dataProcess/Optical/_IMPROVE.py +13 -15
  12. AeroViz/dataProcess/Optical/__init__.py +15 -30
  13. AeroViz/dataProcess/Optical/_absorption.py +21 -47
  14. AeroViz/dataProcess/Optical/_extinction.py +20 -15
  15. AeroViz/dataProcess/Optical/_mie.py +0 -1
  16. AeroViz/dataProcess/Optical/_scattering.py +19 -20
  17. AeroViz/dataProcess/Optical/fRH.pkl +0 -0
  18. AeroViz/dataProcess/SizeDistr/__init__.py +7 -7
  19. AeroViz/dataProcess/SizeDistr/_merge.py +2 -2
  20. AeroViz/dataProcess/SizeDistr/_merge_v1.py +2 -2
  21. AeroViz/dataProcess/SizeDistr/_merge_v2.py +2 -2
  22. AeroViz/dataProcess/SizeDistr/_merge_v3.py +1 -1
  23. AeroViz/dataProcess/SizeDistr/_merge_v4.py +1 -1
  24. AeroViz/dataProcess/VOC/__init__.py +4 -9
  25. AeroViz/dataProcess/VOC/_potential_par.py +71 -37
  26. AeroViz/dataProcess/VOC/{voc_par.json → support_voc.json} +321 -339
  27. AeroViz/dataProcess/__init__.py +28 -6
  28. AeroViz/dataProcess/core/__init__.py +10 -17
  29. AeroViz/plot/__init__.py +1 -1
  30. AeroViz/plot/box.py +2 -1
  31. AeroViz/plot/optical/optical.py +4 -4
  32. AeroViz/plot/regression.py +25 -39
  33. AeroViz/plot/scatter.py +68 -2
  34. AeroViz/plot/templates/__init__.py +2 -1
  35. AeroViz/plot/templates/ammonium_rich.py +34 -0
  36. AeroViz/plot/templates/diurnal_pattern.py +11 -9
  37. AeroViz/plot/templates/koschmieder.py +51 -115
  38. AeroViz/plot/templates/metal_heatmap.py +115 -17
  39. AeroViz/plot/timeseries/__init__.py +1 -0
  40. AeroViz/plot/timeseries/template.py +47 -0
  41. AeroViz/plot/timeseries/timeseries.py +275 -208
  42. AeroViz/plot/utils/plt_utils.py +2 -2
  43. AeroViz/plot/utils/units.json +5 -0
  44. AeroViz/plot/violin.py +9 -8
  45. AeroViz/process/__init__.py +2 -2
  46. AeroViz/process/script/AbstractDistCalc.py +1 -1
  47. AeroViz/process/script/Chemical.py +5 -4
  48. AeroViz/process/script/Others.py +1 -1
  49. AeroViz/rawDataReader/__init__.py +66 -22
  50. AeroViz/rawDataReader/{utils/config.py → config/supported_instruments.py} +33 -54
  51. AeroViz/rawDataReader/core/__init__.py +116 -231
  52. AeroViz/rawDataReader/script/AE33.py +12 -13
  53. AeroViz/rawDataReader/script/AE43.py +10 -13
  54. AeroViz/rawDataReader/script/APS_3321.py +8 -8
  55. AeroViz/rawDataReader/script/Aurora.py +21 -19
  56. AeroViz/rawDataReader/script/BC1054.py +13 -17
  57. AeroViz/rawDataReader/script/EPA_vertical.py +36 -8
  58. AeroViz/rawDataReader/script/GRIMM.py +6 -13
  59. AeroViz/rawDataReader/script/{IGAC_ZM.py → IGAC.py} +18 -18
  60. AeroViz/rawDataReader/script/MA350.py +9 -16
  61. AeroViz/rawDataReader/script/Minion.py +103 -0
  62. AeroViz/rawDataReader/script/NEPH.py +28 -38
  63. AeroViz/rawDataReader/script/SMPS_TH.py +6 -6
  64. AeroViz/rawDataReader/script/SMPS_aim11.py +8 -8
  65. AeroViz/rawDataReader/script/SMPS_genr.py +8 -8
  66. AeroViz/rawDataReader/script/Sunset_OCEC.py +66 -0
  67. AeroViz/rawDataReader/script/TEOM.py +10 -8
  68. AeroViz/rawDataReader/script/Table.py +9 -10
  69. AeroViz/rawDataReader/script/VOC.py +33 -0
  70. AeroViz/rawDataReader/script/__init__.py +10 -12
  71. AeroViz/tools/database.py +7 -9
  72. AeroViz/tools/datareader.py +3 -3
  73. {AeroViz-0.1.3b0.dist-info → AeroViz-0.1.5.dist-info}/METADATA +1 -1
  74. AeroViz-0.1.5.dist-info/RECORD +114 -0
  75. AeroViz/rawDataReader/script/IGAC_TH.py +0 -104
  76. AeroViz/rawDataReader/script/OCEC_LCRES.py +0 -34
  77. AeroViz/rawDataReader/script/OCEC_RES.py +0 -28
  78. AeroViz/rawDataReader/script/VOC_TH.py +0 -30
  79. AeroViz/rawDataReader/script/VOC_ZM.py +0 -37
  80. AeroViz-0.1.3b0.dist-info/RECORD +0 -110
  81. /AeroViz/{config → data}/DEFAULT_PNSD_DATA.csv +0 -0
  82. /AeroViz/rawDataReader/{utils → config}/__init__.py +0 -0
  83. {AeroViz-0.1.3b0.dist-info → AeroViz-0.1.5.dist-info}/LICENSE +0 -0
  84. {AeroViz-0.1.3b0.dist-info → AeroViz-0.1.5.dist-info}/WHEEL +0 -0
  85. {AeroViz-0.1.3b0.dist-info → AeroViz-0.1.5.dist-info}/top_level.txt +0 -0
@@ -1,54 +1,28 @@
1
- def _absCoe(df, abs_band):
2
- import numpy as n
3
- from scipy.optimize import curve_fit
1
+ def _absCoe(df, instru, specified_band: list):
2
+ import numpy as np
3
+ from pandas import concat
4
+ from .Angstrom_exponent import get_Angstrom_exponent, get_species_wavelength
4
5
 
5
- band = n.array([370, 470, 520, 590, 660, 880, 950])
6
+ band_AE33 = np.array([370, 470, 520, 590, 660, 880, 950])
7
+ band_BC1054 = np.array([370, 430, 470, 525, 565, 590, 660, 700, 880, 950])
6
8
 
7
- df_out = {}
9
+ MAE_AE33 = np.array([18.47, 14.54, 13.14, 11.58, 10.35, 7.77, 7.19]) * 1e-3
10
+ MAE_BC1054 = np.array([18.48, 15.90, 14.55, 13.02, 12.10, 11.59, 10.36, 9.77, 7.77, 7.20]) * 1e-3
8
11
 
9
- def _get_slope(__df):
10
- func = lambda _x, _sl, _int: _sl * _x + _int
11
- popt, pcov = curve_fit(func, band, __df.values)
12
+ band = band_AE33 if instru == 'AE33' else band_BC1054
13
+ MAE = MAE_AE33 if instru == 'AE33' else MAE_BC1054
14
+ eBC = 'BC6' if instru == 'AE33' else 'BC9'
12
15
 
13
- return func(n.array(abs_band), *popt)
16
+ # calculate
17
+ df_abs = (df.copy().dropna() * MAE).copy()
14
18
 
15
- MAE = n.array([18.47, 14.54, 13.14, 11.58, 10.35, 7.77, 7.19]) * 1e-3
16
- df_abs = (df.copy() * MAE).dropna().copy()
19
+ df_out = df_abs.apply(get_species_wavelength, axis=1, result_type='expand', args=(specified_band,))
20
+ df_out.columns = [f'abs_{_band}' for _band in specified_band]
21
+ df_out['eBC'] = df[eBC]
17
22
 
18
- df_out = df_abs.apply(_get_slope, axis=1, result_type='expand').reindex(df.index)
19
- df_out.columns = [f'abs_{_band}' for _band in abs_band]
23
+ df_AAE = df_abs.apply(get_Angstrom_exponent, axis=1, result_type='expand', args=(band,))
24
+ df_AAE.columns = ['AAE', 'AAE_intercept']
25
+ df_AAE = df_AAE.mask((-df_AAE['AAE'] < 0.8) | (-df_AAE['AAE'] > 2.)).copy()
20
26
 
21
- df_out['eBC'] = df['BC6']
22
-
23
- return df_out
24
-
25
-
26
- def _AAE(df):
27
- import numpy as n
28
- from scipy.optimize import curve_fit
29
-
30
- def _AAEcalc(_df):
31
- ## parameter
32
- MAE = n.array([18.47, 14.54, 13.14, 11.58, 10.35, 7.77, 7.19]) * 1e-3
33
- band = n.array([370, 470, 520, 590, 660, 880, 950])
34
- _df *= MAE
35
-
36
- ## 7 pts fitting
37
- ## function
38
- def _get_slope(__df):
39
- func = lambda _x, _sl, _int: _sl * _x + _int
40
- popt, pcov = curve_fit(func, n.log(band), n.log(__df))
41
-
42
- return popt
43
-
44
- ## calculate
45
- _AAE = _df.apply(_get_slope, axis=1, result_type='expand')
46
- _AAE.columns = ['slope', 'intercept']
47
-
48
- return _AAE
49
-
50
- df_out = _AAEcalc(df[['BC1', 'BC2', 'BC3', 'BC4', 'BC5', 'BC6', 'BC7']].dropna())
51
- df_out = df_out.mask((-df_out.slope < 0.8) | (-df_out.slope > 2.)).copy()
52
-
53
- df_out['eBC'] = df['BC6']
54
- return df_out.reindex(df.index)
27
+ _df = concat([df_out, df_AAE['AAE']], axis=1)
28
+ return _df.reindex(df.index)
@@ -1,37 +1,42 @@
1
1
  from pandas import DataFrame
2
2
 
3
- from AeroViz.dataProcess.core import _union_index
3
+ from AeroViz.dataProcess.core import union_index
4
4
 
5
5
 
6
- def _basic(df_abs, df_sca, df_ec, df_mass, df_no2):
7
- df_abs, df_sca, df_ec, df_mass, df_no2 = _union_index(df_abs, df_sca, df_ec, df_mass, df_no2)
6
+ def _basic(df_sca, df_abs, df_mass, df_no2, df_temp):
7
+ df_sca, df_abs, df_mass, df_no2, df_temp = union_index(df_sca, df_abs, df_mass, df_no2, df_temp)
8
8
 
9
9
  df_out = DataFrame()
10
10
 
11
- ## abs and sca coe
12
- df_out['abs'] = df_abs.copy()
13
- df_out['sca'] = df_sca.copy()
11
+ # abs and sca coe
12
+ df_out['abs'] = df_abs['abs_550'].copy()
13
+ df_out['sca'] = df_sca['sca_550'].copy()
14
14
 
15
- ## extinction coe.
15
+ # extinction coe.
16
16
  df_out['ext'] = df_out['abs'] + df_out['sca']
17
17
 
18
- ## SSA
18
+ # SSA
19
19
  df_out['SSA'] = df_out['sca'] / df_out['ext']
20
20
 
21
- ## MAE, MSE, MEE
21
+ # SAE, AAE, eBC
22
+ df_out['SAE'] = df_sca['SAE'].copy()
23
+ df_out['AAE'] = df_abs['AAE'].copy()
24
+ df_out['eBC'] = df_abs['eBC'].copy() / 1e3
25
+
26
+ # MAE, MSE, MEE
22
27
  if df_mass is not None:
23
28
  df_out['MAE'] = df_out['abs'] / df_mass
24
29
  df_out['MSE'] = df_out['sca'] / df_mass
25
30
  df_out['MEE'] = df_out['MSE'] + df_out['MAE']
26
31
 
27
- ## gas absorbtion
32
+ # gas absorbtion
28
33
  if df_no2 is not None:
29
34
  df_out['abs_gas'] = df_no2 * .33
30
- df_out['sca_gas'] = 10
31
- df_out['ext_all'] = df_out['ext'] + df_out['abs_gas'] + df_out['sca_gas']
32
35
 
33
- ## other
34
- if df_ec is not None:
35
- df_out['eBC'] = df_ec / 1e3
36
+ if df_temp is not None:
37
+ df_out['sca_gas'] = (11.4 * 293 / (273 + df_temp))
38
+
39
+ if df_no2 is not None and df_temp is not None:
40
+ df_out['ext_all'] = df_out['ext'] + df_out['abs_gas'] + df_out['sca_gas']
36
41
 
37
42
  return df_out
@@ -1,5 +1,4 @@
1
1
  # from PyMieScatt import Mie_SD
2
- # from PyMieScatt import Mie_SD
3
2
 
4
3
  from ._mie_sd import Mie_SD
5
4
 
@@ -1,30 +1,29 @@
1
1
  import numpy as np
2
- from scipy.optimize import curve_fit
2
+ from pandas import concat
3
3
 
4
- __all__ = [
5
- '_SAE',
6
- ]
4
+ __all__ = ['_scaCoe']
7
5
 
8
6
 
9
- def _SAE(df):
10
- def _SAEcalc(_df):
11
- ## parameter
12
- band = np.array([450, 550, 700]) * 1e-3
7
+ def _scaCoe(df, instru, specified_band: list):
8
+ from .Angstrom_exponent import get_Angstrom_exponent, get_species_wavelength
9
+ band_Neph = np.array([450, 550, 700])
10
+ band_Aurora = np.array([450, 525, 635])
13
11
 
14
- ## 3 pts fitting
15
- ## function
16
- def _get_slope(__df):
17
- func = lambda _x, _sl, _int: _sl * _x + _int
18
- popt, pcov = curve_fit(func, np.log(band), np.log(__df))
12
+ band = band_Neph if instru == 'Neph' else band_Aurora
19
13
 
20
- return popt
14
+ df_sca = df.copy().dropna()
21
15
 
22
- ## calculate
23
- _SAE = _df.apply(_get_slope, axis=1, result_type='expand')
24
- _SAE.columns = ['slope', 'intercept']
16
+ if instru == 'Neph':
17
+ df_out = df_sca[['B']].copy()
18
+ df_out.columns = [f'sca_{_band}' for _band in specified_band]
19
+ else:
20
+ df_out = df_sca.apply(get_species_wavelength, axis=1, result_type='expand', args=(specified_band,))
21
+ df_out.columns = [f'sca_{_band}' for _band in specified_band]
25
22
 
26
- return _SAE
23
+ # calculate
24
+ df_SAE = df[['B', 'G', 'R']].dropna().apply(get_Angstrom_exponent, axis=1, result_type='expand', args=(band,))
25
+ df_SAE.columns = ['SAE', 'SAE_intercept']
27
26
 
28
- df_out = _SAEcalc(df[['B', 'G', 'R']].dropna())
27
+ _df = concat([df_out, df_SAE['SAE']], axis=1)
29
28
 
30
- return df_out.reindex(df.index)
29
+ return _df.reindex(df.index)
Binary file
@@ -1,4 +1,4 @@
1
- from ..core import _writter, _run_process
1
+ from ..core import Writer, run_process
2
2
 
3
3
  __all__ = [
4
4
 
@@ -7,10 +7,10 @@ __all__ = [
7
7
  ]
8
8
 
9
9
 
10
- class SizeDistr(_writter):
10
+ class SizeDistr(Writer):
11
11
 
12
12
  ## basic
13
- @_run_process('SizeDistr - basic', 'distr_basic')
13
+ @run_process('SizeDistr - basic', 'distr_basic')
14
14
  def basic(self, df, hybrid_bin_start_loc=None, unit='nm', bin_range=(0, 20000), input_type='norm'):
15
15
  from ._size_distr import _basic
16
16
 
@@ -19,7 +19,7 @@ class SizeDistr(_writter):
19
19
  return self, out
20
20
 
21
21
  ## merge
22
- @_run_process('SizeDistr - merge_SMPS_APS_v4', 'distr_merge')
22
+ @run_process('SizeDistr - merge_SMPS_APS_v4', 'distr_merge')
23
23
  def merge_SMPS_APS_v4(self, df_smps, df_aps, df_pm25, aps_unit='um',
24
24
  smps_overlap_lowbound=500, aps_fit_highbound=1000, dndsdv_alg=True,
25
25
  times_range=(0.8, 1.25, .05)):
@@ -31,7 +31,7 @@ class SizeDistr(_writter):
31
31
  return self, out
32
32
 
33
33
  ## merge
34
- @_run_process('SizeDistr - merge_SMPS_APS_v3', 'distr_merge')
34
+ @run_process('SizeDistr - merge_SMPS_APS_v3', 'distr_merge')
35
35
  def merge_SMPS_APS_v3(self, df_smps, df_aps, aps_unit='um',
36
36
  smps_overlap_lowbound=500, aps_fit_highbound=1000, dndsdv_alg=True):
37
37
  from ._merge_v3 import merge_SMPS_APS
@@ -41,7 +41,7 @@ class SizeDistr(_writter):
41
41
  return self, out
42
42
 
43
43
  ## merge
44
- @_run_process('SizeDistr - merge_SMPS_APS_v2', 'distr_merge')
44
+ @run_process('SizeDistr - merge_SMPS_APS_v2', 'distr_merge')
45
45
  def merge_SMPS_APS_v2(self, df_smps, df_aps, aps_unit='um',
46
46
  smps_overlap_lowbound=500, aps_fit_highbound=1000):
47
47
  from ._merge_v2 import merge_SMPS_APS
@@ -51,7 +51,7 @@ class SizeDistr(_writter):
51
51
  return self, out
52
52
 
53
53
  ## merge
54
- @_run_process('SizeDistr - merge_SMPS_APS_v1', 'distr_merge')
54
+ @run_process('SizeDistr - merge_SMPS_APS_v1', 'distr_merge')
55
55
  def merge_SMPS_APS(self, df_smps, df_aps, aps_unit='um', shift_mode='mobility',
56
56
  smps_overlap_lowbound=523, aps_fit_highbound=800):
57
57
  from ._merge_v1 import _merge_SMPS_APS
@@ -5,7 +5,7 @@ from pandas import DataFrame, to_datetime
5
5
  # from scipy.interpolate import interp1d
6
6
  from scipy.interpolate import UnivariateSpline as unvpline, interp1d
7
7
 
8
- from AeroViz.dataProcess.core import _union_index
8
+ from AeroViz.dataProcess.core import union_index
9
9
 
10
10
  __all__ = ['merge_SMPS_APS']
11
11
 
@@ -195,7 +195,7 @@ def _merge_data(_smps_ori, _aps_ori, _shift_ori, _smps_lb, _aps_hb, _coe, _shift
195
195
 
196
196
 
197
197
  def merge_SMPS_APS(df_smps, df_aps, aps_unit='um', smps_overlap_lowbound=500, aps_fit_highbound=1000):
198
- df_smps, df_aps = _union_index(df_smps, df_aps)
198
+ df_smps, df_aps = union_index(df_smps, df_aps)
199
199
 
200
200
  ## set to the same units
201
201
  smps, aps_ori = df_smps.copy(), df_aps.copy()
@@ -5,7 +5,7 @@ from pandas import DataFrame, to_datetime
5
5
  # from scipy.interpolate import interp1d
6
6
  from scipy.interpolate import UnivariateSpline as unvpline, interp1d
7
7
 
8
- from AeroViz.dataProcess.core import _union_index
8
+ from AeroViz.dataProcess.core import union_index
9
9
 
10
10
  __all__ = ['_merge_SMPS_APS']
11
11
 
@@ -203,7 +203,7 @@ def _merge_data(_smps_ori, _aps_ori, _shift_ori, _shift_mode, _smps_lb, _aps_hb,
203
203
 
204
204
  ## aps_fit_highbound : the diameter I choose randomly
205
205
  def _merge_SMPS_APS(df_smps, df_aps, aps_unit, shift_mode, smps_overlap_lowbound, aps_fit_highbound):
206
- df_smps, df_aps = _union_index(df_smps, df_aps)
206
+ df_smps, df_aps = union_index(df_smps, df_aps)
207
207
 
208
208
  # print(f'\nMerge data :')
209
209
  # print(f' APS fittint higher diameter : {aps_fit_highbound:4d} nm')
@@ -5,7 +5,7 @@ from pandas import DataFrame, to_datetime
5
5
  # from scipy.interpolate import interp1d
6
6
  from scipy.interpolate import UnivariateSpline as unvpline, interp1d
7
7
 
8
- from AeroViz.dataProcess.core import _union_index
8
+ from AeroViz.dataProcess.core import union_index
9
9
 
10
10
  __all__ = ['_merge_SMPS_APS']
11
11
 
@@ -196,7 +196,7 @@ def _merge_data(_smps_ori, _aps_ori, _shift_ori, _smps_lb, _aps_hb, _coe, _shift
196
196
 
197
197
 
198
198
  def merge_SMPS_APS(df_smps, df_aps, aps_unit='um', smps_overlap_lowbound=500, aps_fit_highbound=1000):
199
- df_smps, df_aps = _union_index(df_smps, df_aps)
199
+ df_smps, df_aps = union_index(df_smps, df_aps)
200
200
 
201
201
  ## set to the same units
202
202
  smps, aps_ori = df_smps.copy(), df_aps.copy()
@@ -1,4 +1,4 @@
1
- # from ContainerHandle.dataProcess.utils import _union_index
1
+ # from ContainerHandle.dataProcess.config import _union_index
2
2
 
3
3
  from datetime import datetime as dtm
4
4
 
@@ -1,4 +1,4 @@
1
- # from ContainerHandle.dataProcess.utils import _union_index
1
+ # from ContainerHandle.dataProcess.config import _union_index
2
2
 
3
3
  import warnings
4
4
  from datetime import datetime as dtm
@@ -1,16 +1,11 @@
1
- from ..core import _writter, _run_process
1
+ from ..core import Writer, run_process
2
2
 
3
- __all__ = [
3
+ __all__ = ['VOC']
4
4
 
5
- 'VOC',
6
5
 
7
- ]
6
+ class VOC(Writer):
8
7
 
9
-
10
- class VOC(_writter):
11
-
12
- ## Reconstruction
13
- @_run_process('VOC - basic', 'voc_basic')
8
+ @run_process('VOC - basic', 'voc_basic')
14
9
  def VOC_basic(self, _df_voc):
15
10
  from ._potential_par import _basic
16
11
 
@@ -1,44 +1,41 @@
1
- import pickle as pkl
2
1
  from pathlib import Path
3
2
 
4
- from pandas import DataFrame, read_json
3
+ from pandas import DataFrame, read_json, concat
5
4
 
6
5
 
7
6
  def _basic(_df_voc):
8
- ## parameter
7
+ with (Path(__file__).parent / 'support_voc.json').open('r', encoding='utf-8', errors='ignore') as f:
8
+ _par = read_json(f)
9
+
10
+ # parameter
9
11
  _keys = _df_voc.keys()
10
12
 
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]
15
-
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]
20
-
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'],
30
-
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'],
34
-
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'],
13
+ invalid_keys = [key for key in _df_voc.keys() if key not in set(_par.keys())]
14
+
15
+ if invalid_keys:
16
+ raise KeyError(f'\n\t\t{invalid_keys} are not supported keys.'
17
+ f'\n\t\tPlease check the\033[91m support_voc.md\033[0m file to use the correct name.')
18
+
19
+ _MW, _MIR, _SOAP, _KOH = _par.loc['MW', :], _par.loc['MIR', :], _par.loc['SOAP', :], _par.loc['KOH', :]
20
+
21
+ _voc_classify = {
22
+ 'alkane_total': ['Ethane', 'Propane', 'Isobutane', 'n-Butane', 'Isopentane', 'n-Pentane', 'n-Hexane',
23
+ 'n-Heptane', 'n-Octane', 'n-Nonane', 'n-Decane', 'n-Undecane', 'n-Dodecane',
24
+
25
+ 'Cyclopentane', 'Methylcyclopentane', 'Cyclohexane', 'Methylcyclohexane',
26
+
27
+ '2,2-Dimethylbutane', '2,3-Dimethylbutane', '2-Methylpentane', '3-Methylpentane',
28
+ '2,4-Dimethylpentane', '2-Methylhexane', '3-Methylhexane',
29
+ '2,2,4-Trimethylpentane', '2,3,4-Trimethylpentane', '2-Methylheptane', '3-Methylheptane'],
30
+
31
+ 'alkene_total': ['Ethylene', 'Propylene', '1-Butene', 't-2-Butene', 'cis-2-Butene', '1-Pentene', 't-2-Pentene',
32
+ 'cis-2-Pentene', '1-Hexene', 'Isoprene', '1.3-Butadiene', '1-Octene'],
33
+
34
+ 'aromatic_total': ['Benzene', 'Toluene', 'Ethylbenzene', 'm/p-Xylene', 'o-Xylene', 'Styrene',
35
+ 'Isopropylbenzene',
36
+ 'n-Propylbenzene', 'm-Ethyltoluene', 'p-Ethyltoluene', 'o-Ethyltoluene', 'm-Diethylbenzene',
37
+ 'p-Diethylbenzene', '1,2,4-Trimethylbenzene', '1,2,3-Trimethylbenzene',
38
+ '1,3,5-Trimethylbenzene', ],
42
39
 
43
40
  'alkyne_total': ['Acetylene'],
44
41
 
@@ -55,15 +52,18 @@ def _basic(_df_voc):
55
52
  'LOH': _df_MW / 24.5 / _MW * 0.602 * _KOH,
56
53
  }
57
54
 
58
- ## calculate
55
+ # calculate
59
56
  _out = {}
60
57
  for _nam, _df in _df_dic.items():
61
58
 
62
59
  _df_out = DataFrame(index=_df_voc.index)
63
60
 
64
- for _voc_nam, _voc_lst in _voc_clasfy.items():
61
+ for _voc_nam, _voc_lst in _voc_classify.items():
65
62
  _lst = list(set(_keys) & set(_voc_lst))
66
- if len(_lst) == 0: continue
63
+ if len(_lst) == 0:
64
+ continue
65
+
66
+ _df_out = concat([_df[_lst], _df_out], axis=1)
67
67
 
68
68
  _df_out[_voc_nam] = _df[_lst].sum(axis=1, min_count=1)
69
69
 
@@ -72,3 +72,37 @@ def _basic(_df_voc):
72
72
  _out[_nam] = _df_out
73
73
 
74
74
  return _out
75
+
76
+
77
+ def markdown_table_to_dataframe():
78
+ import pandas as pd
79
+ from pathlib import Path
80
+
81
+ # support_voc.md
82
+ with open(Path(__file__).parent / 'support_voc.md', 'r', encoding='utf-8') as file:
83
+ markdown_content = file.read()
84
+
85
+ # 將內容分割成行
86
+ lines = markdown_content.strip().split('\n')
87
+
88
+ # 提取表頭
89
+ headers = [col.strip() for col in lines[0].split('|')[1:-1]]
90
+
91
+ # 解析數據行
92
+ data = []
93
+ for line in lines[2:]: # 跳過表頭和分隔行
94
+ columns = [col.strip() for col in line.split('|')[1:-1]]
95
+ data.append(columns)
96
+
97
+ # 創建 DataFrame
98
+ df = pd.DataFrame(data, columns=headers)
99
+
100
+ # 轉換數據類型
101
+ numeric_columns = ['MIR', 'MW', 'SOAP', 'KOH']
102
+ for col in numeric_columns:
103
+ df[col] = pd.to_numeric(df[col], errors='coerce')
104
+ df = df.set_index('Species').T
105
+
106
+ df = df.iloc[:, :-7]
107
+
108
+ df.to_json(Path(__file__).parent / 'support_voc.json', indent=4)