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,257 +2,259 @@ from typing import Sequence, Literal
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
5
- from .PyMieScatt_update import AutoMieQ
6
5
  from numpy import exp, log, log10, sqrt, pi
7
6
 
7
+ from .PyMieScatt_update import AutoMieQ
8
+
8
9
 
9
10
  def Mie_Q(m: complex,
10
- wavelength: float,
11
- dp: float | Sequence[float]
12
- ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
13
- """
14
- Calculate Mie scattering efficiency (Q) for given spherical particle diameter(s).
15
-
16
- Parameters
17
- ----------
18
- m : complex
19
- The complex refractive index of the particles.
20
- wavelength : float
21
- The wavelength of the incident light (in nm).
22
- dp : float | Sequence[float]
23
- Particle diameters (in nm), can be a single value or Sequence object.
24
-
25
- Returns
26
- -------
27
- Q_ext : ndarray
28
- The Mie extinction efficiency for each particle diameter.
29
- Q_sca : ndarray
30
- The Mie scattering efficiency for each particle diameter.
31
- Q_abs : ndarray
32
- The Mie absorption efficiency for each particle diameter.
33
-
34
- Examples
35
- --------
36
- >>> Q_ext, Q_sca, Q_abs = Mie_Q(m=complex(1.5, 0.02), wavelength=550, dp=[100, 200, 300, 400])
37
- """
38
- # Ensure dp is a numpy array
39
- dp = np.atleast_1d(dp)
40
-
41
- # Transpose for proper unpacking
42
- Q_ext, Q_sca, Q_abs, g, Q_pr, Q_back, Q_ratio = np.array([AutoMieQ(m, wavelength, _dp) for _dp in dp]).T
43
-
44
- return Q_ext, Q_sca, Q_abs
11
+ wavelength: float,
12
+ dp: float | Sequence[float]
13
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
14
+ """
15
+ Calculate Mie scattering efficiency (Q) for given spherical particle diameter(s).
16
+
17
+ Parameters
18
+ ----------
19
+ m : complex
20
+ The complex refractive index of the particles.
21
+ wavelength : float
22
+ The wavelength of the incident light (in nm).
23
+ dp : float | Sequence[float]
24
+ Particle diameters (in nm), can be a single value or Sequence object.
25
+
26
+ Returns
27
+ -------
28
+ Q_ext : ndarray
29
+ The Mie extinction efficiency for each particle diameter.
30
+ Q_sca : ndarray
31
+ The Mie scattering efficiency for each particle diameter.
32
+ Q_abs : ndarray
33
+ The Mie absorption efficiency for each particle diameter.
34
+
35
+ Examples
36
+ --------
37
+ >>> Q_ext, Q_sca, Q_abs = Mie_Q(m=complex(1.5, 0.02), wavelength=550, dp=[100, 200, 300, 400])
38
+ """
39
+ # Ensure dp is a numpy array
40
+ dp = np.atleast_1d(dp)
41
+
42
+ # Transpose for proper unpacking
43
+ Q_ext, Q_sca, Q_abs, g, Q_pr, Q_back, Q_ratio = np.array([AutoMieQ(m, wavelength, _dp) for _dp in dp]).T
44
+
45
+ return Q_ext, Q_sca, Q_abs
45
46
 
46
47
 
47
48
  def Mie_MEE(m: complex,
48
- wavelength: float,
49
- dp: float | Sequence[float],
50
- density: float
51
- ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
52
- """
53
- Calculate mass extinction efficiency and other parameters.
54
-
55
- Parameters
56
- ----------
57
- m : complex
58
- The complex refractive index of the particles.
59
- wavelength : float
60
- The wavelength of the incident light.
61
- dp : float | Sequence[float]
62
- List of particle sizes or a single value.
63
- density : float
64
- The density of particles.
65
-
66
- Returns
67
- -------
68
- MEE : ndarray
69
- The mass extinction efficiency for each particle diameter.
70
- MSE : ndarray
71
- The mass scattering efficiency for each particle diameter.
72
- MAE : ndarray
73
- The mass absorption efficiency for each particle diameter.
74
-
75
- Examples
76
- --------
77
- >>> MEE, MSE, MAE = Mie_MEE(m=complex(1.5, 0.02), wavelength=550, dp=[100, 200, 300, 400], density=1.2)
78
- """
79
- Q_ext, Q_sca, Q_abs = Mie_Q(m, wavelength, dp)
80
-
81
- MEE = (3 * Q_ext) / (2 * density * dp) * 1000
82
- MSE = (3 * Q_sca) / (2 * density * dp) * 1000
83
- MAE = (3 * Q_abs) / (2 * density * dp) * 1000
84
-
85
- return MEE, MSE, MAE
49
+ wavelength: float,
50
+ dp: float | Sequence[float],
51
+ density: float
52
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
53
+ """
54
+ Calculate mass extinction efficiency and other parameters.
55
+
56
+ Parameters
57
+ ----------
58
+ m : complex
59
+ The complex refractive index of the particles.
60
+ wavelength : float
61
+ The wavelength of the incident light.
62
+ dp : float | Sequence[float]
63
+ List of particle sizes or a single value.
64
+ density : float
65
+ The density of particles.
66
+
67
+ Returns
68
+ -------
69
+ MEE : ndarray
70
+ The mass extinction efficiency for each particle diameter.
71
+ MSE : ndarray
72
+ The mass scattering efficiency for each particle diameter.
73
+ MAE : ndarray
74
+ The mass absorption efficiency for each particle diameter.
75
+
76
+ Examples
77
+ --------
78
+ >>> MEE, MSE, MAE = Mie_MEE(m=complex(1.5, 0.02), wavelength=550, dp=[100, 200, 300, 400], density=1.2)
79
+ """
80
+ Q_ext, Q_sca, Q_abs = Mie_Q(m, wavelength, dp)
81
+
82
+ MEE = (3 * Q_ext) / (2 * density * dp) * 1000
83
+ MSE = (3 * Q_sca) / (2 * density * dp) * 1000
84
+ MAE = (3 * Q_abs) / (2 * density * dp) * 1000
85
+
86
+ return MEE, MSE, MAE
86
87
 
87
88
 
88
89
  def Mie_PESD(m: complex,
89
- wavelength: float = 550,
90
- dp: float | Sequence[float] = None,
91
- ndp: float | Sequence[float] = None,
92
- lognormal: bool = False,
93
- dp_range: tuple = (1, 2500),
94
- geoMean: float = 200,
95
- geoStdDev: float = 2,
96
- numberOfParticles: float = 1e6,
97
- numberOfBins: int = 167,
98
- ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
99
- """
100
- Simultaneously calculate "extinction distribution" and "integrated results" using the Mie_Q method.
101
-
102
- Parameters
103
- ----------
104
- m : complex
105
- The complex refractive index of the particles.
106
- wavelength : float
107
- The wavelength of the incident light.
108
- dp : float | Sequence[float]
109
- Particle sizes.
110
- ndp : float | Sequence[float]
111
- Number concentration from SMPS or APS in the units of dN/dlogdp.
112
- lognormal : bool, optional
113
- Whether to use lognormal distribution for ndp. Default is False.
114
- dp_range : tuple, optional
115
- Range of particle sizes. Default is (1, 2500) nm.
116
- geoMean : float, optional
117
- Geometric mean of the particle size distribution. Default is 200 nm.
118
- geoStdDev : float, optional
119
- Geometric standard deviation of the particle size distribution. Default is 2.
120
- numberOfParticles : float, optional
121
- Number of particles. Default is 1e6.
122
- numberOfBins : int, optional
123
- Number of bins for the lognormal distribution. Default is 167.
124
-
125
- Returns
126
- -------
127
- ext_dist : ndarray
128
- The extinction distribution for the given data.
129
- sca_dist : ndarray
130
- The scattering distribution for the given data.
131
- abs_dist : ndarray
132
- The absorption distribution for the given data.
133
-
134
- Notes
135
- -----
136
- return in "dext/dlogdp", please make sure input the dNdlogdp data.
137
-
138
- Examples
139
- --------
140
- >>> Ext, Sca, Abs = Mie_PESD(m=complex(1.5, 0.02), wavelength=550, dp=[100, 200, 500, 1000], ndp=[100, 50, 30, 20])
141
- """
142
- if lognormal:
143
- dp = np.logspace(log10(dp_range[0]), log10(dp_range[1]), numberOfBins)
144
-
145
- ndp = numberOfParticles * (1 / (log(geoStdDev) * sqrt(2 * pi)) *
146
- exp(-(log(dp) - log(geoMean)) ** 2 / (2 * log(geoStdDev) ** 2)))
147
-
148
- # dN / dlogdp
149
- ndp = np.atleast_1d(ndp)
150
-
151
- Q_ext, Q_sca, Q_abs = Mie_Q(m, wavelength, dp)
152
-
153
- # The 1e-6 here is so that the final value is the same as the unit 1/10^6m.
154
- Ext = Q_ext * (pi / 4 * dp ** 2) * ndp * 1e-6
155
- Sca = Q_sca * (pi / 4 * dp ** 2) * ndp * 1e-6
156
- Abs = Q_abs * (pi / 4 * dp ** 2) * ndp * 1e-6
157
-
158
- return Ext, Sca, Abs
90
+ wavelength: float = 550,
91
+ dp: float | Sequence[float] = None,
92
+ ndp: float | Sequence[float] = None,
93
+ lognormal: bool = False,
94
+ dp_range: tuple = (1, 2500),
95
+ geoMean: float = 200,
96
+ geoStdDev: float = 2,
97
+ numberOfParticles: float = 1e6,
98
+ numberOfBins: int = 167,
99
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
100
+ """
101
+ Simultaneously calculate "extinction distribution" and "integrated results" using the Mie_Q method.
102
+
103
+ Parameters
104
+ ----------
105
+ m : complex
106
+ The complex refractive index of the particles.
107
+ wavelength : float
108
+ The wavelength of the incident light.
109
+ dp : float | Sequence[float]
110
+ Particle sizes.
111
+ ndp : float | Sequence[float]
112
+ Number concentration from SMPS or APS in the units of dN/dlogdp.
113
+ lognormal : bool, optional
114
+ Whether to use lognormal distribution for ndp. Default is False.
115
+ dp_range : tuple, optional
116
+ Range of particle sizes. Default is (1, 2500) nm.
117
+ geoMean : float, optional
118
+ Geometric mean of the particle size distribution. Default is 200 nm.
119
+ geoStdDev : float, optional
120
+ Geometric standard deviation of the particle size distribution. Default is 2.
121
+ numberOfParticles : float, optional
122
+ Number of particles. Default is 1e6.
123
+ numberOfBins : int, optional
124
+ Number of bins for the lognormal distribution. Default is 167.
125
+
126
+ Returns
127
+ -------
128
+ ext_dist : ndarray
129
+ The extinction distribution for the given data.
130
+ sca_dist : ndarray
131
+ The scattering distribution for the given data.
132
+ abs_dist : ndarray
133
+ The absorption distribution for the given data.
134
+
135
+ Notes
136
+ -----
137
+ return in "dext/dlogdp", please make sure input the dNdlogdp data.
138
+
139
+ Examples
140
+ --------
141
+ >>> Ext, Sca, Abs = Mie_PESD(m=complex(1.5, 0.02), wavelength=550, dp=[100, 200, 500, 1000], ndp=[100, 50, 30, 20])
142
+ """
143
+ if lognormal:
144
+ dp = np.logspace(log10(dp_range[0]), log10(dp_range[1]), numberOfBins)
145
+
146
+ ndp = numberOfParticles * (1 / (log(geoStdDev) * sqrt(2 * pi)) *
147
+ exp(-(log(dp) - log(geoMean)) ** 2 / (2 * log(geoStdDev) ** 2)))
148
+
149
+ # dN / dlogdp
150
+ ndp = np.atleast_1d(ndp)
151
+
152
+ Q_ext, Q_sca, Q_abs = Mie_Q(m, wavelength, dp)
153
+
154
+ # The 1e-6 here is so that the final value is the same as the unit 1/10^6m.
155
+ Ext = Q_ext * (pi / 4 * dp ** 2) * ndp * 1e-6
156
+ Sca = Q_sca * (pi / 4 * dp ** 2) * ndp * 1e-6
157
+ Abs = Q_abs * (pi / 4 * dp ** 2) * ndp * 1e-6
158
+
159
+ return Ext, Sca, Abs
159
160
 
160
161
 
161
162
  def internal(dist: pd.Series,
162
- dp: float | Sequence[float],
163
- wavelength: float = 550,
164
- result_type: Literal['extinction', 'scattering', 'absorption'] = 'extinction'
165
- ) -> np.ndarray:
166
- """
167
- Calculate the extinction distribution by internal mixing model.
168
-
169
- Parameters
170
- ----------
171
- dist : pd.Series
172
- Particle size distribution data.
173
- dp : float | Sequence[float]
174
- Diameter(s) of the particles, either a single value or a sequence.
175
- wavelength : float, optional
176
- Wavelength of the incident light, default is 550 nm.
177
- result_type : {'extinction', 'scattering', 'absorption'}, optional
178
- Type of result to calculate, defaults to 'extinction'.
179
-
180
- Returns
181
- -------
182
- np.ndarray
183
- Extinction distribution calculated based on the internal mixing model.
184
- """
185
- ext_dist, sca_dist, abs_dist = Mie_PESD(m=complex(dist['n_amb'], dist['k_amb']),
186
- wavelength=wavelength,
187
- dp=dp,
188
- ndp=np.array(dist[:np.size(dp)]))
189
-
190
- if result_type == 'extinction':
191
- return ext_dist
192
- elif result_type == 'scattering':
193
- return sca_dist
194
- else:
195
- return abs_dist
196
-
197
- # return dict(ext=ext_dist, sca=sca_dist, abs=abs_dist)
163
+ dp: float | Sequence[float],
164
+ wavelength: float = 550,
165
+ result_type: Literal['extinction', 'scattering', 'absorption'] = 'extinction'
166
+ ) -> np.ndarray:
167
+ """
168
+ Calculate the extinction distribution by internal mixing model.
169
+
170
+ Parameters
171
+ ----------
172
+ dist : pd.Series
173
+ Particle size distribution data.
174
+ dp : float | Sequence[float]
175
+ Diameter(s) of the particles, either a single value or a sequence.
176
+ wavelength : float, optional
177
+ Wavelength of the incident light, default is 550 nm.
178
+ result_type : {'extinction', 'scattering', 'absorption'}, optional
179
+ Type of result to calculate, defaults to 'extinction'.
180
+
181
+ Returns
182
+ -------
183
+ np.ndarray
184
+ Extinction distribution calculated based on the internal mixing model.
185
+ """
186
+ ext_dist, sca_dist, abs_dist = Mie_PESD(m=complex(dist['n_amb'], dist['k_amb']),
187
+ wavelength=wavelength,
188
+ dp=dp,
189
+ ndp=np.array(dist[:np.size(dp)]))
190
+
191
+ if result_type == 'extinction':
192
+ return ext_dist
193
+ elif result_type == 'scattering':
194
+ return sca_dist
195
+ else:
196
+ return abs_dist
197
+
198
+
199
+ # return dict(ext=ext_dist, sca=sca_dist, abs=abs_dist)
198
200
 
199
201
 
200
202
  def external(dist: pd.Series,
201
- dp: float | Sequence[float],
202
- wavelength: float = 550,
203
- result_type: Literal['extinction', 'scattering', 'absorption'] = 'extinction'
204
- ) -> np.ndarray:
205
- """
206
- Calculate the extinction distribution by external mixing model.
207
-
208
- Parameters
209
- ----------
210
- dist : pd.Series
211
- Particle size distribution data.
212
- dp : float | Sequence[float]
213
- Diameter(s) of the particles, either a single value or a sequence.
214
- wavelength : float, optional
215
- Wavelength of the incident light, default is 550 nm.
216
- result_type : {'extinction', 'scattering', 'absorption'}, optional
217
- Type of result to calculate, defaults to 'extinction'.
218
-
219
- Returns
220
- -------
221
- np.ndarray
222
- Extinction distribution calculated based on the external mixing model.
223
- """
224
- refractive_dic = {'AS_volume_ratio': complex(1.53, 0.00),
225
- 'AN_volume_ratio': complex(1.55, 0.00),
226
- 'OM_volume_ratio': complex(1.54, 0.00),
227
- 'Soil_volume_ratio': complex(1.56, 0.01),
228
- 'SS_volume_ratio': complex(1.54, 0.00),
229
- 'EC_volume_ratio': complex(1.80, 0.54),
230
- 'ALWC_volume_ratio': complex(1.33, 0.00)}
231
-
232
- ndp = np.array(dist[:np.size(dp)])
233
- mie_results = (
234
- Mie_PESD(refractive_dic[_specie], wavelength, dp, dist[_specie] / (1 + dist['ALWC_volume_ratio']) * ndp) for
235
- _specie in refractive_dic)
236
-
237
- ext_dist, sca_dist, abs_dist = (np.sum([res[0] for res in mie_results], axis=0),
238
- np.sum([res[1] for res in mie_results], axis=0),
239
- np.sum([res[2] for res in mie_results], axis=0))
240
-
241
- if result_type == 'extinction':
242
- return ext_dist
243
- elif result_type == 'scattering':
244
- return sca_dist
245
- else:
246
- return abs_dist
203
+ dp: float | Sequence[float],
204
+ wavelength: float = 550,
205
+ result_type: Literal['extinction', 'scattering', 'absorption'] = 'extinction'
206
+ ) -> np.ndarray:
207
+ """
208
+ Calculate the extinction distribution by external mixing model.
209
+
210
+ Parameters
211
+ ----------
212
+ dist : pd.Series
213
+ Particle size distribution data.
214
+ dp : float | Sequence[float]
215
+ Diameter(s) of the particles, either a single value or a sequence.
216
+ wavelength : float, optional
217
+ Wavelength of the incident light, default is 550 nm.
218
+ result_type : {'extinction', 'scattering', 'absorption'}, optional
219
+ Type of result to calculate, defaults to 'extinction'.
220
+
221
+ Returns
222
+ -------
223
+ np.ndarray
224
+ Extinction distribution calculated based on the external mixing model.
225
+ """
226
+ refractive_dic = {'AS_volume_ratio': complex(1.53, 0.00),
227
+ 'AN_volume_ratio': complex(1.55, 0.00),
228
+ 'OM_volume_ratio': complex(1.54, 0.00),
229
+ 'Soil_volume_ratio': complex(1.56, 0.01),
230
+ 'SS_volume_ratio': complex(1.54, 0.00),
231
+ 'EC_volume_ratio': complex(1.80, 0.54),
232
+ 'ALWC_volume_ratio': complex(1.33, 0.00)}
233
+
234
+ ndp = np.array(dist[:np.size(dp)])
235
+ mie_results = (
236
+ Mie_PESD(refractive_dic[_specie], wavelength, dp, dist[_specie] / (1 + dist['ALWC_volume_ratio']) * ndp) for
237
+ _specie in refractive_dic)
238
+
239
+ ext_dist, sca_dist, abs_dist = (np.sum([res[0] for res in mie_results], axis=0),
240
+ np.sum([res[1] for res in mie_results], axis=0),
241
+ np.sum([res[2] for res in mie_results], axis=0))
242
+
243
+ if result_type == 'extinction':
244
+ return ext_dist
245
+ elif result_type == 'scattering':
246
+ return sca_dist
247
+ else:
248
+ return abs_dist
247
249
 
248
250
 
249
251
  def core_shell():
250
- pass
252
+ pass
251
253
 
252
254
 
253
255
  def sensitivity():
254
- pass
256
+ pass
255
257
 
256
258
 
257
259
  if __name__ == '__main__':
258
- result = Mie_Q(m=complex(1.5, 0.02), wavelength=550, dp=[100., 200.])
260
+ result = Mie_Q(m=complex(1.5, 0.02), wavelength=550, dp=[100., 200.])
@@ -4,59 +4,59 @@ from scipy.signal import find_peaks
4
4
 
5
5
 
6
6
  def geometric(dp: np.ndarray,
7
- dist: np.ndarray
8
- ) -> tuple[float, float]:
9
- """ Calculate the geometric mean and standard deviation. """
7
+ dist: np.ndarray
8
+ ) -> tuple[float, float]:
9
+ """ Calculate the geometric mean and standard deviation. """
10
10
 
11
- _gmd = (((dist * log(dp)).sum()) / dist.sum())
11
+ _gmd = (((dist * log(dp)).sum()) / dist.sum())
12
12
 
13
- logdp_mesh, gmd_mesh = np.meshgrid(log(dp), _gmd)
14
- _gsd = ((((logdp_mesh - gmd_mesh) ** 2) * dist).sum() / dist.sum()) ** .5
13
+ logdp_mesh, gmd_mesh = np.meshgrid(log(dp), _gmd)
14
+ _gsd = ((((logdp_mesh - gmd_mesh) ** 2) * dist).sum() / dist.sum()) ** .5
15
15
 
16
- return exp(_gmd), exp(_gsd)
16
+ return exp(_gmd), exp(_gsd)
17
17
 
18
18
 
19
19
  def contribution(dp: np.ndarray,
20
- dist: np.ndarray
21
- ) -> tuple[float, float, float]:
22
- """ Calculate the relative contribution of each mode. """
20
+ dist: np.ndarray
21
+ ) -> tuple[float, float, float]:
22
+ """ Calculate the relative contribution of each mode. """
23
23
 
24
- ultra = dist[(dp >= 11.8) & (dp < 100)].sum() / dist.sum()
25
- accum = dist[(dp >= 100) & (dp < 1000)].sum() / dist.sum()
26
- coars = dist[(dp >= 1000) & (dp < 2500)].sum() / dist.sum()
24
+ ultra = dist[(dp >= 11.8) & (dp < 100)].sum() / dist.sum()
25
+ accum = dist[(dp >= 100) & (dp < 1000)].sum() / dist.sum()
26
+ coars = dist[(dp >= 1000) & (dp < 2500)].sum() / dist.sum()
27
27
 
28
- return ultra, accum, coars
28
+ return ultra, accum, coars
29
29
 
30
30
 
31
31
  def mode(dp: np.ndarray,
32
- dist: np.ndarray
33
- ) -> np.ndarray:
34
- """ Find three peak mode in distribution. """
32
+ dist: np.ndarray
33
+ ) -> np.ndarray:
34
+ """ Find three peak mode in distribution. """
35
35
 
36
- min_value = np.array([dist.min()])
37
- mode, _ = find_peaks(np.concatenate([min_value, dist, min_value]), distance=len(dist) - 1)
36
+ min_value = np.array([dist.min()])
37
+ mode, _ = find_peaks(np.concatenate([min_value, dist, min_value]), distance=len(dist) - 1)
38
38
 
39
- return dp[mode - 1]
39
+ return dp[mode - 1]
40
40
 
41
41
 
42
42
  def properties(dist,
43
- dp: np.ndarray,
44
- dlogdp: np.ndarray,
45
- weighting: str
46
- ) -> dict:
47
- """ for apply """
48
- dist = np.array(dist)
49
-
50
- gmd, gsd = geometric(dp, dist)
51
- ultra, accum, coarse = contribution(dp, dist)
52
- peak = mode(dp, dist)
53
-
54
- return {key: round(value, 3) for key, value in
55
- {f'total_{weighting}': (dist * dlogdp).sum(),
56
- f'GMD_{weighting}': gmd,
57
- f'GSD_{weighting}': gsd,
58
- f'mode_{weighting}': peak[0],
59
- f'ultra_{weighting}': ultra,
60
- f'accum_{weighting}': accum,
61
- f'coarse_{weighting}': coarse}
62
- .items()}
43
+ dp: np.ndarray,
44
+ dlogdp: np.ndarray,
45
+ weighting: str
46
+ ) -> dict:
47
+ """ for apply """
48
+ dist = np.array(dist)
49
+
50
+ gmd, gsd = geometric(dp, dist)
51
+ ultra, accum, coarse = contribution(dp, dist)
52
+ peak = mode(dp, dist)
53
+
54
+ return {key: round(value, 3) for key, value in
55
+ {f'total_{weighting}': (dist * dlogdp).sum(),
56
+ f'GMD_{weighting}': gmd,
57
+ f'GSD_{weighting}': gsd,
58
+ f'mode_{weighting}': peak[0],
59
+ f'ultra_{weighting}': ultra,
60
+ f'accum_{weighting}': accum,
61
+ f'coarse_{weighting}': coarse}
62
+ .items()}