11from .utils import convert_pressure , convert_temperature , convert_concentration
2- from .species_concentration import SpeciesConcentration
3- from .species import Species
4- from .reaction_rate import ReactionRate
5- from typing import List
6- import csv
2+ import pandas as pd
73import os
8- from typing import List
9- from .reaction_rate import ReactionRate
10- from .species import Species
11- from .species_concentration import SpeciesConcentration
124
135import logging
146logger = logging .getLogger (__name__ )
@@ -38,13 +30,13 @@ def __init__(
3830 Args:
3931 pressure (float): The pressure of the conditions in atmospheres.
4032 temperature (float): The temperature of the conditions in Kelvin.
41- species_concentrations (List[SpeciesConcentration ]): A list of species concentrations. Default is an empty list .
42- reaction_rates (List[ReactionRate ]): A list of reaction rates. Default is an empty list .
33+ species_concentrations (Dict[Species, float ]): A dictionary of species concentrations.
34+ reaction_rates (Dict[Reaction, float ]): A dictionary of reaction rates.
4335 """
4436 self .pressure = pressure
4537 self .temperature = temperature
46- self .species_concentrations = species_concentrations if species_concentrations is not None else []
47- self .reaction_rates = reaction_rates if reaction_rates is not None else []
38+ self .species_concentrations = species_concentrations if species_concentrations is not None else {}
39+ self .reaction_rates = reaction_rates if reaction_rates is not None else {}
4840
4941 def __repr__ (self ):
5042 return f"Conditions(pressure={ self .pressure } , temperature={ self .temperature } , species_concentrations={ self .species_concentrations } , reaction_rates={ self .reaction_rates } )"
@@ -117,9 +109,7 @@ def from_UI_JSON(self, UI_JSON, species_list, reaction_list):
117109 def from_config_JSON (
118110 self ,
119111 path_to_json ,
120- config_JSON ,
121- species_list ,
122- reaction_list ):
112+ object ):
123113 """
124114 Creates an instance of the class from a configuration JSON object.
125115
@@ -128,75 +118,51 @@ def from_config_JSON(
128118
129119 Args:
130120 path_to_json (str): The path to the JSON file containing the initial conditions and settings.
131- config_JSON (dict): The configuration JSON object containing the initial conditions and settings.
132- species_list (SpeciesList): A SpeciesList containing the species involved in the simulation.
133- reaction_list (ReactionList): A ReactionList containing the reactions involved in the simulation.
121+ object (dict): The configuration JSON object containing the initial conditions and settings.
134122
135123 Returns:
136124 object: An instance of the Conditions class with the settings from the configuration JSON object.
137125 """
138126 pressure = convert_pressure (
139- config_JSON ['environmental conditions' ]['pressure' ],
127+ object ['environmental conditions' ]['pressure' ],
140128 'initial value' )
141129
142130 temperature = convert_temperature (
143- config_JSON ['environmental conditions' ]['temperature' ],
131+ object ['environmental conditions' ]['temperature' ],
144132 'initial value' )
145133
146134 # Set initial species concentrations
147- species_concentrations = []
148- reaction_rates = []
135+ initial_concentrations = {}
136+ reaction_rates = {}
149137
150138 # reads initial conditions from csv if it is given
151- if 'initial conditions' in config_JSON and len (
152- list (config_JSON ['initial conditions' ].keys ())) > 0 :
139+ if 'initial conditions' in object and len (
140+ list (object ['initial conditions' ].keys ())) > 0 :
153141
154142 initial_conditions_path = os .path .join (
155143 os .path .dirname (path_to_json ),
156- list (config_JSON ['initial conditions' ].keys ())[0 ])
144+ list (object ['initial conditions' ].keys ())[0 ])
157145
158146 reaction_rates = Conditions .read_initial_rates_from_file (
159- initial_conditions_path , reaction_list )
147+ initial_conditions_path )
160148
161149 # reads from config file directly if present
162- if 'chemical species' in config_JSON :
163- for chem_spec in config_JSON ['chemical species' ]:
164- species = Species (name = chem_spec )
165- concentration = convert_concentration (
166- config_JSON ['chemical species' ][chem_spec ], 'initial value' , temperature , pressure )
167-
168- species_concentrations .append (
169- SpeciesConcentration (
170- species , concentration ))
171-
172- for species in species_list .species :
173- if species .tracer_type == 'THIRD_BODY' :
174- continue
175- if not any (conc .species .name ==
176- species .name for conc in species_concentrations ):
177- species_concentrations .append (SpeciesConcentration (species , 0 ))
178-
179- # Set initial reaction rates
180- for reaction in reaction_list .reactions :
181- if (reaction .name is None ):
182- continue
183- reaction_exists = False
184- for rate in reaction_rates :
185- if rate .reaction .name == reaction .name :
186- reaction_exists = True
187- break
188-
189- if not reaction_exists :
190- reaction_rates .append (ReactionRate (reaction , 0 ))
150+ if 'chemical species' in object :
151+ initial_concentrations = {
152+ species : convert_concentration (
153+ object ['chemical species' ][species ], 'initial value' , temperature , pressure
154+ )
155+ for species in object ['chemical species' ]
156+ }
191157
192158 return self (
193159 pressure ,
194160 temperature ,
195- species_concentrations ,
161+ initial_concentrations ,
196162 reaction_rates )
197163
198164 @classmethod
199- def read_initial_rates_from_file (self , file_path , reaction_list ):
165+ def read_initial_rates_from_file (cls , file_path ):
200166 """
201167 Reads initial reaction rates from a file.
202168
@@ -205,29 +171,32 @@ def read_initial_rates_from_file(self, file_path, reaction_list):
205171
206172 Args:
207173 file_path (str): The path to the file containing the initial reaction rates.
208- reaction_list (ReactionList): A ReactionList containing the reactions involved in the simulation.
209174
210175 Returns:
211- list : A list where each element represents the initial rate of a reaction.
176+ dict : A dictionary of initial reaction rates .
212177 """
213178
214- reaction_rates = []
215-
216- with open (file_path , 'r' ) as csv_file :
217- initial_conditions = list (csv .reader (csv_file ))
218-
219- if (len (initial_conditions ) > 1 ):
220- # The first row of the CSV contains headers
221- headers = initial_conditions [0 ]
222-
223- # The second row of the CSV contains rates
224- rates = initial_conditions [1 ]
225-
226- for reaction_rate , rate in zip (headers , rates ):
227- type , name , * rest = reaction_rate .split ('.' )
228- for reaction in reaction_list .reactions :
229- if reaction .name == name and reaction .short_type () == type :
230- reaction_rates .append (ReactionRate (reaction , rate ))
179+ reaction_rates = {}
180+
181+ df = pd .read_csv (file_path )
182+ rows , _ = df .shape
183+ if rows > 1 :
184+ raise ValueError (f'Initial conditions file ({ file_path } ) may only have one row of data. There are { rows } rows present.' )
185+ for key in df .columns :
186+ parts = key .split ('.' )
187+ reaction_type , label = None , None
188+ if len (parts ) == 3 :
189+ reaction_type , label , units = parts
190+ elif len (parts ) == 2 :
191+ reaction_type , label = parts
192+ else :
193+ error = f"Unexpected format in key: { key } "
194+ logger .error (error )
195+ raise ValueError (error )
196+ rate_name = f'{ reaction_type } .{ label } '
197+ if rate_name in reaction_rates :
198+ raise ValueError (f"Duplicate reaction rate found: { rate_name } " )
199+ reaction_rates [rate_name ] = df .iloc [0 ][key ]
231200
232201 return reaction_rates
233202
@@ -294,18 +263,6 @@ def update_conditions(self, new_conditions):
294263 self .pressure = new_conditions .pressure
295264 if new_conditions .temperature is not None :
296265 self .temperature = new_conditions .temperature
297- for conc in new_conditions .species_concentrations :
298- match = filter (
299- lambda x : x .species .name == conc .species .name ,
300- self .species_concentrations )
301- for item in list (match ):
302- item .concentration = conc .concentration
303-
304- for rate in new_conditions .reaction_rates :
305-
306- match = filter (
307- lambda x : x .reaction .name == rate .reaction .name ,
308- self .reaction_rates )
266+ self .species_concentrations .update (new_conditions .species_concentrations )
309267
310- for item in list (match ):
311- item .rate = rate .rate
268+ self .reaction_rates .update (new_conditions .reaction_rates )
0 commit comments