Skip to content

Commit

Permalink
Debugging2 (#149)
Browse files Browse the repository at this point in the history
* fixed inital conditions for reaction rates

* added handling for loss and emission in generating config

* fixed chapman test

* added scaling factors to config

* changed initial conditions to be read and stored in a separate file
  • Loading branch information
alexjamesgarza authored Apr 17, 2024
1 parent 4afde18 commit adbdbb9
Show file tree
Hide file tree
Showing 15 changed files with 5,952 additions and 8,026 deletions.
37 changes: 32 additions & 5 deletions src/acom_music_box/music_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ def generateConfig(self, directory):
"evolving_conditions.csv": {},
}

data["initial conditions"] = {}
data["initial conditions"] = {
"initial_conditions.csv": {}
}

for reaction_rate in self.initial_conditions.reaction_rates:
name = "PHOT." + reaction_rate.reaction.name + ".s-1"
data["initial conditions"][name] = reaction_rate.rate


data["model components"] = [
{
Expand All @@ -141,6 +141,7 @@ def generateConfig(self, directory):

config_file.write(json.dumps(data, indent=4))


# Make evolving conditions config
with open(output_path + "/evolving_conditions.csv", 'w', newline='') as evolving_conditions_file:
writer = csv.writer(evolving_conditions_file)
Expand Down Expand Up @@ -171,6 +172,29 @@ def generateConfig(self, directory):

writer.writerow(row)



reaction_names = []
reaction_rates = []

for reaction_rate in self.initial_conditions.reaction_rates:
if reaction_rate.reaction.reaction_type == "PHOTOLYSIS":
name = "PHOT." + reaction_rate.reaction.name + ".s-1"
elif reaction_rate.reaction.reaction_type == "LOSS":
name = "LOSS." + reaction_rate.reaction.name + ".s-1"
elif reaction_rate.reaction.reaction_type == "EMISSION":
name = "EMISSION." + reaction_rate.reaction.name + ".s-1"

reaction_names.append(name)
reaction_rates.append(reaction_rate.rate)
#writes reaction rates inital conditions to file
with open(output_path + "/initial_conditions.csv", 'w', newline='') as initial_conditions_file:
writer = csv.writer(initial_conditions_file)
writer.writerow(reaction_names)
writer.writerow(reaction_rates)



def generateSpeciesConfig(self):
"""
Generate a JSON configuration for the species in the box model.
Expand Down Expand Up @@ -358,6 +382,9 @@ def generateReactionConfig(self):
if(reaction.name != None):
reac["MUSICA name"] = reaction.name

if(reaction.scaling_factor != None):
reac["scaling factor"] = reaction.scaling_factor

reactionsArray.append(reac)

reacList["reactions"] = reactionsArray
Expand Down Expand Up @@ -552,7 +579,7 @@ def readConditionsFromJson(self, path_to_json):
self.reaction_list = ReactionList.from_config_JSON(path_to_json, data, self.species_list)

# Set initial conditions
self.initial_conditions = Conditions.from_config_JSON(data, self.species_list, self.reaction_list)
self.initial_conditions = Conditions.from_config_JSON(path_to_json, data, self.species_list, self.reaction_list)

# Set initial conditions
self.evolving_conditions = EvolvingConditions.from_config_JSON(path_to_json, data, self.species_list, self.reaction_list)
Expand Down
45 changes: 39 additions & 6 deletions src/acom_music_box/music_box_conditions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import csv
import os
from typing import List
from .music_box_reaction_rate import ReactionRate
from .music_box_species import Species
Expand Down Expand Up @@ -76,20 +78,23 @@ def from_UI_JSON(cls, UI_JSON, species_list, reaction_list):
return cls(pressure, temperature, species_concentrations, reaction_rates)

@classmethod
def from_config_JSON(cls, config_JSON, species_list, reaction_list):
def from_config_JSON(cls, path_to_json, config_JSON, species_list, reaction_list):
pressure = convert_pressure(config_JSON['environmental conditions']['pressure'], 'initial value')

temperature = convert_temperature(config_JSON['environmental conditions']['temperature'], 'initial value')


# Set initial species concentrations
species_concentrations = []
reaction_rates = []

#reads initial conditions from csv if it is given
if 'initial conditions' in config_JSON:
initial_conditions_csv = config_JSON['initial conditions']
#read_initial_conditions_from_csv(initial_conditions_csv)
if 'initial conditions' in config_JSON and len(list(config_JSON['initial conditions'].keys())) > 0:

initial_conditions_path = os.path.dirname(path_to_json) + "/" + list(config_JSON['initial conditions'].keys())[0]
reaction_rates = Conditions.read_initial_rates_from_file(initial_conditions_path, reaction_list)


#reads from config file directly if present
if 'chemical species' in config_JSON:
for chem_spec in config_JSON['chemical species']:
Expand All @@ -105,16 +110,44 @@ def from_config_JSON(cls, config_JSON, species_list, reaction_list):

#TODO: may or may not be necessary
# Set initial reaction rates
reaction_rates = []

for reaction in reaction_list.reactions:
if reaction.name != None and not any(reac.reaction.name == reaction.name for reac in reaction_rates):
reaction_rates.append(ReactionRate(reaction, 0))


return cls(pressure, temperature, species_concentrations, reaction_rates)


@classmethod
def read_initial_rates_from_file(cls, file_path, reaction_list):

reaction_rates = []

with open(file_path, 'r') as csv_file:
initial_conditions = list(csv.reader(csv_file))

if(len(initial_conditions) > 1):
# The first row of the CSV contains headers
headers = initial_conditions[0]

# The second row of the CSV contains rates
rates = initial_conditions[1]


for i in range(0, len(headers)):


reaction_rate = headers[i]

match = filter(lambda x: x.name == reaction_rate.split('.')[1], reaction_list.reactions)

reaction = next(match, None)
rate = rates[i]

reaction_rates.append(ReactionRate(reaction, rate))
return reaction_rates


def add_species_concentration(self, species_concentration):
"""
Expand Down
103 changes: 52 additions & 51 deletions src/acom_music_box/music_box_evolving_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,58 +125,59 @@ def read_conditions_from_file(cls, file_path, species_list, reaction_list):

# Open the evolving conditions file and read it as a CSV
with open(file_path, 'r') as csv_file:
evolving_conditions = list(csv.reader(csv_file))

# The first row of the CSV contains headers
headers = evolving_conditions[0]
evolving_conditions = list(csv.reader(csv_file))

# Iterate over the remaining rows of the CSV
for i in range(1, len(evolving_conditions)):
# The first column of each row is a time value
times.append(float(evolving_conditions[i][0]))

# Initialize pressure and temperature as None
pressure = None
temperature = None

# If pressure and temperature headers are present in the CSV, extract their values
if 'ENV.pressure.Pa' in headers:
pressure = float(evolving_conditions[i][headers.index('ENV.pressure.Pa')])
if 'ENV.temperature.K' in headers:
temperature = float(evolving_conditions[i][headers.index('ENV.temperature.K')])

# Initialize concentrations list and extract concentration headers
concentrations = []
concentration_headers = list(filter(lambda x: 'CONC' in x, headers))

# For each concentration header, find the matching species and append its concentration to the list
for j in range(len(concentration_headers)):
match = filter(lambda x: x.name == concentration_headers[j].split('.')[1], species_list.species)
species = next(match, None)
concentration = float(evolving_conditions[i][headers.index(concentration_headers[j])])

concentrations.append(SpeciesConcentration(species, concentration))


# Initialize rates list and extract rate headers
rates = []
rate_headers = list(filter(lambda x: 's-1' in x, headers))

# For each rate header, find the matching reaction and append its rate to the list
for k in range(len(rate_headers)):
name_to_match = rate_headers[k].split('.')

if name_to_match[0] == 'LOSS' or name_to_match[0] == 'EMIS':
name_to_match = name_to_match[0] + '_' + name_to_match[1]
else:
name_to_match = name_to_match[1]
match = filter(lambda x: x.name == name_to_match, reaction_list.reactions)
reaction = next(match, None)
rate = float(evolving_conditions[i][headers.index(rate_headers[k])])
rates.append(ReactionRate(reaction, rate))

# Append the conditions for this time point to the conditions list
conditions.append(Conditions(pressure, temperature, concentrations, rates))
if(len(evolving_conditions) > 1):
# The first row of the CSV contains headers
headers = evolving_conditions[0]

# Iterate over the remaining rows of the CSV
for i in range(1, len(evolving_conditions)):
# The first column of each row is a time value
times.append(float(evolving_conditions[i][0]))

# Initialize pressure and temperature as None
pressure = None
temperature = None

# If pressure and temperature headers are present in the CSV, extract their values
if 'ENV.pressure.Pa' in headers:
pressure = float(evolving_conditions[i][headers.index('ENV.pressure.Pa')])
if 'ENV.temperature.K' in headers:
temperature = float(evolving_conditions[i][headers.index('ENV.temperature.K')])

# Initialize concentrations list and extract concentration headers
concentrations = []
concentration_headers = list(filter(lambda x: 'CONC' in x, headers))

# For each concentration header, find the matching species and append its concentration to the list
for j in range(len(concentration_headers)):
match = filter(lambda x: x.name == concentration_headers[j].split('.')[1], species_list.species)
species = next(match, None)
concentration = float(evolving_conditions[i][headers.index(concentration_headers[j])])

concentrations.append(SpeciesConcentration(species, concentration))


# Initialize rates list and extract rate headers
rates = []
rate_headers = list(filter(lambda x: 's-1' in x, headers))

# For each rate header, find the matching reaction and append its rate to the list
for k in range(len(rate_headers)):
name_to_match = rate_headers[k].split('.')

if name_to_match[0] == 'LOSS' or name_to_match[0] == 'EMIS':
name_to_match = name_to_match[0] + '_' + name_to_match[1]
else:
name_to_match = name_to_match[1]
match = filter(lambda x: x.name == name_to_match, reaction_list.reactions)
reaction = next(match, None)
rate = float(evolving_conditions[i][headers.index(rate_headers[k])])
rates.append(ReactionRate(reaction, rate))

# Append the conditions for this time point to the conditions list
conditions.append(Conditions(pressure, temperature, concentrations, rates))

# Return a new instance of the class with the times and conditions

Expand Down
3 changes: 2 additions & 1 deletion src/acom_music_box/music_box_reaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Reaction:
products (List[Product]): A list of Product instances representing the products. Default is an empty list.
"""

def __init__(self, name=None, reaction_type=None, reactants=None, products=None):
def __init__(self, name=None, reaction_type=None, reactants=None, products=None, scaling_factor=None):
"""
Initializes a new instance of the Reaction class.
Expand All @@ -25,6 +25,7 @@ def __init__(self, name=None, reaction_type=None, reactants=None, products=None)
self.reaction_type = reaction_type
self.reactants = reactants if reactants is not None else []
self.products = products if products is not None else []
self.scaling_factor = scaling_factor

def add_reactant(self, reactant):
"""
Expand Down
3 changes: 2 additions & 1 deletion src/acom_music_box/music_box_reaction_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def get_products_from_JSON(self, reaction, species_list):
def get_reactions_from_JSON(self, reaction, species_list):

name = reaction['MUSICA name'] if 'MUSICA name' in reaction else None
scaling_factor = reaction['scaling factor'] if 'scaling factor' in reaction else None
reaction_type = reaction['type']

reactants = ReactionList.get_reactants_from_JSON(reaction, species_list)
Expand Down Expand Up @@ -163,4 +164,4 @@ def get_reactions_from_JSON(self, reaction, species_list):
N = reaction.get('N')
return Troe_Ternary(name, reaction_type, reactants, products, k0_A, k0_B, k0_C, kinf_A, kinf_B, kinf_C, Fc, N)
else:
return Reaction(name, reaction_type, reactants, products)
return Reaction(name, reaction_type, reactants, products, scaling_factor)
Loading

0 comments on commit adbdbb9

Please sign in to comment.