Debugging the OFRAnalyser, it is now completely functional. Remaining to-do's: Check transformations, implement median, mode, mean and variance methods of Distribution class, implement sample number list check for flow file. The two to-do's in the GetData method of the OFRAnalyser can be neglected as they are already fulfilled.
This commit is contained in:
1 parent
76b0129b6f
commit
fdc30aeb36
4 files changed
+107
-190
No files matched your search
Vendored
+1
-1
@@ -52,7 +52,7 @@
|
||||
"editor.suggestOnTriggerCharacters": false,
|
||||
"window.zoomLevel": -1,
|
||||
"editor.wordWrap": "on",
|
||||
"editor.rulers": [140],
|
||||
"editor.rulers": [145],
|
||||
"notebook.editorOptionsCustomizations": {"editor.rulers":[]},
|
||||
"editor.fontSize": 16,
|
||||
"jupiter.notebookFileRoot": "${workspaceFolder}/"
|
||||
|
||||
+92
-178
@@ -24,30 +24,47 @@ class Distribution():
|
||||
warnings.warn("Already in desired format. Transformation has no effect.")
|
||||
return
|
||||
|
||||
# TODO: check the transformations!
|
||||
# TODO: check the transformations!
|
||||
# TODO: check the order of the transformation (first variable, then function, or vice versa) to avoid having a mess!
|
||||
|
||||
match to:
|
||||
case 'linear':
|
||||
if self.__form == 'ln':
|
||||
self.var = np.exp(self.var)
|
||||
self.fct = np.divide(self.fct, self.var)
|
||||
self.__form = 'linear'
|
||||
elif self.__form == 'log10':
|
||||
self.var = np.power(10, self.var)
|
||||
self.fct = np.divide(self.fct, self.var * np.log(10))
|
||||
self.__form = 'linear'
|
||||
case 'ln':
|
||||
if self.__form == 'linear':
|
||||
self.var = np.log(self.var)
|
||||
self.fct = np.multiply(self.var, self.fct)
|
||||
self.__form = 'ln'
|
||||
elif self.__form == 'log10':
|
||||
self.var = np.log(np.power(10, self.var))
|
||||
self.fct = np.divide(self.fct, np.log(10))
|
||||
self.__form = 'ln'
|
||||
case 'log10':
|
||||
if self.__form == 'linear':
|
||||
self.var = np.log10(self.var)
|
||||
self.fct = np.multiply(self.var, self.fct * np.log(10))
|
||||
self.var = np.log10(self.var)
|
||||
self.__form = 'log10'
|
||||
elif self.__form == 'ln':
|
||||
self.var = np.log10(np.exp(self.var))
|
||||
self.fct = np.multiply(self.fct, np.log(10))
|
||||
self.__form = 'log10'
|
||||
|
||||
def update_units(self, new_var_units, new_fct_units):
|
||||
|
||||
old_from = self.__form
|
||||
self.transform(to='linear')
|
||||
|
||||
self.var = self.var * new_var_units
|
||||
self.fct = self.fct * new_fct_units
|
||||
|
||||
self.transform(to=old_from)
|
||||
|
||||
def integrate(self) -> np.float64:
|
||||
return np.trapezoid(y = self.fct, x = self.var)
|
||||
@@ -154,6 +171,12 @@ class OFRSample:
|
||||
else:
|
||||
continue
|
||||
|
||||
self.aerosol_flow = self.aerosol_flow * 6E-4
|
||||
self.SOA_density = self.SOA_density * 1E3
|
||||
self.lower_diameter_bound = self.lower_diameter_bound * 1E-9
|
||||
self.upper_diameter_bound = self.upper_diameter_bound * 1E-9
|
||||
|
||||
|
||||
# Input data from file is in (nm)
|
||||
return [np.array(midpoints), np.array(counts)]
|
||||
|
||||
@@ -178,21 +201,21 @@ class OFRSample:
|
||||
|
||||
# Distributions of the relevant quantities (all relative to nanometer)
|
||||
data = self.__get_data()
|
||||
self.Count = Distribution(variable_array = np.log10(data[0]),
|
||||
function_array = data[1],
|
||||
form='log10')
|
||||
self.Length = Distribution(variable_array = np.log10(data[0]),
|
||||
function_array = data[0] * data[1],
|
||||
form = 'log10')
|
||||
self.Surface = Distribution(variable_array = np.log(data[0]),
|
||||
function_array = ((math.pi) * data[0] ** 2) * data[1],
|
||||
form = 'log10')
|
||||
self.Volume = Distribution(variable_array = np.log10(data[0]),
|
||||
function_array = ((math.pi / 6) * data[0] ** 3) * data[1],
|
||||
form = 'log10')
|
||||
self.Mass = Distribution(variable_array = np.log10(data[0]),
|
||||
function_array = (self.SOA_density * (math.pi / 6) * data[0] ** 3) * data[1],
|
||||
form='log10')
|
||||
|
||||
# Getting Distribution objects
|
||||
self.Count = Distribution(variable_array = np.log10(data[0]), function_array = data[1], form='log10')
|
||||
self.Count.update_units(new_fct_units=1E15, new_var_units=1E-9)
|
||||
|
||||
self.Length = Distribution(variable_array = np.log10(data[0]), function_array = data[0]*data[1], form = 'log10')
|
||||
self.Length.update_units(new_fct_units=1E6, new_var_units=1E-9)
|
||||
|
||||
self.Surface = Distribution(variable_array = np.log(data[0]), function_array = ((math.pi)* data[0] ** 2) * data[1], form = 'log10')
|
||||
self.Surface.update_units(new_fct_units=1E-3, new_var_units=1E-9)
|
||||
|
||||
self.Volume = Distribution(variable_array = np.log10(data[0]),function_array = ((math.pi / 6) * data[0] ** 3) * data[1], form = 'log10')
|
||||
self.Volume.update_units(new_fct_units=1E-12, new_var_units=1E-9)
|
||||
|
||||
self.Mass = Distribution(variable_array = self.Volume.var, function_array = self.Volume.fct * self.SOA_density, form='log10')
|
||||
|
||||
class OFRAnalyser:
|
||||
|
||||
@@ -225,48 +248,53 @@ class OFRAnalyser:
|
||||
|
||||
def GetData(self) -> None:
|
||||
|
||||
# TODO make this work also for a specific sample!
|
||||
# TODO convert everything is SI units, making live a lot easier...
|
||||
|
||||
self.__sample_number_list_check(self.sample_number_list)
|
||||
|
||||
numbers_of_sample = []
|
||||
number_concentrations = []
|
||||
length_concentrations = []
|
||||
surface_concentrations = []
|
||||
volume_concentrations = []
|
||||
aerosol_densities = []
|
||||
mass_concentrations = []
|
||||
starting_times = []
|
||||
stopping_times = []
|
||||
sampling_times = []
|
||||
dry_air_flows = []
|
||||
species_flows = []
|
||||
ozone_flows = []
|
||||
total_flows = None
|
||||
cpc_flows = []
|
||||
numbers_of_sample = [] # (-)
|
||||
number_concentrations = [] # (#/m^3)
|
||||
length_concentrations = [] # (m/m^3)
|
||||
surface_concentrations = [] # (m^2/m^3)
|
||||
volume_concentrations = [] # (m^3/m^3)
|
||||
aerosol_densities = [] # (kg/m^3)
|
||||
mass_concentrations = [] # (kg/m^3)
|
||||
starting_times = [] # (s)
|
||||
stopping_times = [] # (s)
|
||||
sampling_times = [] # (s)
|
||||
dry_air_flows = [] # (m^3/s)
|
||||
species_flows = [] # (m^3/s)
|
||||
ozone_flows = [] # (m^3/s)
|
||||
total_flows = None # (m^3/s)
|
||||
cpc_flows = [] # (m^3/s)
|
||||
mass_production_rate = None # (kg/s)
|
||||
mass_produced = None # (kg)
|
||||
cumulative_mass_produced = None # (kg)
|
||||
|
||||
|
||||
for sample_number in self.sample_number_list:
|
||||
sample = OFRSample(source_file=self.data_source_file, sample_number = sample_number, data_separator = self.__data_separator)
|
||||
|
||||
numbers_of_sample.append(sample_number)
|
||||
number_concentrations.append(sample.Count.integrate())
|
||||
length_concentrations.append(sample.Length.integrate() / 1E6)
|
||||
surface_concentrations.append(sample.Surface.integrate() / 1E12)
|
||||
volume_concentrations.append(sample.Volume.integrate() / 1E9)
|
||||
length_concentrations.append(sample.Length.integrate())
|
||||
surface_concentrations.append(sample.Surface.integrate())
|
||||
volume_concentrations.append(sample.Volume.integrate())
|
||||
aerosol_densities.append(sample.SOA_density)
|
||||
mass_concentrations.append(sample.Mass.integrate() / 1E12)
|
||||
mass_concentrations.append(sample.Mass.integrate())
|
||||
|
||||
if sample_number == 1:
|
||||
starting_times.append(0.00)
|
||||
stopping_times.append(sample.sampling_time)
|
||||
|
||||
elif sample_number >= 1:
|
||||
starting_times.append(stopping_times[-1])
|
||||
stopping_times.append(stopping_times[-1] + sample.sampling_time)
|
||||
starting_times.append((sample_number - 1) * sample.sampling_time)
|
||||
stopping_times.append(sample_number * sample.sampling_time)
|
||||
|
||||
sampling_times.append(sample.sampling_time)
|
||||
|
||||
out_flag = False
|
||||
|
||||
with open(self.flows_source_file, 'r', errors='ignore') as file:
|
||||
|
||||
j = 1
|
||||
|
||||
for line_counter, line in enumerate(file.readlines()):
|
||||
|
||||
if out_flag == True:
|
||||
@@ -283,156 +311,42 @@ class OFRAnalyser:
|
||||
|
||||
while i < int(items[-1]):
|
||||
|
||||
dry_air_flows.append(float(items[0]))
|
||||
species_flows.append(float(items[1]))
|
||||
ozone_flows.append(float(items[2]))
|
||||
cpc_flows.append(float(items[3]))
|
||||
if j in self.sample_number_list:
|
||||
dry_air_flows.append(float(items[0]) * 6E-4)
|
||||
species_flows.append(float(items[1]) * 6E-4)
|
||||
ozone_flows.append(float(items[2]) * 6E-4)
|
||||
cpc_flows.append(float(items[3]) * 6E-4)
|
||||
|
||||
i += 1
|
||||
j += 1
|
||||
|
||||
else:
|
||||
continue
|
||||
|
||||
total_flows = [(flow_1 + flow_2 + flow_3) * 1E3 for flow_1, flow_2, flow_3 in zip(dry_air_flows, species_flows, ozone_flows)]
|
||||
total_flows = [(flow_1 + flow_2 + flow_3) for flow_1, flow_2, flow_3 in zip(dry_air_flows, species_flows, ozone_flows)]
|
||||
mass_production_rate = [(mass * flow) for mass, flow in zip(mass_concentrations, total_flows)]
|
||||
mass_produced = [(mpr * duration) for mpr, duration in zip(mass_production_rate, sampling_times)]
|
||||
cumulative_mass_produced = np.cumsum(np.array(mass_produced)).tolist()
|
||||
|
||||
self.data = pd.DataFrame({'Sample (-)': numbers_of_sample,
|
||||
'Number (#/cm^3)': number_concentrations,
|
||||
'Length (mm/cm^3)': length_concentrations,
|
||||
'Surface (mm^2/cm^3)': surface_concentrations,
|
||||
'Volume (μm^3/cm^3)': volume_concentrations,
|
||||
'Density (pg/μm^3)': aerosol_densities,
|
||||
'Mass (mg/cm^3)': mass_concentrations,
|
||||
'Number (#/m^3)': number_concentrations,
|
||||
'Length (m/m^3)': length_concentrations,
|
||||
'Surface (m^2/m^3)': surface_concentrations,
|
||||
'Volume (m^3/m^3)': volume_concentrations,
|
||||
'Density (kg/m^3)': aerosol_densities,
|
||||
'Mass (kg/m^3)': mass_concentrations,
|
||||
'Start (s)': starting_times,
|
||||
'Stop (s)': stopping_times,
|
||||
'Duration (s)': sampling_times,
|
||||
'Dry Air Flow (L/min)': dry_air_flows,
|
||||
'Species Flow (L/min)': species_flows,
|
||||
'Ozone Flow (L/min)': ozone_flows,
|
||||
'Total Flow (cm^3/s)': total_flows,
|
||||
'CPC Flow (L/min)': cpc_flows,
|
||||
'Mass Production Rate (mg/s)': mass_production_rate,
|
||||
'Mass Produced (mg)': mass_produced,
|
||||
'Cumulative Mass Produced (mg)': cumulative_mass_produced})
|
||||
'Dry Air Flow (m^3/s)': dry_air_flows,
|
||||
'Species Flow (m^3/s)': species_flows,
|
||||
'Ozone Flow (m^3/s)': ozone_flows,
|
||||
'Total Flow (m^3/s)': total_flows,
|
||||
'CPC Flow (m^3/s)': cpc_flows,
|
||||
'Mass Production Rate (kg/s)': mass_production_rate,
|
||||
'Mass Produced (kg)': mass_produced,
|
||||
'Cumulative Mass Produced (kg)': cumulative_mass_produced})
|
||||
|
||||
def GetPlottableData(self, which_data = 'Mass'):
|
||||
|
||||
times = []
|
||||
output_list = []
|
||||
|
||||
match which_data:
|
||||
case 'Number':
|
||||
key = 'Number (#/cm^3)'
|
||||
case 'Length':
|
||||
key = 'Length (mm/cm^3)'
|
||||
case 'Surface':
|
||||
key = 'Surface (mm^2/cm^3)'
|
||||
case 'Volume':
|
||||
key = 'Volume (μm^3/cm^3)'
|
||||
case 'Mass':
|
||||
key = 'Mass (mg/cm^3)'
|
||||
|
||||
times.append(0.00)
|
||||
output_list.append(0.00)
|
||||
|
||||
for i, row in self.data.iterrows():
|
||||
|
||||
times.append(row['Time (s)'])
|
||||
times.append(times[-1])
|
||||
|
||||
output_list.append(output_list[-1])
|
||||
output_list.append(row[key])
|
||||
|
||||
if i == self.max_samples - 1:
|
||||
|
||||
times.append(row['Time (s)'])
|
||||
times.append(times[-1])
|
||||
|
||||
output_list.append(output_list[-1])
|
||||
output_list.append(0.00)
|
||||
|
||||
|
||||
return times, output_list
|
||||
|
||||
|
||||
def GetFlowData(self, flow_source_file):
|
||||
|
||||
# For a step diagram
|
||||
|
||||
self.flow_source_file = flow_source_file
|
||||
|
||||
dry_air_flows = []
|
||||
species_flows = []
|
||||
ozone_flows = []
|
||||
cnc_flows = []
|
||||
starts = []
|
||||
stops = []
|
||||
smpls = []
|
||||
|
||||
out_flag = False
|
||||
|
||||
with open(self.flow_source_file, 'r', errors='ignore') as file:
|
||||
i = 0
|
||||
for line_counter, line in enumerate(file.readlines()):
|
||||
if out_flag == True:
|
||||
continue
|
||||
if line_counter == 6:
|
||||
items = line.split()
|
||||
dry_air_flows.append(float(items[0]))
|
||||
species_flows.append(float(items[1]))
|
||||
ozone_flows.append(float(items[2]))
|
||||
cnc_flows.append(float(items[-1]))
|
||||
starts.append(0)
|
||||
stops.append(float(items[3]) * float(items[4]))
|
||||
smpls.append(float(items[4]))
|
||||
i += 1
|
||||
elif line_counter > 6 and not line.startswith('-'):
|
||||
items = line.split()
|
||||
dry_air_flows.append(float(items[0]))
|
||||
species_flows.append(float(items[1]))
|
||||
ozone_flows.append(float(items[2]))
|
||||
cnc_flows.append(float(items[-1]))
|
||||
starts.append(stops[i-1])
|
||||
stops.append(stops[i-1] + float(items[3]) * float(items[4]))
|
||||
smpls.append(float(items[4]))
|
||||
i += 1
|
||||
if line_counter > 6 and line.startswith('-'):
|
||||
out_flag = True
|
||||
else:
|
||||
continue
|
||||
|
||||
self.flow_data = pd.DataFrame({'Dry Air (L/min)': dry_air_flows, 'Species (L/min)': species_flows, 'Ozone (L/min)': ozone_flows, 'Start (s)': starts, 'Stop (s)': stops, 'CNC Flow (L/min)': cnc_flows, 'Samples': smpls})
|
||||
|
||||
def GetPlottableFlowData(self, which_flow_rate='Species'):
|
||||
|
||||
times = []
|
||||
output_list = []
|
||||
|
||||
match which_flow_rate:
|
||||
case 'Species':
|
||||
key = 'Species (L/min)'
|
||||
case 'Ozone':
|
||||
key = 'Ozone (L/min)'
|
||||
case 'Dry Air':
|
||||
key = 'Dry Air (L/min)'
|
||||
|
||||
for _, row in self.flow_data.iterrows():
|
||||
times.append(row['Start (s)'])
|
||||
times.append(row['Stop (s)'])
|
||||
|
||||
# Now append relevant data twice so that the data can be plotted correctly
|
||||
i = 0
|
||||
while i < 2:
|
||||
output_list.append(row[key])
|
||||
i += 1
|
||||
|
||||
return times, output_list
|
||||
|
||||
def GetMassProductionRates(self):
|
||||
|
||||
pass
|
||||
|
||||
### ----------------------------------------------------------------------------------------------------------------------------------- ###
|
||||
###
|
||||
@@ -1,17 +1,13 @@
|
||||
# Imports
|
||||
#%%
|
||||
from defs.computing import OFRSample, OFRAnalyser
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# Path to the source file
|
||||
source_file = Path(r"C:\Users\tschan_d\Documents\data_local\20260612_SET02_EXP01_full.txt")
|
||||
flows_source_file = Path(r"C:\Users\tschan_d\Documents\data_local\20260612_SET02_EXP01_full_flows.txt")
|
||||
|
||||
analyser = OFRAnalyser(data_source_file=source_file, flows_source_file=flows_source_file, sample_number_list=range(1, 157))
|
||||
# Code to debug
|
||||
analyser = OFRAnalyser(data_source_file=source_file, flows_source_file=flows_source_file, sample_number_list=[33, 35])
|
||||
analyser.GetData()
|
||||
print(analyser.data)
|
||||
|
||||
|
||||
# %%
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 1,
|
||||
"id": "8769766b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -85,16 +85,15 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 2,
|
||||
"id": "8db19b57",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sample_number_list = [int(i) for i in range(1, 157)]\n",
|
||||
"\n",
|
||||
"analyser = OFRAnalyser(data_source_file = source_file, flows_source_file = flows_source_file, sample_number_list = sample_number_list)\n",
|
||||
"analyser = OFRAnalyser(data_source_file = source_file, flows_source_file = flows_source_file, sample_number_list = [33, 35, 37])\n",
|
||||
"analyser.GetData()\n",
|
||||
"\n",
|
||||
"analyser.data.to_csv(path_or_buf=r\"C:\\Users\\tschan_d\\Documents\\data_local\\data.csv\", index=False)"
|
||||
]
|
||||
},
|
||||
@@ -129,7 +128,7 @@
|
||||
"\n",
|
||||
"ax.set_xlim([1, 156])\n",
|
||||
"ax.set_ylim([0, 1.2E6])\n",
|
||||
"ax_2.set_ylim([0, 15])\n",
|
||||
"#ax_2.set_ylim([0, 15])\n",
|
||||
"\n",
|
||||
"lines_1, labels_1 = ax.get_legend_handles_labels()\n",
|
||||
"lines_2, labels_2 = ax_2.get_legend_handles_labels()\n",
|
||||
@@ -220,6 +219,14 @@
|
||||
"\n",
|
||||
"plt.savefig(\"20260723_OFR_Analysis_01_Experiment_Overview_bottom.pdf\", format='pdf', dpi=400)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c6110f8c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
Reference in new issue
Block a user