diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle index 9aea328..bfa0d33 100644 Binary files a/docs/_build/doctrees/environment.pickle and b/docs/_build/doctrees/environment.pickle differ diff --git a/docs/_build/doctrees/guide/about.doctree b/docs/_build/doctrees/guide/about.doctree deleted file mode 100644 index ef90f74..0000000 Binary files a/docs/_build/doctrees/guide/about.doctree and /dev/null differ diff --git a/docs/_build/doctrees/guide/install.doctree b/docs/_build/doctrees/guide/install.doctree index 88d39c3..46eb899 100644 Binary files a/docs/_build/doctrees/guide/install.doctree and b/docs/_build/doctrees/guide/install.doctree differ diff --git a/docs/_build/doctrees/guide/quickstart.doctree b/docs/_build/doctrees/guide/quickstart.doctree index bfd9bfb..3f643f7 100644 Binary files a/docs/_build/doctrees/guide/quickstart.doctree and b/docs/_build/doctrees/guide/quickstart.doctree differ diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree index 9d5c4ce..9a0fc6a 100644 Binary files a/docs/_build/doctrees/index.doctree and b/docs/_build/doctrees/index.doctree differ diff --git a/docs/_build/doctrees/modules/LLEPE.doctree b/docs/_build/doctrees/modules/LLEPE.doctree deleted file mode 100644 index 9b52f4a..0000000 Binary files a/docs/_build/doctrees/modules/LLEPE.doctree and /dev/null differ diff --git a/docs/_build/doctrees/modules/reeps.doctree b/docs/_build/doctrees/modules/reeps.doctree index 87fd4d1..e316e1a 100644 Binary files a/docs/_build/doctrees/modules/reeps.doctree and b/docs/_build/doctrees/modules/reeps.doctree differ diff --git a/docs/_build/html/.buildinfo b/docs/_build/html/.buildinfo index 51dc31b..d0738d2 100644 --- a/docs/_build/html/.buildinfo +++ b/docs/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: fdde7da710e99305b2f90b2ffb8f91ce +config: 09c8b5742a1f96cda53a1848d8ac9ec1 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_build/html/_modules/index.html b/docs/_build/html/_modules/index.html index d96106f..ca853b9 100644 --- a/docs/_build/html/_modules/index.html +++ b/docs/_build/html/_modules/index.html @@ -85,11 +85,10 @@

Searchers

@@ -152,6 +151,7 @@

All modules for which code is available

@@ -164,7 +164,7 @@

- © Copyright 2020, UChicago Argonne, LLC. + © Copyright 2020, Titus Quah, Nwike Iloeje

diff --git a/docs/_build/html/_modules/llepe/llepe.html b/docs/_build/html/_modules/llepe/llepe.html index 13e2620..bf78f9b 100644 --- a/docs/_build/html/_modules/llepe/llepe.html +++ b/docs/_build/html/_modules/llepe/llepe.html @@ -85,11 +85,10 @@

Searchers

@@ -170,7 +169,7 @@ from .utils import set_size -
[docs]class LLEPE: +
[docs]class LLEPE: r""" Liquid-Liquid Extraction Parameter estimator @@ -181,7 +180,7 @@ must be the same order as they appear in the xml, complex_names and extracted_species_ion_names. - For example, say in exp_data, ES_1 is Nd ES_2 is Pr, + For example, say in exp_csv_filename's csv, ES_1 is Nd ES_2 is Pr, and .. code-block:: python @@ -192,7 +191,7 @@ Then: - The exp_data column ordering must be (names do not matter): + The csvs column ordering must be: [h_i, h_eq, z_i, z_eq, Nd_aq_i, Nd_aq_eq, Nd_d_eq, Pr_aq_i, Pr_aq_eq, Pr_d_eq] @@ -527,8 +526,7 @@ self._predicted_dict = None self.update_predicted_dict() - # TODO: move scipy_minimize to optimizers -
[docs] @staticmethod +
[docs] @staticmethod def scipy_minimize(objective, x_guess, optimizer_kwargs=None): """ The default optimizer for LLEPE @@ -562,8 +560,7 @@ est_parameters = res.x return est_parameters, res.fun
- # TODO: move log_mean_squared_error to objectives -
[docs] def log_mean_squared_error(self, predicted_dict, meas_df): +
[docs] def log_mean_squared_error(self, predicted_dict, meas_df): """Default objective function for LLEPE Returns the log mean squared error of @@ -587,14 +584,14 @@ obj = np.sum(log_diff) return obj
-
[docs] def get_exp_df(self) -> pd.DataFrame: +
[docs] def get_exp_df(self) -> pd.DataFrame: """Returns the experimental DataFrame :return: (pd.DataFrame) Experimental data """ return self._exp_df
-
[docs] def set_exp_df(self, exp_data): +
[docs] def set_exp_df(self, exp_data): """Changes the experimental DataFrame to input exp_csv_filename data and renames columns to internal LLEPE names @@ -635,7 +632,7 @@ self.update_predicted_dict() return None
-
[docs] def get_phases(self) -> list: +
[docs] def get_phases(self) -> list: """ Returns the list of Cantera solutions @@ -643,7 +640,7 @@ """ return self._phases
-
[docs] def set_phases(self, phases_xml_filename, phase_names): +
[docs] def set_phases(self, phases_xml_filename, phase_names): """Change list of Cantera solutions by inputting new xml file name and phase names @@ -676,7 +673,7 @@ self.update_predicted_dict() return None
-
[docs] def get_opt_dict(self) -> dict: +
[docs] def get_opt_dict(self) -> dict: """ Returns the dictionary containing optimization information @@ -685,7 +682,7 @@ """ return self._opt_dict
-
[docs] def set_opt_dict(self, opt_dict): +
[docs] def set_opt_dict(self, opt_dict): """ Change the dictionary to input opt_dict. @@ -701,14 +698,14 @@ self._opt_dict = opt_dict return None
-
[docs] def get_aq_solvent_name(self) -> str: +
[docs] def get_aq_solvent_name(self) -> str: """Returns aq_solvent_name :return: aq_solvent_name: (str) name of aqueous solvent in xml file """ return self._aq_solvent_name
-
[docs] def set_aq_solvent_name(self, aq_solvent_name): +
[docs] def set_aq_solvent_name(self, aq_solvent_name): """ Change aq_solvent_name to input aq_solvent_name :param aq_solvent_name: (str) name of aqueous solvent in xml file @@ -716,14 +713,14 @@ self._aq_solvent_name = aq_solvent_name return None
-
[docs] def get_extractant_name(self) -> str: +
[docs] def get_extractant_name(self) -> str: """Returns extractant name :return: extractant_name: (str) name of extractant in xml file """ return self._extractant_name
-
[docs] def set_extractant_name(self, extractant_name): +
[docs] def set_extractant_name(self, extractant_name): """ Change extractant_name to input extractant_name :param extractant_name: (str) name of extractant in xml file @@ -731,13 +728,13 @@ self._extractant_name = extractant_name return None
-
[docs] def get_diluant_name(self) -> str: +
[docs] def get_diluant_name(self) -> str: """ Returns diluant name :return: diluant_name: (str) name of diluant in xml file """ return self._diluant_name
-
[docs] def set_diluant_name(self, diluant_name): +
[docs] def set_diluant_name(self, diluant_name): """ Change diluant_name to input diluant_name @@ -746,14 +743,14 @@ self._diluant_name = diluant_name return None
-
[docs] def get_complex_names(self) -> list: +
[docs] def get_complex_names(self) -> list: """Returns list of complex names :return: complex_names: (list) names of complexes in xml file. """ return self._complex_names
-
[docs] def set_complex_names(self, complex_names): +
[docs] def set_complex_names(self, complex_names): """Change complex names list to input complex_names :param complex_names: (list) names of complexes in xml file. @@ -761,7 +758,7 @@ self._complex_names = complex_names return None
-
[docs] def get_extracted_species_ion_names(self) -> list: +
[docs] def get_extracted_species_ion_names(self) -> list: """Returns list of extracted species ion names :return: extracted_species_ion_names: (list) names of @@ -769,7 +766,7 @@ """ return self._extracted_species_ion_names
-
[docs] def set_extracted_species_ion_names(self, extracted_species_ion_names): +
[docs] def set_extracted_species_ion_names(self, extracted_species_ion_names): """Change list of extracted species ion names to input extracted_species_ion_names @@ -779,7 +776,7 @@ self._extracted_species_ion_names = extracted_species_ion_names return None
-
[docs] def get_extracted_species_list(self) -> list: +
[docs] def get_extracted_species_list(self) -> list: """Returns list of extracted species names :return: extracted_species_list: (list) names of extracted species in @@ -787,7 +784,7 @@ """ return self._extracted_species_list
-
[docs] def set_extracted_species_list(self, extracted_species_list): +
[docs] def set_extracted_species_list(self, extracted_species_list): """Change list of extracted species ion names to input extracted_species_ion_names @@ -797,14 +794,14 @@ self._extracted_species_list = extracted_species_list return None
-
[docs] def get_aq_solvent_rho(self) -> str: +
[docs] def get_aq_solvent_rho(self) -> str: """Returns aqueous solvent density (g/L) :return: aq_solvent_rho: (float) density of aqueous solvent """ return self._aq_solvent_rho
-
[docs] def set_aq_solvent_rho(self, aq_solvent_rho): +
[docs] def set_aq_solvent_rho(self, aq_solvent_rho): """Changes aqueous solvent density (g/L) to input aq_solvent_rho :param aq_solvent_rho: (float) density of aqueous solvent @@ -812,14 +809,14 @@ self._aq_solvent_rho = aq_solvent_rho return None
-
[docs] def get_extractant_rho(self) -> str: +
[docs] def get_extractant_rho(self) -> str: """Returns extractant density (g/L) :return: extractant_rho: (float) density of extractant """ return self._extractant_rho
-
[docs] def set_extractant_rho(self, extractant_rho): +
[docs] def set_extractant_rho(self, extractant_rho): """Changes extractant density (g/L) to input extractant_rho :param extractant_rho: (float) density of extractant @@ -827,14 +824,14 @@ self._extractant_rho = extractant_rho return None
-
[docs] def get_diluant_rho(self) -> str: +
[docs] def get_diluant_rho(self) -> str: """Returns diluant density (g/L) :return: diluant_rho: (float) density of diluant """ return self._diluant_rho
-
[docs] def set_diluant_rho(self, diluant_rho): +
[docs] def set_diluant_rho(self, diluant_rho): """Changes diluant density (g/L) to input diluant_rho :param diluant_rho: (float) density of diluant @@ -842,12 +839,7 @@ self._diluant_rho = diluant_rho return None
- # TODO: Change input DataFrame structure to contain information about - # other species like NaCl - # TODO: Change DataFrame structure to contain info about O/A ratio - # TODO: Generalize code to more than just org and aq phase (3+ phases) - # TODO: Handle multiple electrolytes ie. NO3- with Cl- -
[docs] def set_in_moles(self, feed_vol): +
[docs] def set_in_moles(self, feed_vol): """Function that initializes mole fractions to input feed_vol This function is called at initialization @@ -930,7 +922,7 @@ for extracted_species in extracted_species_list]) extracted_species_charge_sum = np.sum( extracted_species_charges * extracted_species_moles) - anion_moles = extracted_species_charge_sum + h_plus_moles + chlorine_moles = extracted_species_charge_sum + h_plus_moles extractant_moles = feed_vol * row['z_i'] extractant_vol = extractant_moles * extractant_mw / extractant_rho diluant_vol = feed_vol - extractant_vol @@ -940,7 +932,7 @@ species_moles_aq = [aq_phase_solvent_moles, h_plus_moles, hydroxide_ions, - anion_moles] + chlorine_moles] species_moles_aq.extend(list(extracted_species_moles)) species_moles_org = [extractant_moles, diluant_moles] species_moles_org.extend(list(complex_moles)) @@ -954,7 +946,7 @@ self.update_predicted_dict() return None
-
[docs] def get_in_moles(self) -> pd.DataFrame: +
[docs] def get_in_moles(self) -> pd.DataFrame: """Returns the in_moles DataFrame which contains the initial mole fractions of each species for each experiment @@ -962,7 +954,7 @@ """ return self._in_moles
-
[docs] def set_objective_function(self, objective_function): +
[docs] def set_objective_function(self, objective_function): """Change objective function to input objective_function. See class docstring on "objective_function" for instructions @@ -987,7 +979,7 @@ self._objective_function = objective_function return None
-
[docs] def get_objective_function(self): +
[docs] def get_objective_function(self): """Returns objective function :return: objective_function: (func) Objective function to quantify @@ -995,7 +987,7 @@ """ return self._objective_function
-
[docs] def set_optimizer(self, optimizer): +
[docs] def set_optimizer(self, optimizer): """Change optimizer function to input optimizer. See class docstring on "optimizer" for instructions @@ -1020,7 +1012,7 @@ self._optimizer = optimizer return None
-
[docs] def get_optimizer(self): +
[docs] def get_optimizer(self): """Returns objective function :return: optimizer: (func) Optimizer function to minimize objective @@ -1028,7 +1020,7 @@ """ return self._optimizer
-
[docs] def get_temp_xml_file_path(self): +
[docs] def get_temp_xml_file_path(self): """Returns path to temporary xml file. This xml file is a duplicate of the phases_xml_file name and is @@ -1039,7 +1031,7 @@ """ return self._temp_xml_file_path
-
[docs] def set_temp_xml_file_path(self, temp_xml_file_path): +
[docs] def set_temp_xml_file_path(self, temp_xml_file_path): """Changes temporary xml file path to input temp_xml_file_path. This xml file is a duplicate of the phases_xml_file name and is @@ -1051,7 +1043,7 @@ self._temp_xml_file_path = temp_xml_file_path return None
-
[docs] def get_dependant_params_dict(self): +
[docs] def get_dependant_params_dict(self): """ Returns the dependant_params_dict @@ -1060,7 +1052,7 @@ """ return self._dependant_params_dict
-
[docs] def set_dependant_params_dict(self, dependant_params_dict): +
[docs] def set_dependant_params_dict(self, dependant_params_dict): """ Sets the dependant_params_dict @@ -1070,7 +1062,7 @@ self._dependant_params_dict = dependant_params_dict return None
-
[docs] def get_custom_objects_dict(self): +
[docs] def get_custom_objects_dict(self): """ Returns the custom_objects_dict @@ -1079,7 +1071,7 @@ """ return self._custom_objects_dict
-
[docs] def set_custom_objects_dict(self, custom_objects_dict): +
[docs] def set_custom_objects_dict(self, custom_objects_dict): """ Sets the custom_objects_dict @@ -1089,11 +1081,7 @@ self._custom_objects_dict = custom_objects_dict return None
- # TODO: Change DataFrame strucutre to contain info whether to set - # equilibrium pH to measured value. Will be useful for saponification - # TODO: Find way to add saponification to model. - # Maybe use fsolve to match experimental equilibrium pH -
[docs] def update_predicted_dict(self, +
[docs] def update_predicted_dict(self, phases_xml_filename=None, phase_names=None): """Function that computes the predicted equilibrium concentrations @@ -1160,7 +1148,7 @@ self._predicted_dict = predicted_dict return None
-
[docs] def get_predicted_dict(self): +
[docs] def get_predicted_dict(self): """Returns predicted dictionary of species concentrations that xml parameters predicts given current in_moles @@ -1224,7 +1212,7 @@ objective_values = objective_values[0] return objective_values -
[docs] def fit(self, +
[docs] def fit(self, objective_function=None, optimizer=None, objective_kwargs=None, @@ -1267,7 +1255,7 @@ return opt_dict, obj_value
-
[docs] def update_xml(self, +
[docs] def update_xml(self, info_dict, phases_xml_filename=None, dependant_params_dict=None): @@ -1374,7 +1362,7 @@ self.set_phases(self._phases_xml_filename, self._phase_names) return None
-
[docs] def update_custom_objects_dict(self, info_dict): +
[docs] def update_custom_objects_dict(self, info_dict): """ updates internal custom_objects_dict with info_dict @@ -1399,7 +1387,7 @@ self._custom_objects_dict = custom_objects_dict return None
-
[docs] def parity_plot(self, +
[docs] def parity_plot(self, compared_value=None, c_data=None, c_label=None, @@ -1508,9 +1496,7 @@ filtered_meas = filtered_data['meas'] filtered_pred = filtered_data['pred'] if len(filtered_pred) != 0: - ax.scatter(filtered_meas, - filtered_pred, - label=label) + ax.scatter(filtered_meas, filtered_pred, label=label) if legend: ax.legend(loc='best') @@ -1545,7 +1531,7 @@ plt.savefig(save_path, bbox_inches='tight') return fig, ax
-
[docs] def r_squared(self, compared_value=None): +
[docs] def r_squared(self, compared_value=None): """r-squared value comparing measured and predicted compared value Closer to 1, the better the model's predictions. @@ -1585,7 +1571,7 @@ r_2 = (1 - num / den) return r_2
-
[docs] @staticmethod +
[docs] @staticmethod def plot_3d_data(x_data, y_data, z_data, @@ -1595,8 +1581,6 @@ z_label=None, c_label=None): """ - THis is for plotting 3d scatter plots. - We suggest use matplotlib's ax.scatter to make 3d plots. :param x_data: (list) list of data for x axis :param y_data: (list) list of data for y axis @@ -1647,7 +1631,7 @@

- © Copyright 2020, UChicago Argonne, LLC. + © Copyright 2020, Titus Quah, Nwike Iloeje

diff --git a/docs/_build/html/_modules/reeps/reeps.html b/docs/_build/html/_modules/reeps/reeps.html new file mode 100644 index 0000000..bb9a06e --- /dev/null +++ b/docs/_build/html/_modules/reeps/reeps.html @@ -0,0 +1,1735 @@ + + + + + + + + + + + reeps.reeps — LLEPE 1.0.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for reeps.reeps

+from datetime import datetime
+import cantera as ct
+import pandas as pd
+import numpy as np
+from scipy.optimize import minimize
+# noinspection PyPep8Naming
+import xml.etree.ElementTree as ET
+import seaborn as sns
+import matplotlib.pyplot as plt
+import shutil
+import copy
+from inspect import signature
+import os
+import re
+import pkg_resources
+from .utils import set_size
+
+sns.set()
+sns.set(font_scale=1.6)
+
+
+
[docs]class REEPS: + r""" + Rare earth elements (REE or RE) Takes in experimental data + Returns parameters for GEM + + .. note:: + + The order in which the REEs appear in the csv file must be the same + order as they appear in the xml, complex_names and + rare_earth_ion_names. + + For example, say in exp_csv_filename's csv, RE_1 is Nd RE_2 is Pr, + and + + .. code-block:: python + + aq_solvent_name = 'H2O(L)' + extractant_name = '(HA)2(org)' + diluent_name = 'dodecane' + + Then: + + The csvs column ordering must be: + + [h_i, h_eq, z_i, z_eq, Nd_aq_i, Nd_aq_eq, Nd_d_eq, + Pr_aq_i, Pr_aq_eq, Pr_d_eq] + + The aqueous speciesArray must be + "H2O(L) H+ OH- Cl- Nd+++ Pr+++" + + The organic speciesArray must be + "(HA)2(org) dodecane Nd(H(A)2)3(org) Pr(H(A)2)3(org)" + + .. code-block:: python + + complex_names = ['Nd(H(A)2)3(org)', 'Pr(H(A)2)3(org)'] + rare_earth_ion_names = ['Nd+++', 'Pr+++'] + + + :param exp_data: (str) csv file name with experimental data + + In the .csv file, the rows are different experiments and + columns are the measured quantities. + + The ordering of the columns needs to be: + + [h_i, h_eq, z_i, z_eq, + {RE_1}_aq_i, {RE_1}_aq_eq, {RE_1}_d_eq, + {RE_2}_aq_i, {RE_2}_aq_eq, {RE_2}_d_eq,... + {RE_N}_aq_i, {RE_N}_aq_eq, {RE_N}_d_eq] + + Naming does not matter, just the order. + + Where {RE_1}-{RE_N} are the rare earth element names of interest + i.e. Nd, Pr, La, etc. + + Below is an explanation of the columns. + + +-------+------------+------------------------------------------+ + | Index | Column | Meaning | + +=======+============+==========================================+ + | 0 | h_i | Initial Concentration of | + | | | H+ ions (mol/L) | + +-------+------------+------------------------------------------+ + | 1 | h_eq | Equilibrium concentration of | + | | | H+ ions (mol/L) | + +-------+------------+------------------------------------------+ + | 2 | z_i | Initial concentration of | + | | | extractant (mol/L) | + +-------+------------+------------------------------------------+ + | 3 | z_eq | Equilibrium concentration of | + | | | extractant (mol/L) | + +-------+------------+------------------------------------------+ + | 4 | {RE}_aq_i | Initial concentration of RE ions (mol/L) | + +-------+------------+------------------------------------------+ + | 5 | {RE}_aq_eq | Equilibrium concentration of RE ions | + | | | in aqueous phase (mol/L) | + +-------+------------+------------------------------------------+ + | 6 | {RE}_d_eq | Equilibrium Ratio between amount of | + | | | RE atoms in organic to aqueous | + +-------+------------+------------------------------------------+ + :param phases_xml_filename: (str) xml file with parameters + for equilibrium calc + + Would recommend copying and modifying xmls located in data/xmls + or in Cantera's "data" folder + + speciesArray fields need specific ordering. + + In aqueous phase: aq_solvent_name, H+, OH-, Cl-, RE_1, RE_2, ..., RE_N + + For aqueous phase, RE_1-RE_N represent RE ion names i.e. Nd+++, Pr+++ + + In organic phase : extractant_name, diluant_name, RE_1, RE_2, ..., RE_N + + For organic phase, RE_1-RE_N represent RE complex names + i.e. Nd(H(A)2)3(org), Pr(H(A)2)3(org) + + :param phase_names: (list) names of phases in xml file + + Found in the xml file under <phase ... id={phase_name}> + + :param aq_solvent_name: (str) name of aqueous solvent in xml file + :param extractant_name: (str) name of extractant in xml file + :param diluant_name: (str) name of diluant in xml file + :param complex_names: (list) names of complexes in xml file. + + Ensure the ordering is correct + :param rare_earth_ion_names: (list) names of rare earth ions in xml file + + Ensure the ordering is correct + :param re_species_list: (list) names of rare earth elements. + + If ``None``, re_species_list will be rare_earth_ion_names without '+' + i.e. 'Nd+++'->'Nd' + + Ensure the ordering is correct + :param aq_solvent_rho: (float) density of solvent (g/L) + + If ``None``, molar volume/molecular weight is used from xml + :param extractant_rho: (float) density of extractant (g/L) + + If ``None``, molar volume/molecular weight is used from xml + :param diluant_rho: (float) density of diluant (g/L) + + If ``None``, molar volume/molecular weight is used from xml + :param opt_dict: (dict) dictionary containing info about which + species parameters are updated to fit model to experimental data + + Should have the format as below. Dictionary keys under user defined + parameter name must be named as shown below ('upper_element_name', + 'upper_attrib_name', etc.). 'attrib_name's and 'attrib_value's can + be None. {} denotes areas for user to fill in. + + .. code-block:: python + + opt_dict = {"{user_defined_name_for_parameter_1}": + {'upper_element_name': {param_upper_element}, + 'upper_attrib_name': {param_upper_attrib_name}, + 'upper_attrib_value': {param_upper_attrib_value}, + 'lower_element_name': {param_lower_element}, + 'lower_attrib_name': {param_lower_attrib_name}, + 'lower_attrib_value': {param_lower_attrib_value}, + 'input_format': {str format to input input_value} + 'input_value': {guess_value}}, + "{user_defined_name_for_parameter_2}": + ... + ... + } + :param objective_function: (function or str) function to compute objective + + By default, the objective function is log mean squared error + of distribution ratio + + .. code-block:: python + + np.sum((np.log10(d_pred)-np.log10(d_meas))^2) + + Function needs to take inputs: + + .. code-block:: python + + objective_function(predicted_dict, measured_df, kwargs) + + ``kwargs`` is optional + + Function needs to return: (float) value computed by objective function + + Below is the guide for referencing predicted values + + +---------------------------+--------------------------------+ + | To access | Use | + +===========================+================================+ + | hydrogen ion conc in aq | predicted_dict['h_eq'] | + +---------------------------+--------------------------------+ + | extractant conc in org | predicted_dict['z_eq'] | + +---------------------------+--------------------------------+ + | RE ion eq conc in aq | predicted_dict['{RE}_aq_eq'] | + +---------------------------+--------------------------------+ + | RE complex eq conc in org | predicted_dict['{RE}_org_eq'] | + +---------------------------+--------------------------------+ + | RE distribution ratio | predicted_dict['{RE}_d_eq'] | + +---------------------------+--------------------------------+ + + Replace "{RE}" with rare earth element i.e. Nd, La, etc. + + For measured values, use the same names, but + replace ``predicted_dict`` with ``measured_df`` + :param optimizer: (function or str) function to perform optimization + + .. note:: + + The optimized variables are not directly the species parameters, + but instead are first multiplied by the initial guess before + sending becoming the species parameters. + + For example, say + + .. code-block:: python + + opt_dict = {'Nd(H(A)2)3(org):'h0':-4.7e6} + + If the bounds on h0 need to be [-4.7e7,-4.7e5], then + divide the bounds by the guess and get + + .. code-block:: python + + "bounds": [(1e-1, 1e1)] + + By default, the optimizer is scipy's optimize function with + + .. code-block:: python + + default_kwargs= {"method": 'SLSQP', + "bounds": [(1e-1, 1e1)] * len(x_guess), + "constraints": (), + "options": {'disp': True, + 'maxiter': 1000, + 'ftol': 1e-6}} + + Function needs to take inputs: + ``optimizer(objective_function, x_guess, kwargs)`` + + ``kwargs`` is optional + + Function needs to return: ((np.ndarray, float)) Optimized parameters, + objective_function value + + :param temp_xml_file_path: (str) path to temporary xml file. + + This xml file is a duplicate of the phases_xml_file name and is + modified during the optimization process to avoid changing the original + xml file + + default is local temp folder + + :param dependant_params_dict: (dict) dictionary containing information + about parameters dependant on opt_dict + """ + + def __init__(self, + exp_data, + phases_xml_filename, + phase_names, + aq_solvent_name, + extractant_name, + diluant_name, + complex_names, + rare_earth_ion_names, + re_species_list=None, + aq_solvent_rho=None, + extractant_rho=None, + diluant_rho=None, + opt_dict=None, + objective_function='Log-MSE', + optimizer='SLSQP', + temp_xml_file_path=None, + dependant_params_dict=None, + ): + self._built_in_obj_list = ['Log-MSE'] + self._built_in_opt_list = ['SLSQP'] + self._exp_data = exp_data + self._phases_xml_filename = phases_xml_filename + self._opt_dict = opt_dict + self._phase_names = phase_names + self._aq_solvent_name = aq_solvent_name + self._extractant_name = extractant_name + self._diluant_name = diluant_name + self._complex_names = complex_names + self._rare_earth_ion_names = rare_earth_ion_names + self._aq_solvent_rho = aq_solvent_rho + self._extractant_rho = extractant_rho + self._diluant_rho = diluant_rho + self._objective_function = None + self.set_objective_function(objective_function) + self._optimizer = None + self._re_species_list = re_species_list + self.set_optimizer(optimizer) + if temp_xml_file_path is None: + temp_xml_file_path = r'{0}/temp.xml'.format(os.getenv('TEMP')) + self._temp_xml_file_path = temp_xml_file_path + self._dependant_params_dict = dependant_params_dict + # Try and except for adding package data to path. + # This only works for sdist, not bdist + # If bdist is needed, research "manifest.in" python setup files + try: + shutil.copyfile(self._phases_xml_filename, + self._temp_xml_file_path) + self._phases = ct.import_phases(self._phases_xml_filename, + phase_names) + except FileNotFoundError: + self._phases_xml_filename = \ + pkg_resources.resource_filename('reeps', + r'..\data\xmls\{0}'.format( + phases_xml_filename)) + shutil.copyfile(self._phases_xml_filename, + self._temp_xml_file_path) + self._phases = ct.import_phases(self._phases_xml_filename, + phase_names) + if isinstance(self._exp_data, str): + try: + self._exp_df = pd.read_csv(self._exp_data) + except FileNotFoundError: + self._exp_data = pkg_resources.resource_filename( + 'reeps', r'..\data\csvs\{0}'.format(self._exp_data)) + self._exp_df = pd.read_csv(self._exp_data) + else: + self._exp_df = self._exp_data.copy() + + self._exp_df_columns = ['h_i', 'h_eq', 'z_i', 'z_eq'] + if self._re_species_list is None: + self._re_species_list = [] + for name in self._rare_earth_ion_names: + species = name.replace('+', '') + self._re_species_list.append(species) + for species in self._re_species_list: + self._exp_df_columns.append('{0}_aq_i'.format(species)) + self._exp_df_columns.append('{0}_aq_eq'.format(species)) + self._exp_df_columns.append('{0}_d_eq'.format(species)) + + self._exp_df.columns = self._exp_df_columns + for species in self._re_species_list: + self._exp_df['{0}_org_eq'.format(species)] = \ + self._exp_df['{0}_aq_eq'.format(species)] \ + * self._exp_df['{0}_d_eq'.format(species)] + + self._in_moles = None + + self._aq_ind = None + self._org_ind = None + self._re_charges = None + + self.set_in_moles(feed_vol=1) + self._predicted_dict = None + self.update_predicted_dict() + +
[docs] @staticmethod + def scipy_minimize(objective, x_guess, optimizer_kwargs=None): + """ The default optimizer for REEPS + + Uses scipy.minimize + + By default, options are + + .. code-block:: python + + default_kwargs= {"method": 'SLSQP', + "bounds": [(1e-1, 1e1)]*len(x_guess), + "constraints": (), + "options": {'disp': True, + 'maxiter': 1000, + 'ftol': 1e-6}} + + :param objective: (func) the objective function + :param x_guess: (np.ndarray) the initial guess (always 1) + :param optimizer_kwargs: (dict) dictionary of options for minimize + :returns: ((np.ndarray, float)) Optimized parameters, + objective_function value + """ + if optimizer_kwargs is None: + optimizer_kwargs = {"method": 'SLSQP', + "bounds": [(1e-1, 1e1)] * len(x_guess), + "constraints": (), + "options": {'disp': True, + 'maxiter': 1000, + 'ftol': 1e-6}} + res = minimize(objective, x_guess, **optimizer_kwargs) + est_parameters = res.x + return est_parameters, res.fun
+ +
[docs] def log_mean_squared_error(self, predicted_dict, meas_df): + """Default objective function for REEPS + + Returns the log mean squared error of + predicted distribution ratios (d=n_org/n_aq) + to measured d. + + np.sum((np.log10(d_pred)-np.log10(d_meas))\**2) + + :param predicted_dict: (dict) contains predicted data + :param meas_df: (pd.DataFrame) contains experimental data + :return: (float) log mean squared error between predicted and measured + """ + meas = np.concatenate([meas_df['{0}_d_eq'.format(species)].values + for species in self._re_species_list]) + pred = np.concatenate([ + predicted_dict['{0}_d_eq'.format(species)] + for species in self._re_species_list]) + log_pred = np.log10(pred) + log_meas = np.log10(meas) + log_diff = (log_pred - log_meas) ** 2 + obj = np.sum(log_diff) + return obj
+ +
[docs] def get_exp_df(self) -> pd.DataFrame: + """Returns the experimental DataFrame + + :return: (pd.DataFrame) Experimental data + """ + return self._exp_df
+ +
[docs] def set_exp_df(self, exp_data): + """Changes the experimental DataFrame to input exp_csv_filename data + and renames columns to internal REEPS names + + + h_i, h_eq, z_i, z_eq, {RE}_aq_i, {RE}_aq_eq, {RE}_d + + See class docstring on "exp_csv_filename" for further explanations. + + :param exp_data: (str or pd.DataFrame) + file name/path or DataFrame for experimental data csv + """ + self._exp_data = exp_data + if isinstance(self._exp_data, str): + try: + self._exp_df = pd.read_csv(self._exp_data) + except FileNotFoundError: + self._exp_data = pkg_resources.resource_filename( + 'reeps', r'..\data\csvs\{0}'.format(self._exp_data)) + self._exp_df = pd.read_csv(self._exp_data) + else: + self._exp_df = exp_data.copy() + self._exp_df_columns = ['h_i', 'h_eq', 'z_i', 'z_eq'] + if self._re_species_list is None: + self._re_species_list = [] + for name in self._rare_earth_ion_names: + species = name.replace('+', '') + self._re_species_list.append(species) + for species in self._re_species_list: + self._exp_df_columns.append('{0}_aq_i'.format(species)) + self._exp_df_columns.append('{0}_aq_eq'.format(species)) + self._exp_df_columns.append('{0}_d_eq'.format(species)) + self._exp_df.columns = self._exp_df_columns + for species in self._re_species_list: + self._exp_df['{0}_org_eq'.format(species)] = \ + self._exp_df['{0}_aq_eq'.format(species)] \ + * self._exp_df['{0}_d_eq'.format(species)] + self.set_in_moles(feed_vol=1) + self.update_predicted_dict() + return None
+ +
[docs] def get_phases(self) -> list: + """ + Returns the list of Cantera solutions + + :return: (list) list of Cantera solutions/phases + """ + return self._phases
+ +
[docs] def set_phases(self, phases_xml_filename, phase_names): + """Change list of Cantera solutions by inputting + new xml file name and phase names + + Also runs set_in_moles to set feed volume to 1 L + + :param phases_xml_filename: (str) xml file with parameters + for equilibrium calc + :param phase_names: (list) names of phases in xml file + """ + self._phases_xml_filename = phases_xml_filename + self._phase_names = phase_names + # Try and except for adding package data to path. + # This only works for sdist, not bdist + # If bdist is needed, research "manifest.in" python setup files + try: + shutil.copyfile(self._phases_xml_filename, + self._temp_xml_file_path) + self._phases = ct.import_phases(self._phases_xml_filename, + phase_names) + except FileNotFoundError: + self._phases_xml_filename = \ + pkg_resources.resource_filename('reeps', + r'..\data\xmls\{0}'.format( + phases_xml_filename)) + shutil.copyfile(self._phases_xml_filename, + self._temp_xml_file_path) + self._phases = ct.import_phases(self._phases_xml_filename, + phase_names) + self.set_in_moles(feed_vol=1) + self.update_predicted_dict() + return None
+ +
[docs] def get_opt_dict(self) -> dict: + """ + Returns the dictionary containing optimization information + + :return: (dict) dictionary containing info about which + species parameters are updated to fit model to experimental data + """ + return self._opt_dict
+ +
[docs] def set_opt_dict(self, opt_dict): + """ + Change the dictionary to input opt_dict. + + opt_dict specifies species parameters to be updated to + fit model to data + + See class docstring on "opt_dict" for more information. + + :param opt_dict: (dict) dictionary containing info about which + species parameters are updated to fit model to experimental data + """ + + self._opt_dict = opt_dict + return None
+ +
[docs] def get_aq_solvent_name(self) -> str: + """Returns aq_solvent_name + + :return: aq_solvent_name: (str) name of aqueous solvent in xml file + """ + return self._aq_solvent_name
+ +
[docs] def set_aq_solvent_name(self, aq_solvent_name): + """ Change aq_solvent_name to input aq_solvent_name + + :param aq_solvent_name: (str) name of aqueous solvent in xml file + """ + self._aq_solvent_name = aq_solvent_name + return None
+ +
[docs] def get_extractant_name(self) -> str: + """Returns extractant name + + :return: extractant_name: (str) name of extractant in xml file + """ + return self._extractant_name
+ +
[docs] def set_extractant_name(self, extractant_name): + """ + Change extractant_name to input extractant_name + :param extractant_name: (str) name of extractant in xml file + """ + self._extractant_name = extractant_name + return None
+ +
[docs] def get_diluant_name(self) -> str: + """ Returns diluant name + :return: diluant_name: (str) name of diluant in xml file + """ + return self._diluant_name
+ +
[docs] def set_diluant_name(self, diluant_name): + """ + Change diluant_name to input diluant_name + + :param diluant_name: (str) name of diluant in xml file + """ + self._diluant_name = diluant_name + return None
+ +
[docs] def get_complex_names(self) -> list: + """Returns list of complex names + + :return: complex_names: (list) names of complexes in xml file. + """ + return self._complex_names
+ +
[docs] def set_complex_names(self, complex_names): + """Change complex names list to input complex_names + + :param complex_names: (list) names of complexes in xml file. + """ + self._complex_names = complex_names + return None
+ +
[docs] def get_rare_earth_ion_names(self) -> list: + """Returns list of rare earth ion names + + :return: rare_earth_ion_names: (list) names of rare earth ions in + xml file + """ + return self._rare_earth_ion_names
+ +
[docs] def set_rare_earth_ion_names(self, rare_earth_ion_names): + """Change list of rare earth ion names to input + rare_earth_ion_names + + :param rare_earth_ion_names: (list) names of rare earth ions in + xml file + """ + self._rare_earth_ion_names = rare_earth_ion_names + return None
+ +
[docs] def get_re_species_list(self) -> list: + """Returns list of rare earth element names + + :return: re_species_list: (list) names of rare earth elements in + xml file + """ + return self._re_species_list
+ +
[docs] def set_re_species_list(self, re_species_list): + """Change list of rare earth ion names to input + rare_earth_ion_names + + :param re_species_list: (list) names of rare earth elements in + xml file + """ + self._re_species_list = re_species_list + return None
+ +
[docs] def get_aq_solvent_rho(self) -> str: + """Returns aqueous solvent density (g/L) + + :return: aq_solvent_rho: (float) density of aqueous solvent + """ + return self._aq_solvent_rho
+ +
[docs] def set_aq_solvent_rho(self, aq_solvent_rho): + """Changes aqueous solvent density (g/L) to input aq_solvent_rho + + :param aq_solvent_rho: (float) density of aqueous solvent + """ + self._aq_solvent_rho = aq_solvent_rho + return None
+ +
[docs] def get_extractant_rho(self) -> str: + """Returns extractant density (g/L) + + :return: extractant_rho: (float) density of extractant + """ + return self._extractant_rho
+ +
[docs] def set_extractant_rho(self, extractant_rho): + """Changes extractant density (g/L) to input extractant_rho + + :param extractant_rho: (float) density of extractant + """ + self._extractant_rho = extractant_rho + return None
+ +
[docs] def get_diluant_rho(self) -> str: + """Returns diluant density (g/L) + + :return: diluant_rho: (float) density of diluant + """ + return self._diluant_rho
+ +
[docs] def set_diluant_rho(self, diluant_rho): + """Changes diluant density (g/L) to input diluant_rho + + :param diluant_rho: (float) density of diluant + """ + self._diluant_rho = diluant_rho + return None
+ +
[docs] def set_in_moles(self, feed_vol): + """Function that initializes mole fractions to input feed_vol + + This function is called at initialization + + Sets in_moles to a pd.DataFrame containing initial mole fractions + + Columns for species and rows for different experiments + + This function also calls update_predicted_dict + + :param feed_vol: (float) feed volume of mixture (L) + """ + phases_copy = self._phases.copy() + exp_df = self._exp_df.copy() + solvent_name = self._aq_solvent_name + extractant_name = self._extractant_name + diluant_name = self._diluant_name + solvent_rho = self._aq_solvent_rho + extractant_rho = self._extractant_rho + diluant_rho = self._diluant_rho + re_names = self._rare_earth_ion_names + re_species_list = self._re_species_list + + mixed = ct.Mixture(phases_copy) + aq_ind = None + solvent_ind = None + for ind, phase in enumerate(phases_copy): + if solvent_name in phase.species_names: + aq_ind = ind + solvent_ind = phase.species_names.index(solvent_name) + if aq_ind is None: + raise Exception('Solvent "{0}" not found \ + in xml file'.format(solvent_name)) + + if aq_ind == 0: + org_ind = 1 + else: + org_ind = 0 + self._aq_ind = aq_ind + self._org_ind = org_ind + extractant_ind = phases_copy[org_ind].species_names.index( + extractant_name) + diluant_ind = phases_copy[org_ind].species_names.index(diluant_name) + + re_ind_list = [phases_copy[aq_ind].species_names.index(re_name) + for re_name in re_names] + re_charges = np.array([phases_copy[aq_ind].species(re_ind).charge + for re_ind in re_ind_list]) + self._re_charges = re_charges + + mix_aq = mixed.phase(aq_ind) + mix_org = mixed.phase(org_ind) + solvent_mw = mix_aq.molecular_weights[solvent_ind] # g/mol + extractant_mw = mix_org.molecular_weights[extractant_ind] + diluant_mw = mix_org.molecular_weights[diluant_ind] + if solvent_rho is None: + solvent_rho = mix_aq(aq_ind).partial_molar_volumes[ + solvent_ind] / solvent_mw * 1e6 # g/L + self._aq_solvent_rho = solvent_rho + if extractant_rho is None: + extractant_rho = mix_org(org_ind).partial_molar_volumes[ + extractant_ind] / extractant_mw * 1e6 + self._extractant_rho = extractant_rho + if diluant_rho is None: + diluant_rho = mix_org(org_ind).partial_molar_volumes[ + extractant_ind] / extractant_mw * 1e6 + self._diluant_rho = diluant_rho + + in_moles_data = [] + aq_phase_solvent_moles = feed_vol * solvent_rho / solvent_mw + for index, row in exp_df.iterrows(): + h_plus_moles = feed_vol * row['h_i'] + hydroxide_ions = 0 + rare_earth_moles = np.array([feed_vol * row[ + '{0}_aq_i'.format(re_species)] + for re_species in re_species_list]) + re_charge_sum = np.sum(re_charges * rare_earth_moles) + chlorine_moles = re_charge_sum + h_plus_moles + extractant_moles = feed_vol * row['z_i'] + extractant_vol = extractant_moles * extractant_mw / extractant_rho + diluant_vol = feed_vol - extractant_vol + diluant_moles = diluant_vol * diluant_rho / diluant_mw + complex_moles = np.zeros(len(re_species_list)) + + species_moles_aq = [aq_phase_solvent_moles, + h_plus_moles, + hydroxide_ions, + chlorine_moles] + species_moles_aq.extend(list(rare_earth_moles)) + species_moles_org = [extractant_moles, diluant_moles] + species_moles_org.extend(list(complex_moles)) + if aq_ind == 0: + species_moles = species_moles_aq + species_moles_org + else: + species_moles = species_moles_org + species_moles_aq + in_moles_data.append(species_moles) + self._in_moles = pd.DataFrame( + in_moles_data, columns=mixed.species_names) + self.update_predicted_dict() + return None
+ +
[docs] def get_in_moles(self) -> pd.DataFrame: + """Returns the in_moles DataFrame which contains the initial mole + fractions of each species for each experiment + + :return: in_moles: (pd.DataFrame) DataFrame with initial mole fractions + """ + return self._in_moles
+ +
[docs] def set_objective_function(self, objective_function): + """Change objective function to input objective_function. + + See class docstring on "objective_function" for instructions + + :param objective_function: (func) Objective function to quantify + error between model and experimental data + """ + if not callable(objective_function) \ + and objective_function not in self._built_in_obj_list: + raise Exception( + "objective_function must be a function " + "or in this strings list: {0}".format( + self._built_in_obj_list)) + if callable(objective_function): + if len(signature(objective_function).parameters) < 2: + raise Exception( + "objective_function must be a function " + "with at least 3 arguments:" + " f(predicted_dict, experimental_df, kwargs)") + if objective_function == 'Log-MSE': + objective_function = self.log_mean_squared_error + self._objective_function = objective_function + return None
+ +
[docs] def get_objective_function(self): + """Returns objective function + + :return: objective_function: (func) Objective function to quantify + error between model and experimental data + """ + return self._objective_function
+ +
[docs] def set_optimizer(self, optimizer): + """Change optimizer function to input optimizer. + + See class docstring on "optimizer" for instructions + + :param optimizer: (func) Optimizer function to minimize objective + function + """ + if not callable(optimizer) \ + and optimizer not in self._built_in_opt_list: + raise Exception( + "optimizer must be a function " + "or in this strings list: {0}".format( + self._built_in_opt_list)) + if callable(optimizer): + if len(signature(optimizer).parameters) < 2: + raise Exception( + "optimizer must be a function " + "with at least 2 arguments: " + "f(objective_func,x_guess, kwargs)") + if optimizer == 'SLSQP': + optimizer = self.scipy_minimize + self._optimizer = optimizer + return None
+ +
[docs] def get_optimizer(self): + """Returns objective function + + :return: optimizer: (func) Optimizer function to minimize objective + function + """ + return self._optimizer
+ +
[docs] def get_temp_xml_file_path(self): + """Returns path to temporary xml file. + + This xml file is a duplicate of the phases_xml_file name and is + modified during the optimization process to avoid changing the original + xml file. + + :return: temp_xml_file_path: (str) path to temporary xml file. + """ + return self._temp_xml_file_path
+ +
[docs] def set_temp_xml_file_path(self, temp_xml_file_path): + """Changes temporary xml file path to input temp_xml_file_path. + + This xml file is a duplicate of the phases_xml_file name and is + modified during the optimization process to avoid changing the original + xml file. + + :param temp_xml_file_path: (str) path to temporary xml file. + """ + self._temp_xml_file_path = temp_xml_file_path + return None
+ +
[docs] def get_dependant_params_dict(self): + """ + Returns the dependant_params_dict + :return: dependant_params_dict: (dict) dictionary containing + information about parameters dependant on opt_dict + """ + return self._dependant_params_dict
+ +
[docs] def set_dependant_params_dict(self, dependant_params_dict): + """ + Sets the dependant_params_dict + :param dependant_params_dict: (dict) dictionary containing information + about parameters dependant on opt_dict + """ + self._dependant_params_dict = dependant_params_dict + return None
+ +
[docs] def update_predicted_dict(self, + phases_xml_filename=None, + phase_names=None): + """Function that computes the predicted equilibrium concentrations + the fed phases_xml_filename parameters predicts given the initial + mole fractions set by in_moles() + + :param phases_xml_filename: (str)xml file with parameters + for equilibrium calc. If ``None``, the + current phases_xml_filename is used. + :param phase_names: (list) names of phases in xml file. + If ``None``, the current phases_names is used. + """ + if phases_xml_filename is None: + phases_xml_filename = self._phases_xml_filename + if phase_names is None: + phase_names = self._phase_names + aq_ind = self._aq_ind + org_ind = self._org_ind + complex_names = self._complex_names + extractant_name = self._extractant_name + rare_earth_ion_names = self._rare_earth_ion_names + in_moles = self._in_moles + re_species_list = self._re_species_list + + phases_copy = ct.import_phases(phases_xml_filename, phase_names) + mix = ct.Mixture(phases_copy) + key_names = ['h_eq', 'z_eq'] + for re_species in re_species_list: + key_names.append('{0}_aq_eq'.format(re_species)) + key_names.append('{0}_org_eq'.format(re_species)) + key_names.append('{0}_d_eq'.format(re_species)) + + predicted_dict = {'{0}'.format(key_name): [] + for key_name in key_names} + + for row in in_moles.values: + mix.species_moles = row + mix.equilibrate('TP', log_level=0) + re_org_array = np.array([mix.species_moles[mix.species_index( + org_ind, complex_name)] for complex_name in complex_names]) + re_aq_array = np.array([mix.species_moles[mix.species_index( + aq_ind, re_ion_name)] for re_ion_name in rare_earth_ion_names]) + d_array = re_org_array / re_aq_array + hydrogen_ions = mix.species_moles[mix.species_index(aq_ind, 'H+')] + extractant = mix.species_moles[mix.species_index( + org_ind, extractant_name)] + for index, re_species in enumerate(re_species_list): + predicted_dict['{0}_aq_eq'.format( + re_species)].append(re_aq_array[index]) + predicted_dict['{0}_org_eq'.format( + re_species)].append(re_org_array[index]) + predicted_dict['{0}_d_eq'.format( + re_species)].append(d_array[index]) + predicted_dict['h_eq'].append(hydrogen_ions) + predicted_dict['z_eq'].append(extractant) + for key, value in predicted_dict.items(): + predicted_dict[key] = np.array(value) + self._predicted_dict = predicted_dict + return None
+ +
[docs] def get_predicted_dict(self): + """Returns predicted dictionary of species concentrations + that xml parameters predicts given current in_moles + + :return: predicted_dict: (dict) dictionary of species concentrations + """ + return self._predicted_dict
+ + def _internal_objective(self, x, kwargs=None): + """ + Internal objective function. Uses objective function to compute value + If the optimizer requires vectorized variables ie pso, this function + takes care of it + + :param x: (list) thermo properties varied to minimize objective func + :param kwargs: (list) arguments for objective_function + """ + temp_xml_file_path = self._temp_xml_file_path + exp_df = self._exp_df + objective_function = self._objective_function + opt_dict = copy.deepcopy(self._opt_dict) + dep_dict = copy.deepcopy(self._dependant_params_dict) + x = np.array(x) + + if len(x.shape) == 1: + xs = np.array([x]) + vectorized_x = False + else: + vectorized_x = True + xs = x + objective_values = [] + for x in xs: + i = 0 + for species_name in opt_dict.keys(): + for thermo_prop in opt_dict[species_name].keys(): + if not np.isnan( + x[i]): # if nan, do not update xml with nan + opt_dict[species_name][thermo_prop] *= x[i] + i += 1 + + self.update_xml(opt_dict, + temp_xml_file_path, + dependant_params_dict=dep_dict) + + self.update_predicted_dict(temp_xml_file_path) + predicted_dict = self.get_predicted_dict() + self.update_predicted_dict() + + if kwargs is None: + # noinspection PyCallingNonCallable + obj = objective_function(predicted_dict, exp_df) + else: + # noinspection PyCallingNonCallable + obj = objective_function(predicted_dict, exp_df, **kwargs) + objective_values.append(obj) + if vectorized_x: + objective_values = np.array(objective_values) + else: + objective_values = objective_values[0] + return objective_values + +
[docs] def fit(self, + objective_function=None, + optimizer=None, + objective_kwargs=None, + optimizer_kwargs=None) -> tuple: + """Fits experimental to modeled data by minimizing objective function + with optimizer. Returns dictionary with opt_dict structure + + :param objective_function: (function) function to compute objective + If 'None', last set objective or default function is used + :param optimizer: (function) function to perform optimization + If 'None', last set optimizer or default is used + :param optimizer_kwargs: (dict) optional arguments for optimizer + :param objective_kwargs: (dict) optional arguments + for objective function + :returns tuple: (opt_dict (dict), opt_value (float)) + optimized opt_dict: Has identical structure as opt_dict + """ + if objective_function is not None: + self.set_objective_function(objective_function) + if optimizer is not None: + self.set_optimizer(optimizer) + + def objective(x): + return self._internal_objective(x, objective_kwargs) + + optimizer = self._optimizer + opt_dict = copy.deepcopy(self._opt_dict) + i = 0 + for species_name in opt_dict.keys(): + for _ in opt_dict[species_name].keys(): + i += 1 + x_guess = np.ones(i) + + if optimizer_kwargs is None: + # noinspection PyCallingNonCallable + est_parameters, obj_value = optimizer(objective, x_guess) + else: + # noinspection PyCallingNonCallable + est_parameters, obj_value = optimizer(objective, + x_guess, + optimizer_kwargs) + + i = 0 + for species_name in opt_dict.keys(): + for thermo_prop in opt_dict[species_name].keys(): + opt_dict[species_name][thermo_prop] *= est_parameters[i] + i += 1 + return opt_dict, obj_value
+ +
[docs] def update_xml(self, + info_dict, + phases_xml_filename=None, + dependant_params_dict=None): + """updates xml file with info_dict + + :param info_dict: (dict) info in {species_names:{thermo_prop:val}} + Requires an identical structure to opt_dict + :param phases_xml_filename: (str) xml filename if editing other xml + If ``None``, the current xml will be modified and the internal + Cantera phases will be refreshed to the new values. + :param dependant_params_dict: (dict) dictionary containing information + about parameters dependant on info_dict + """ + if phases_xml_filename is None: + phases_xml_filename = self._phases_xml_filename + new_dict = copy.deepcopy(info_dict) + dep_dict = dependant_params_dict + if dep_dict is not None: + for species_name in dep_dict.keys(): + for thermo_prop in dep_dict[species_name]: + mod_func = \ + dep_dict[species_name][thermo_prop]['function'] + mod_kwargs = \ + dep_dict[species_name][thermo_prop]['kwargs'] + ind_vars = \ + dep_dict[species_name][thermo_prop]['ind_vars'] + ind_vals = [new_dict[ind_var[0]][ind_var[1]] + for ind_var in ind_vars] + + new_dict[species_name] = {} + new_dict[species_name][thermo_prop] = {} + new_dict[species_name][thermo_prop] = \ + mod_func(ind_vals, **mod_kwargs) + # print(mod_func(ind_vals, **mod_kwargs)) + # print(new_dict) + + tree = ET.parse(phases_xml_filename) + root = tree.getroot() + # Update xml file + for species_name in new_dict.keys(): + for thermo_prop in new_dict[species_name].keys(): + for species in root.iter('species'): + if species.attrib['name'] == species_name: + for changed_prop in species.iter(thermo_prop): + changed_prop.text = str( + new_dict[species_name][thermo_prop]) + now = datetime.now() + changed_prop.set('updated', + 'Updated at {0}:{1} {2}-{3}-{4}' + .format(now.hour, now.minute, + now.month, now.day, + now.year)) + + tree.write(phases_xml_filename) + if phases_xml_filename == self._phases_xml_filename: + self.set_phases(self._phases_xml_filename, self._phase_names) + return None
+ + def _internal_objective_ver2(self, x, kwargs=None): + """ + ver2 generalizes to handle accessing parameters. ver1 assumes species + parameter is modified. ver2 assumes parameter is accessed by going + through two levels: upper and lower + Internal objective function. Uses objective function to compute value + If the optimizer requires vectorized variables ie pso, this function + takes care of it + + :param x: (list) thermo properties varied to minimize objective func + :param kwargs: (list) arguments for objective_function + """ + temp_xml_file_path = self._temp_xml_file_path + exp_df = self._exp_df + objective_function = self._objective_function + opt_dict = copy.deepcopy(self._opt_dict) + dep_dict = copy.deepcopy(self._dependant_params_dict) + x = np.array(x) + + if len(x.shape) == 1: + xs = np.array([x]) + vectorized_x = False + else: + vectorized_x = True + xs = x + objective_values = [] + for x in xs: + for ind, param_name in enumerate(opt_dict.keys()): + if not np.isnan( + x[ind]): # if nan, do not update xml with nan + opt_dict[param_name]['input_value'] *= x[ind] + + self.update_xml_ver2(opt_dict, + temp_xml_file_path, + dependant_params_dict=dep_dict) + + self.update_predicted_dict(temp_xml_file_path) + predicted_dict = self.get_predicted_dict() + self.update_predicted_dict() + + if kwargs is None: + # noinspection PyCallingNonCallable + obj = objective_function(predicted_dict, exp_df) + else: + # noinspection PyCallingNonCallable + obj = objective_function(predicted_dict, exp_df, **kwargs) + objective_values.append(obj) + if vectorized_x: + objective_values = np.array(objective_values) + else: + objective_values = objective_values[0] + return objective_values + +
[docs] def fit_ver2(self, + objective_function=None, + optimizer=None, + objective_kwargs=None, + optimizer_kwargs=None) -> tuple: + """Fits experimental to modeled data by minimizing objective function + with optimizer. Returns dictionary with opt_dict structure + + :param objective_function: (function) function to compute objective + If 'None', last set objective or default function is used + :param optimizer: (function) function to perform optimization + If 'None', last set optimizer or default is used + :param optimizer_kwargs: (dict) optional arguments for optimizer + :param objective_kwargs: (dict) optional arguments + for objective function + :returns tuple: (opt_dict (dict), opt_value (float)) + optimized opt_dict: Has identical structure as opt_dict + """ + if objective_function is not None: + self.set_objective_function(objective_function) + if optimizer is not None: + self.set_optimizer(optimizer) + + def objective(x): + return self._internal_objective_ver2(x, objective_kwargs) + + optimizer = self._optimizer + opt_dict = copy.deepcopy(self._opt_dict) + x_guess = np.ones(len(list(opt_dict.keys()))) + + if optimizer_kwargs is None: + # noinspection PyCallingNonCallable + est_parameters, obj_value = optimizer(objective, x_guess) + else: + # noinspection PyCallingNonCallable + est_parameters, obj_value = optimizer(objective, + x_guess, + optimizer_kwargs) + for ind, param_name in enumerate(opt_dict.keys()): + opt_dict[param_name]['input_value'] *= est_parameters[ind] + + return opt_dict, obj_value
+ +
[docs] def update_xml_ver2(self, + info_dict, + phases_xml_filename=None, + dependant_params_dict=None): + """updates xml file with info_dict + + :param info_dict: (dict) info in {species_names:{thermo_prop:val}} + Requires an identical structure to opt_dict + :param phases_xml_filename: (str) xml filename if editing other xml + If ``None``, the current xml will be modified and the internal + Cantera phases will be refreshed to the new values. + :param dependant_params_dict: (dict) dictionary containing information + about parameters dependant on info_dict + """ + if phases_xml_filename is None: + phases_xml_filename = self._phases_xml_filename + new_dict = copy.deepcopy(info_dict) + dep_dict = dependant_params_dict + + if dep_dict is not None: + new_dict.update(dep_dict) + for param_name in dep_dict.keys(): + mod_func = \ + dep_dict[param_name]['function'] + mod_kwargs = \ + dep_dict[param_name]['kwargs'] + if isinstance(dep_dict[param_name]['independent_params'], str): + ind_param_names = [dep_dict[ + param_name]['independent_params']] + else: + ind_param_names = \ + dep_dict[param_name]['independent_params'] + ind_vals = [new_dict[ind_param_name]['input_value'] + for ind_param_name in ind_param_names] + if mod_kwargs is None: + new_dict[param_name]['input_value'] = mod_func(ind_vals) + else: + new_dict[param_name]['input_value'] = \ + mod_func(ind_vals, + **mod_kwargs) + tree = ET.parse(phases_xml_filename) + root = tree.getroot() + # Update xml file + for key in list(new_dict.keys()): + d = new_dict[key] + now = datetime.now() + if (d['upper_attrib_name'] is not None + and d['lower_attrib_name'] is not None): + for child1 in root.iter(d['upper_element_name']): + if (child1.attrib[d['upper_attrib_name']] + == d['upper_attrib_value']): + for child2 in child1.iter(d['lower_element_name']): + if (child1.attrib[d['lower_attrib_name']] + == d['lower_attrib_value']): + child2.text = d['input_format'].format( + d['input_value']) + child2.set('updated', + 'Updated at {0}:{1} {2}-{3}-{4}' + .format(now.hour, now.minute, + now.month, now.day, + now.year)) + elif (d['upper_attrib_name'] is None + and d['lower_attrib_name'] is not None): + for child1 in root.iter(d['upper_element_name']): + for child2 in child1.iter(d['lower_element_name']): + if (child1.attrib[d['lower_attrib_name']] + == d['lower_attrib_value']): + child2.text = d['input_format'].format( + d['input_value']) + child2.set('updated', + 'Updated at {0}:{1} {2}-{3}-{4}' + .format(now.hour, now.minute, + now.month, now.day, + now.year)) + elif (d['upper_attrib_name'] is not None + and d['lower_attrib_name'] is None): + for child1 in root.iter(d['upper_element_name']): + if (child1.attrib[d['upper_attrib_name']] + == d['upper_attrib_value']): + for child2 in child1.iter(d['lower_element_name']): + child2.text = d['input_format'].format( + d['input_value']) + child2.set('updated', + 'Updated at {0}:{1} {2}-{3}-{4}' + .format(now.hour, now.minute, + now.month, now.day, + now.year)) + else: + for child1 in root.iter(d['upper_element_name']): + for child2 in child1.iter(d['lower_element_name']): + child2.text = d['input_format'].format( + d['input_value']) + child2.set('updated', 'Updated at {0}:{1} {2}-{3}-{4}' + .format(now.hour, now.minute, + now.month, now.day, + now.year)) + + tree.write(phases_xml_filename) + if phases_xml_filename == self._phases_xml_filename: + self.set_phases(self._phases_xml_filename, self._phase_names) + return None
+ +
[docs] def parity_plot(self, + compared_value=None, + c_data=None, + c_label=None, + plot_title=None, + save_path=None, + print_r_squared=False, + data_labels=None, + legend=True): + """ + Parity plot between measured and predicted compared_value. + Default compared value is {RE_1}_aq_eq + + :param compared_value: (str) Quantity to compare predicted and + experimental data. Can be any column containing "eq" in exp_df i.e. + h_eq, z_eq, {RE}_d_eq, etc. + :param plot_title: (str or boolean) + + If None (default): Plot title will be generated from compared_value + Recommend to just explore. If h_eq, plot_title is + "H^+ eq conc". + + If str: Plot title will be plot_title string + + If "False": No plot title + :param c_data: (list or np.ndarray) data for color axis + :param c_label: (str) label for color axis + :param save_path: (str) save path for parity plot + :param print_r_squared: (boolean) To plot or not to plot r-squared + value. Prints 2 places past decimal + :param data_labels: labels for the data such as paper's name where + experiment is pulled from. + :param legend: whether to display legend for data_labels. Has no + effect if data_labels is None + :return fig, ax: returns the figure and axes objects + """ + exp_df = self.get_exp_df() + predicted_dict = self.get_predicted_dict() + re_species_list = self._re_species_list + extractant_name = self.get_extractant_name() + re_charges = self._re_charges + if compared_value is None: + compared_value = '{0}_aq_eq'.format(re_species_list[0]) + pred = pd.DataFrame(predicted_dict)[compared_value].fillna(0).values + meas = exp_df[compared_value].fillna(0).values + name_breakdown = re.findall('[^_\W]+', compared_value) + compared_species = name_breakdown[0] + if compared_species == 'h': + feed_molarity = exp_df['h_i'].fillna(0).values + elif compared_species == 'z': + feed_molarity = exp_df['z_i'].fillna(0).values + else: + feed_molarity = exp_df[ + '{0}_aq_i'.format(compared_species)].fillna(0).values + if isinstance(data_labels, list): + combined_df = pd.DataFrame({'pred': pred, + 'meas': meas, + 'label': data_labels, + 'feed_molarity': feed_molarity}) + elif isinstance(c_data, str): + combined_df = pd.DataFrame({'pred': pred, + 'meas': meas, + c_data: exp_df[c_data].values, + 'feed_molarity': feed_molarity}) + else: + combined_df = pd.DataFrame({'pred': pred, + 'meas': meas, + 'feed_molarity': feed_molarity}) + + combined_df = combined_df[(combined_df['feed_molarity'] != 0)] + meas = combined_df['meas'].values + pred = combined_df['pred'].values + + min_data = np.min([pred, meas]) + max_data = np.max([pred, meas]) + min_max_data = np.array([min_data, max_data]) + + if compared_species == 'h': + default_title = '$H^+$ eq. conc. (mol/L)' + elif compared_species == 'z': + default_title = '{0} eq. conc. (mol/L)'.format(extractant_name) + else: + phase = name_breakdown[1] + if phase == 'aq': + re_charge = re_charges[re_species_list.index(compared_species)] + default_title = '$%s^{%d+}$ eq. conc. (mol/L)' \ + % (compared_species, re_charge) + elif phase == 'd': + default_title = '{0} distribution ratio'.format( + compared_species) + else: + default_title = '{0} complex eq. conc. (mol/L)'.format( + compared_species) + fig, ax = plt.subplots() + if isinstance(data_labels, list): + unique_labels = list(set(data_labels)) + for label in unique_labels: + filtered_data = combined_df[combined_df['label'] == label] + filtered_meas = filtered_data['meas'] + filtered_pred = filtered_data['pred'] + ax.scatter(filtered_meas, filtered_pred, label=label) + if legend: + ax.legend(loc='best') + + elif c_data is not None: + if isinstance(c_data, str): + c_data = combined_df[c_data].values + p1 = ax.scatter(meas, pred, c=c_data, alpha=1, cmap='viridis') + c_bar = fig.colorbar(p1, format='%.2f') + if c_label is not None: + c_bar.set_label(c_label, rotation=270, labelpad=20) + else: + sns.scatterplot(meas, pred, color="r", + legend=False) + ax.plot(min_max_data, min_max_data, color="b", label="") + + if print_r_squared: + ax.text(min_max_data[0], + min_max_data[1] * 0.9, + '$R^2$={0:.2f}'.format(self.r_squared(compared_value))) + # plt.legend(loc='lower right') + # else: + # plt.legend() + + ax.set(xlabel='Measured', ylabel='Predicted') + if plot_title is None: + ax.set_title(default_title) + elif isinstance(plot_title, str): + ax.set_title(plot_title) + set_size(8, 6) + plt.tight_layout() + plt.show() + if save_path is not None: + plt.savefig(save_path, bbox_inches='tight') + return fig, ax
+ +
[docs] def r_squared(self, compared_value=None): + """r-squared value comparing measured and predicted compared value + + Closer to 1, the better the model's predictions. + + :param compared_value: (str) Quantity to compare predicted and + experimental data. Can be any column containing "eq" in exp_df i.e. + h_eq, z_eq, {RE}_d_eq, etc. default is {RE}_aq_eq + """ + exp_df = self.get_exp_df() + predicted_dict = self.get_predicted_dict() + re_species_list = self._re_species_list + if compared_value is None: + compared_value = '{0}_aq_eq'.format(re_species_list[0]) + pred = pd.DataFrame(predicted_dict)[compared_value].fillna(0).values + predicted_y = np.array(pred) + actual_y = exp_df[compared_value].fillna(0).values + name_breakdown = re.findall('[^_\W]+', compared_value) + compared_species = name_breakdown[0] + if compared_species == 'h': + feed_molarity = exp_df['h_i'].fillna(0).values + elif compared_species == 'z': + feed_molarity = exp_df['z_i'].fillna(0).values + else: + feed_molarity = exp_df[ + '{0}_aq_i'.format(compared_species)].fillna(0).values + combined_df = pd.DataFrame({'pred': predicted_y, + 'meas': actual_y, + 'in_moles': feed_molarity}) + combined_df = combined_df[(combined_df['in_moles'] != 0)] + actual_y = combined_df['meas'].values + predicted_y = combined_df['pred'].values + num = sum((actual_y - predicted_y) ** 2) + den = sum((actual_y - np.mean(actual_y)) ** 2) + if den == 0: + r_2 = 0 + else: + r_2 = (1 - num / den) + return r_2
+ +
[docs] @staticmethod + def plot_3d_data(x_data, + y_data, + z_data, + c_data=None, + x_label=None, + y_label=None, + z_label=None, + c_label=None): + """ + + :param x_data: (list) list of data for x axis + :param y_data: (list) list of data for y axis + :param z_data: (list) list of data for z axis + :param c_data: (list) list of data for color axis + :param x_label: (str) label for x axis + :param y_label: (str) label for y axis + :param z_label: (str) label for z axis + :param c_label: (str) label for color axis + :return: + """ + + fig = plt.figure() + ax = fig.add_subplot(111, projection='3d') + if c_data is None: + ax.plot(x_data, y_data, z_data, 'o') + else: + p1 = ax.scatter(x_data, + y_data, + z_data, 'o', c=c_data, + cmap='viridis', alpha=1) + c_bar = fig.colorbar(p1) + if c_label is not None: + c_bar.set_label(c_label, rotation=270, labelpad=20) + if x_label is None: + ax.set_xlabel('x', labelpad=15) + else: + ax.set_xlabel(x_label, labelpad=15) + if y_label is None: + ax.set_ylabel('y', labelpad=15) + else: + ax.set_ylabel(y_label, labelpad=15) + if z_label is None: + ax.set_zlabel('z', labelpad=15) + else: + ax.set_zlabel(z_label, labelpad=15) + plt.show() + return fig, ax
+
+ +
+ +
+
+ + +
+ +
+

+ © Copyright 2020, Titus Quah, Nwike Iloeje + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_sources/guide/about.rst.txt b/docs/_build/html/_sources/guide/about.rst.txt deleted file mode 100644 index dbd1116..0000000 --- a/docs/_build/html/_sources/guide/about.rst.txt +++ /dev/null @@ -1,61 +0,0 @@ -.. _about: - -************ -About -************ - -Authors -============= -Titus Quah, University of Utah, - -Nwike Iloeje, Argonne National Laboratory, - -Acknowledgements -================ -Based upon work supported by funding from Argonne National Laboratory provided by the U.S. Department of Energy, Office of Energy Efficiency and Renewable Energy (EERE), under contract DE-AC02-06CH11357 - -References -========== - -If you use LLEPE in your research , we kindly request that you cite the package as follows: - -T. Quah and C. O. Iloeje, “Liquid--Liquid Extraction Thermodynamic Parameter Estimator (LLEPE) for Multicomponent Separation Systems,” in Materials Processing Fundamentals 2021, 2021, pp. 107–120, doi: https://doi.org/10.1007/978-3-030-65253-1_9. - -License -======= - -:: - - Copyright © 2020, UChicago Argonne, LLC - All Rights Reserved - Software Name: LLEPE - By: Argonne National Laboratory, University of Utah - OPEN SOURCE LICENSE - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - - ****************************************************************************************************** - DISCLAIMER - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - OF SUCH DAMAGE. - *************************************************************************************************** diff --git a/docs/_build/html/_sources/guide/install.rst.txt b/docs/_build/html/_sources/guide/install.rst.txt index e7306d7..ce1a1f9 100644 --- a/docs/_build/html/_sources/guide/install.rst.txt +++ b/docs/_build/html/_sources/guide/install.rst.txt @@ -24,17 +24,17 @@ To install the latest master version: .. code-block:: bash - pip install git+https://github.com/ANL-CEEESA/LLEPE.git + pip install git+https://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git Development version =================== -To contribute to LLEPE, with support for running tests and building the documentation. +To contribute to Stable-Baselines, with support for running tests and building the documentation. .. code-block:: bash - git clone https://github.com/ANL-CEEESA/LLEPE.git + git clone https://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git && cd parameter-estimation pip install -e .[docs,tests] diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt index a0c905b..9a973a9 100644 --- a/docs/_build/html/_sources/index.rst.txt +++ b/docs/_build/html/_sources/index.rst.txt @@ -1,8 +1,9 @@ -.. LLEPE: Liquid-Liquid Equilibrium Parameter Estimator - Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. - Released under the modified BSD license. See LICENSE for more details. +.. reeps documentation master file, created by Titus Quah + sphinx-quickstart on Tue Jun 9 10:13:23 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. -Welcome to LLEPE's docs! - the Liquid-Liquid Extraction Parameter Estimator +Welcome to llepe's docs! - the Liquid-Liquid Extraction Parameter Estimator =========================================================================== LLEPE is a package for thermodynamic parameter estimation for liquid-liquid extraction modeling @@ -18,13 +19,12 @@ Error between predicted and experimental data is then minimized. guide/install guide/quickstart - guide/about .. toctree:: :maxdepth: 1 :caption: Searchers - modules/LLEPE + modules/reeps diff --git a/docs/_build/html/_sources/modules/LLEPE.rst.txt b/docs/_build/html/_sources/modules/LLEPE.rst.txt deleted file mode 100644 index 41daa9d..0000000 --- a/docs/_build/html/_sources/modules/LLEPE.rst.txt +++ /dev/null @@ -1,15 +0,0 @@ -.. _LLEPE: - -.. automodule:: llepe - -LLEPE -===== - - - -Parameters ----------- - -.. autoclass:: LLEPE - :members: - :inherited-members: \ No newline at end of file diff --git a/docs/_build/html/_sources/modules/reeps.rst.txt b/docs/_build/html/_sources/modules/reeps.rst.txt index 41daa9d..bba5c13 100644 --- a/docs/_build/html/_sources/modules/reeps.rst.txt +++ b/docs/_build/html/_sources/modules/reeps.rst.txt @@ -1,4 +1,4 @@ -.. _LLEPE: +.. _reeps: .. automodule:: llepe diff --git a/docs/_build/html/_static/alabaster.css b/docs/_build/html/_static/alabaster.css new file mode 100644 index 0000000..0eddaeb --- /dev/null +++ b/docs/_build/html/_static/alabaster.css @@ -0,0 +1,701 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/docs/_build/html/_static/classic.css b/docs/_build/html/_static/classic.css new file mode 100644 index 0000000..b4fd80f --- /dev/null +++ b/docs/_build/html/_static/classic.css @@ -0,0 +1,266 @@ +/* + * classic.css_t + * ~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- classic theme. + * + * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +html { + /* CSS hack for macOS's scrollbar (see #1125) */ + background-color: #FFFFFF; +} + +body { + font-family: sans-serif; + font-size: 100%; + background-color: #11303d; + color: #000; + margin: 0; + padding: 0; +} + +div.document { + background-color: #1c4e63; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 230px; +} + +div.body { + background-color: #ffffff; + color: #000000; + padding: 0 20px 30px 20px; +} + +div.footer { + color: #ffffff; + width: 100%; + padding: 9px 0 9px 0; + text-align: center; + font-size: 75%; +} + +div.footer a { + color: #ffffff; + text-decoration: underline; +} + +div.related { + background-color: #133f52; + line-height: 30px; + color: #ffffff; +} + +div.related a { + color: #ffffff; +} + +div.sphinxsidebar { +} + +div.sphinxsidebar h3 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.4em; + font-weight: normal; + margin: 0; + padding: 0; +} + +div.sphinxsidebar h3 a { + color: #ffffff; +} + +div.sphinxsidebar h4 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.3em; + font-weight: normal; + margin: 5px 0 0 0; + padding: 0; +} + +div.sphinxsidebar p { + color: #ffffff; +} + +div.sphinxsidebar p.topless { + margin: 5px 10px 10px 10px; +} + +div.sphinxsidebar ul { + margin: 10px; + padding: 0; + color: #ffffff; +} + +div.sphinxsidebar a { + color: #98dbcc; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + + + +/* -- hyperlink styles ------------------------------------------------------ */ + +a { + color: #355f7c; + text-decoration: none; +} + +a:visited { + color: #355f7c; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + + + +/* -- body styles ----------------------------------------------------------- */ + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Trebuchet MS', sans-serif; + background-color: #f2f2f2; + font-weight: normal; + color: #20435c; + border-bottom: 1px solid #ccc; + margin: 20px -20px 10px -20px; + padding: 3px 0 3px 10px; +} + +div.body h1 { margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 160%; } +div.body h3 { font-size: 140%; } +div.body h4 { font-size: 120%; } +div.body h5 { font-size: 110%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + text-align: justify; + line-height: 130%; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.admonition p { + margin-bottom: 5px; +} + +div.admonition pre { + margin-bottom: 5px; +} + +div.admonition ul, div.admonition ol { + margin-bottom: 5px; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 5px; + background-color: #eeffcc; + color: #333333; + line-height: 120%; + border: 1px solid #ac9; + border-left: none; + border-right: none; +} + +code { + background-color: #ecf0f3; + padding: 0 1px 0 1px; + font-size: 0.95em; +} + +th, dl.field-list > dt { + background-color: #ede; +} + +.warning code { + background: #efc2c2; +} + +.note code { + background: #d6d6d6; +} + +.viewcode-back { + font-family: sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} + +div.code-block-caption { + color: #efefef; + background-color: #1c4e63; +} \ No newline at end of file diff --git a/docs/_build/html/_static/custom.css b/docs/_build/html/_static/custom.css new file mode 100644 index 0000000..2a924f1 --- /dev/null +++ b/docs/_build/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/docs/_build/html/_static/default.css b/docs/_build/html/_static/default.css new file mode 100644 index 0000000..81b9363 --- /dev/null +++ b/docs/_build/html/_static/default.css @@ -0,0 +1 @@ +@import url("classic.css"); diff --git a/docs/_build/html/_static/sidebar.js b/docs/_build/html/_static/sidebar.js new file mode 100644 index 0000000..657f8be --- /dev/null +++ b/docs/_build/html/_static/sidebar.js @@ -0,0 +1,159 @@ +/* + * sidebar.js + * ~~~~~~~~~~ + * + * This script makes the Sphinx sidebar collapsible. + * + * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds + * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton + * used to collapse and expand the sidebar. + * + * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden + * and the width of the sidebar and the margin-left of the document + * are decreased. When the sidebar is expanded the opposite happens. + * This script saves a per-browser/per-session cookie used to + * remember the position of the sidebar among the pages. + * Once the browser is closed the cookie is deleted and the position + * reset to the default (expanded). + * + * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +$(function() { + + + + + + + + + // global elements used by the functions. + // the 'sidebarbutton' element is defined as global after its + // creation, in the add_sidebar_button function + var bodywrapper = $('.bodywrapper'); + var sidebar = $('.sphinxsidebar'); + var sidebarwrapper = $('.sphinxsidebarwrapper'); + + // for some reason, the document has no sidebar; do not run into errors + if (!sidebar.length) return; + + // original margin-left of the bodywrapper and width of the sidebar + // with the sidebar expanded + var bw_margin_expanded = bodywrapper.css('margin-left'); + var ssb_width_expanded = sidebar.width(); + + // margin-left of the bodywrapper and width of the sidebar + // with the sidebar collapsed + var bw_margin_collapsed = '.8em'; + var ssb_width_collapsed = '.8em'; + + // colors used by the current theme + var dark_color = $('.related').css('background-color'); + var light_color = $('.document').css('background-color'); + + function sidebar_is_collapsed() { + return sidebarwrapper.is(':not(:visible)'); + } + + function toggle_sidebar() { + if (sidebar_is_collapsed()) + expand_sidebar(); + else + collapse_sidebar(); + } + + function collapse_sidebar() { + sidebarwrapper.hide(); + sidebar.css('width', ssb_width_collapsed); + bodywrapper.css('margin-left', bw_margin_collapsed); + sidebarbutton.css({ + 'margin-left': '0', + 'height': bodywrapper.height() + }); + sidebarbutton.find('span').text('»'); + sidebarbutton.attr('title', _('Expand sidebar')); + document.cookie = 'sidebar=collapsed'; + } + + function expand_sidebar() { + bodywrapper.css('margin-left', bw_margin_expanded); + sidebar.css('width', ssb_width_expanded); + sidebarwrapper.show(); + sidebarbutton.css({ + 'margin-left': ssb_width_expanded-12, + 'height': bodywrapper.height() + }); + sidebarbutton.find('span').text('«'); + sidebarbutton.attr('title', _('Collapse sidebar')); + document.cookie = 'sidebar=expanded'; + } + + function add_sidebar_button() { + sidebarwrapper.css({ + 'float': 'left', + 'margin-right': '0', + 'width': ssb_width_expanded - 28 + }); + // create the button + sidebar.append( + '
«
' + ); + var sidebarbutton = $('#sidebarbutton'); + light_color = sidebarbutton.css('background-color'); + // find the height of the viewport to center the '<<' in the page + var viewport_height; + if (window.innerHeight) + viewport_height = window.innerHeight; + else + viewport_height = $(window).height(); + sidebarbutton.find('span').css({ + 'display': 'block', + 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 + }); + + sidebarbutton.click(toggle_sidebar); + sidebarbutton.attr('title', _('Collapse sidebar')); + sidebarbutton.css({ + 'color': '#FFFFFF', + 'border-left': '1px solid ' + dark_color, + 'font-size': '1.2em', + 'cursor': 'pointer', + 'height': bodywrapper.height(), + 'padding-top': '1px', + 'margin-left': ssb_width_expanded - 12 + }); + + sidebarbutton.hover( + function () { + $(this).css('background-color', dark_color); + }, + function () { + $(this).css('background-color', light_color); + } + ); + } + + function set_position_from_cookie() { + if (!document.cookie) + return; + var items = document.cookie.split(';'); + for(var k=0; k
  • Installation
  • Getting Started
  • -
  • About
  • Searchers

    @@ -170,7 +169,7 @@

    F

    @@ -178,45 +177,45 @@

    G

    @@ -228,14 +227,14 @@ llepe @@ -247,7 +246,7 @@ module @@ -256,11 +255,11 @@

    P

    @@ -268,7 +267,7 @@

    R

    @@ -276,45 +275,45 @@

    S

    @@ -322,13 +321,13 @@

    U

    @@ -345,7 +344,7 @@

    - © Copyright 2020, UChicago Argonne, LLC. + © Copyright 2020, Titus Quah, Nwike Iloeje

    diff --git a/docs/_build/html/guide/about.html b/docs/_build/html/guide/about.html deleted file mode 100644 index 67be0bd..0000000 --- a/docs/_build/html/guide/about.html +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - - - - - - About — LLEPE 1.0.0 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - -
    - - - - - -
    - -
    - - - - - - - - - - - - - - - - - -
    - - - - -
    -
    -
    -
    - -
    -

    About

    -
    -

    Authors

    -

    Titus Quah, University of Utah, <titus{dot}quah{at}gmail{dot}com>

    -

    Nwike Iloeje, Argonne National Laboratory, <ciloeje{at}anl{dot}gov>

    -
    -
    -

    Acknowledgements

    -

    Based upon work supported by funding from Argonne National Laboratory provided by the U.S. Department of Energy, Office of Energy Efficiency and Renewable Energy (EERE), under contract DE-AC02-06CH11357

    -
    -
    -

    References

    -

    If you use LLEPE in your research , we kindly request that you cite the package as follows:

    -
      -
    1. Quah and C. O. Iloeje, “Liquid--Liquid Extraction Thermodynamic Parameter Estimator (LLEPE) for Multicomponent Separation Systems,” in Materials Processing Fundamentals 2021, 2021, pp. 107–120, doi: https://doi.org/10.1007/978-3-030-65253-1_9.

    2. -
    -
    -
    -

    License

    -
    Copyright © 2020, UChicago Argonne, LLC
    -All Rights Reserved
    - Software Name: LLEPE
    -By: Argonne National Laboratory, University of Utah
    -OPEN SOURCE LICENSE
    -
    -Redistribution and use in source and binary forms, with or without
    -modification, are permitted provided that the following conditions are met:
    -
    -1. Redistributions of source code must retain the above copyright notice,
    -   this list of conditions and the following disclaimer.
    -2. Redistributions in binary form must reproduce the above copyright notice,
    -   this list of conditions and the following disclaimer in the documentation
    -   and/or other materials provided with the distribution.
    -3. Neither the name of the copyright holder nor the names of its contributors
    -   may be used to endorse or promote products derived from this software without
    -   specific prior written permission.
    -
    -
    -******************************************************************************************************
    -DISCLAIMER
    -
    -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
    -OF SUCH DAMAGE.
    -***************************************************************************************************
    -
    -
    -
    -
    - - -
    - -
    - - -
    -
    - -
    - -
    - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_build/html/guide/install.html b/docs/_build/html/guide/install.html index 17e566e..f28dddc 100644 --- a/docs/_build/html/guide/install.html +++ b/docs/_build/html/guide/install.html @@ -36,7 +36,7 @@ - + @@ -97,7 +97,7 @@

    Searchers

    @@ -175,14 +175,14 @@

    Bleeding-edge version

    To install the latest master version:

    -
    pip install git+https://github.com/ANL-CEEESA/LLEPE.git
    +
    pip install git+https://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git
     

    Development version

    -

    To contribute to LLEPE, with support for running tests and building the documentation.

    -
    git clone https://github.com/ANL-CEEESA/LLEPE.git
    +

    To contribute to Stable-Baselines, with support for running tests and building the documentation.

    +
    git clone https://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git && cd parameter-estimation
     pip install -e .[docs,tests]
     
    @@ -204,7 +204,7 @@ pip install -e .[docs,tests] - +
    @@ -213,7 +213,7 @@ pip install -e .[docs,tests]

    - © Copyright 2020, UChicago Argonne, LLC. + © Copyright 2020, Titus Quah, Nwike Iloeje

    diff --git a/docs/_build/html/guide/quickstart.html b/docs/_build/html/guide/quickstart.html index 72b8974..948381e 100644 --- a/docs/_build/html/guide/quickstart.html +++ b/docs/_build/html/guide/quickstart.html @@ -218,7 +218,7 @@ aqueous phase.

    - © Copyright 2020, UChicago Argonne, LLC. + © Copyright 2020, Titus Quah, Nwike Iloeje

    diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html index 9cee7a4..7f6af8e 100644 --- a/docs/_build/html/index.html +++ b/docs/_build/html/index.html @@ -8,7 +8,7 @@ - Welcome to LLEPE's docs! - the Liquid-Liquid Extraction Parameter Estimator — LLEPE 1.0.0 documentation + Welcome to llepe's docs! - the Liquid-Liquid Extraction Parameter Estimator — LLEPE 1.0.0 documentation @@ -86,11 +86,10 @@

    Searchers

    @@ -136,7 +135,7 @@
  • Docs »
  • -
  • Welcome to LLEPE's docs! - the Liquid-Liquid Extraction Parameter Estimator
  • +
  • Welcome to llepe's docs! - the Liquid-Liquid Extraction Parameter Estimator
  • @@ -156,7 +155,7 @@
    -

    Welcome to LLEPE's docs! - the Liquid-Liquid Extraction Parameter Estimator

    +

    Welcome to llepe's docs! - the Liquid-Liquid Extraction Parameter Estimator

    LLEPE is a package for thermodynamic parameter estimation for liquid-liquid extraction modeling

    LLEPE takes experimental data in a csv and system data in a xml.

    The package then uses Cantera, another python package, to simulate equilibrium.

    @@ -173,19 +172,12 @@
  • Getting Started
  • -
  • About -
  • Searchers

    @@ -216,7 +208,7 @@

    - © Copyright 2020, UChicago Argonne, LLC. + © Copyright 2020, Titus Quah, Nwike Iloeje

    diff --git a/docs/_build/html/modules/LLEPE.html b/docs/_build/html/modules/LLEPE.html deleted file mode 100644 index 4f1ff3b..0000000 --- a/docs/_build/html/modules/LLEPE.html +++ /dev/null @@ -1,1123 +0,0 @@ - - - - - - - - - - - LLEPE — LLEPE 1.0.0 documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - -
    - - - - - -
    - -
    - - - - - - - - - - - - - - - - - -
    - - - - -
    -
    -
    -
    - -
    -

    LLEPE

    -
    -

    Parameters

    -
    -
    -class llepe.LLEPE(exp_data, phases_xml_filename, phase_names, aq_solvent_name, extractant_name, diluant_name, complex_names, extracted_species_ion_names, extracted_species_list=None, aq_solvent_rho=None, extractant_rho=None, diluant_rho=None, opt_dict=None, objective_function='Log-MSE', optimizer='scipy_minimize', temp_xml_file_path=None, dependant_params_dict=None, custom_objects_dict=None)[source]
    -

    Liquid-Liquid Extraction Parameter estimator

    -
    -

    Note

    -

    The order in which the extracted species (ES) appear in the csv file -must be the same order as they appear in the xml, complex_names and -extracted_species_ion_names.

    -

    For example, say in exp_data, ES_1 is Nd ES_2 is Pr, -and

    -
    aq_solvent_name = 'H2O(L)'
    -extractant_name = '(HA)2(org)'
    -diluent_name = 'dodecane'
    -
    -
    -

    Then:

    -

    The exp_data column ordering must be (names do not matter):

    -

    [h_i, h_eq, z_i, z_eq, Nd_aq_i, Nd_aq_eq, Nd_d_eq, -Pr_aq_i, Pr_aq_eq, Pr_d_eq]

    -

    The aqueous speciesArray must be -"H2O(L) H+ OH- Cl- Nd+++ Pr+++"

    -

    The organic speciesArray must be -"(HA)2(org) dodecane Nd(H(A)2)3(org) Pr(H(A)2)3(org)"

    -
    complex_names = ['Nd(H(A)2)3(org)', 'Pr(H(A)2)3(org)']
    -extracted_species_ion_names = ['Nd+++', 'Pr+++']
    -
    -
    -
    -
    -
    Parameters
    -
      -
    • exp_data --

      (str or pd.DataFrame) csv file name -or DataFrame with experimental data

      -

      In the .csv file, the rows are different experiments and -columns are the measured quantities.

      -

      The ordering of the columns needs to be:

      -

      [h_i, h_eq, z_i, z_eq, -{ES_1}_aq_i, {ES_1}_aq_eq, {ES_1}_d_eq, -{ES_2}_aq_i, {ES_2}_aq_eq, {ES_2}_d_eq,... -{ES_N}_aq_i, {ES_N}_aq_eq, {ES_N}_d_eq]

      -

      Naming does not matter, just the order.

      -

      Where {ES_1}-{ES_N} are the extracted species names of interest -i.e. Nd, Pr, La, etc.

      -

      Below is an explanation of the columns.

      - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      Index

      Column

      Meaning

      0

      h_i

      Initial Concentration of -H+ ions (mol/L)

      1

      h_eq

      Equilibrium concentration of -H+ ions (mol/L)

      2

      z_i

      Initial concentration of -extractant (mol/L)

      3

      z_eq

      Equilibrium concentration of -extractant (mol/L)

      4

      {ES}_aq_i

      Initial concentration of ES ions (mol/L)

      5

      {ES}_aq_eq

      Equilibrium concentration of ES ions -in aqueous phase (mol/L)

      6

      {ES}_d_eq

      Equilibrium Ratio between amount of -ES atoms in organic to aqueous

      -

    • -
    • phases_xml_filename --

      (str) xml file with parameters -for equilibrium calc

      -

      Would recommend copying and modifying xmls located in data/xmls -or in Cantera's "data" folder

      -

      speciesArray fields need specific ordering.

      -

      In aqueous phase: aq_solvent_name, H+, OH-, Cl-, ES_1, ES_2, ..., ES_N

      -

      (ES_1-ES_N) represent ES ion names i.e. Nd+++, Pr+++

      -

      In organic phase : extractant_name, diluant_name, ES_1, ES_2, ..., ES_N

      -

      (ES_1-ES_N) represent ES complex names -i.e. Nd(H(A)2)3(org), Pr(H(A)2)3(org)

      -

    • -
    • phase_names --

      (list) names of phases in xml file

      -

      Found in the xml file under <phase ... id={phase_name}>

      -

    • -
    • aq_solvent_name -- (str) name of aqueous solvent in xml file

    • -
    • extractant_name -- (str) name of extractant in xml file

    • -
    • diluant_name -- (str) name of diluant in xml file

    • -
    • complex_names -- (list) names of complexes in xml file.

    • -
    • extracted_species_ion_names -- (list) names of extracted species ions -in xml file

    • -
    • extracted_species_list --

      (list) names of extracted species elements.

      -

      If None, extracted_species_list will be extracted_species_ion_names -without '+' i.e. 'Nd+++'->'Nd'

      -

    • -
    • aq_solvent_rho --

      (float) density of solvent (g/L)

      -

      If None, molar volume/molecular weight is used from xml

      -

    • -
    • extractant_rho --

      (float) density of extractant (g/L)

      -

      If None, molar volume/molecular weight is used from xml

      -

    • -
    • diluant_rho --

      (float) density of diluant (g/L)

      -

      If None, molar volume/molecular weight is used from xml

      -

    • -
    • opt_dict --

      (dict) dictionary containing info about which -species parameters are updated to fit model to experimental data

      -

      Should have the format as below. Dictionary keys under user defined -parameter name must be named as shown below ('upper_element_name', -'upper_attrib_name', etc.). 'attrib_name's and 'attrib_value's can -be None. {} denotes areas for user to fill in.

      -
      opt_dict = {"{user_defined_name_for_parameter_1}":
      -                {'upper_element_name': {param_upper_element},
      -                'upper_attrib_name': {param_upper_attrib_name},
      -                'upper_attrib_value': {param_upper_attrib_value},
      -                'lower_element_name': {param_lower_element},
      -                'lower_attrib_name': {param_lower_attrib_name},
      -                'lower_attrib_value': {param_lower_attrib_value},
      -                'input_format': {str format to input input_value}
      -                'input_value': {guess_value}},
      -            "{user_defined_name_for_parameter_2}":
      -                            ...
      -            ...
      -            }
      -
      -
      -

      See example files for more examples.

      -

    • -
    • objective_function --

      (function or str) function to compute objective

      -

      By default, the objective function is log mean squared error -of distribution ratio

      -
      np.sum((np.log10(d_pred)-np.log10(d_meas))^2)
      -
      -
      -

      Function needs to take inputs:

      -
      objective_function(predicted_dict, measured_df, kwargs)
      -
      -
      -

      kwargs is optional

      -

      Function needs to return: (float) value computed by objective function

      -

      Below is the guide for referencing predicted values

      - ---- - - - - - - - - - - - - - - - - - - - - - - -

      To access

      Use

      hydrogen ion conc in aq

      predicted_dict['h_eq']

      extractant conc in org

      predicted_dict['z_eq']

      ES ion eq conc in aq

      predicted_dict['{ES}_aq_eq']

      ES complex eq conc in org

      predicted_dict['{ES}_org_eq']

      ES distribution ratio

      predicted_dict['{ES}_d_eq']

      -

      Replace "{ES}" with extracted species element i.e. Nd, La, etc.

      -

      For measured values, use the same names, but -replace predicted_dict with measured_df

      -

    • -
    • optimizer --

      (function or str) function to perform optimization

      -
      -

      Note

      -

      The optimized variables are not directly the species parameters, -but instead are first multiplied by the initial guess before -sending becoming the species parameters.

      -

      For example, say

      -
      opt_dict = {'Nd(H(A)2)3(org):'h0':-4.7e6}
      -
      -
      -

      If the bounds on h0 need to be [-4.7e7,-4.7e5], then -divide the bounds by the guess and get

      -
      "bounds": [(1e-1, 1e1)]
      -
      -
      -
      -

      By default, the optimizer is scipy's optimize function with

      -
      default_kwargs= {"method": 'SLSQP',
      -                 "bounds": [(1e-1, 1e1)] * len(x_guess),
      -                 "constraints": (),
      -                 "options": {'disp': True,
      -                             'maxiter': 1000,
      -                             'ftol': 1e-6}}
      -
      -
      -

      Function needs to take inputs: -optimizer(objective_function, x_guess, kwargs)

      -

      kwargs is optional

      -
      -
      Function needs to return: ((np.ndarray, float)) Optimized parameters,

      objective_function value

      -
      -
      -

    • -
    • temp_xml_file_path --

      (str) path to temporary xml file.

      -

      This xml file is a duplicate of the phases_xml_file name and is -modified during the optimization process to avoid changing the original -xml file

      -

      default is local temp folder

      -

    • -
    • dependant_params_dict --

      (dict) dictionary containing information -about parameters dependant on opt_dict. Has a similar structure to -opt_dict except instead of input values, it has 3 other fields: -'function', 'kwargs', and 'independent_params.

      -

      'function' is a function of the form

      -

      function(independent_param__value_list, custom_objects_dict, -**kwargs)

      -

      'kwargs' are the extra arguments to pass to function

      -

      'independent_params' is a list of parameter names in opt_dict that the -dependent_param is a function of.

      -

      'custom_objects_dict' is for accessing the estimator's internal -custom_objects_dict and must be included in the arguments, even if the -custom_objects_dict is not set and is None.

      -

      See example code for usage.

      -

    • -
    • custom_objects_dict -- (dict) dictionary containing custom objects -format: {<object_name_string>: <object>,...}

    • -
    -
    -
    -
    -
    -fit(objective_function=None, optimizer=None, objective_kwargs=None, optimizer_kwargs=None) → tuple[source]
    -

    Fits experimental to modeled data by minimizing objective function -with optimizer. Returns dictionary with opt_dict structure

    -
    -
    Parameters
    -
      -
    • objective_function -- (function) function to compute objective -If 'None', last set objective or default function is used

    • -
    • optimizer -- (function) function to perform optimization -If 'None', last set optimizer or default is used

    • -
    • optimizer_kwargs -- (dict) optional arguments for optimizer

    • -
    • objective_kwargs -- (dict) optional arguments -for objective function

    • -
    -
    -
    Returns tuple
    -

    (opt_dict (dict), opt_value (float)) -optimized opt_dict: Has identical structure as opt_dict

    -
    -
    -
    - -
    -
    -get_aq_solvent_name() → str[source]
    -

    Returns aq_solvent_name

    -
    -
    Returns
    -

    aq_solvent_name: (str) name of aqueous solvent in xml file

    -
    -
    -
    - -
    -
    -get_aq_solvent_rho() → str[source]
    -

    Returns aqueous solvent density (g/L)

    -
    -
    Returns
    -

    aq_solvent_rho: (float) density of aqueous solvent

    -
    -
    -
    - -
    -
    -get_complex_names() → list[source]
    -

    Returns list of complex names

    -
    -
    Returns
    -

    complex_names: (list) names of complexes in xml file.

    -
    -
    -
    - -
    -
    -get_custom_objects_dict()[source]
    -

    Returns the custom_objects_dict

    -
    -
    Returns
    -

    custom_objects_dict: (dict) dictionary containing -information about custom objects from user

    -
    -
    -
    - -
    -
    -get_dependant_params_dict()[source]
    -

    Returns the dependant_params_dict

    -
    -
    Returns
    -

    dependant_params_dict: (dict) dictionary containing -information about parameters dependant on opt_dict

    -
    -
    -
    - -
    -
    -get_diluant_name() → str[source]
    -

    Returns diluant name -:return: diluant_name: (str) name of diluant in xml file

    -
    - -
    -
    -get_diluant_rho() → str[source]
    -

    Returns diluant density (g/L)

    -
    -
    Returns
    -

    diluant_rho: (float) density of diluant

    -
    -
    -
    - -
    -
    -get_exp_df() → pandas.core.frame.DataFrame[source]
    -

    Returns the experimental DataFrame

    -
    -
    Returns
    -

    (pd.DataFrame) Experimental data

    -
    -
    -
    - -
    -
    -get_extractant_name() → str[source]
    -

    Returns extractant name

    -
    -
    Returns
    -

    extractant_name: (str) name of extractant in xml file

    -
    -
    -
    - -
    -
    -get_extractant_rho() → str[source]
    -

    Returns extractant density (g/L)

    -
    -
    Returns
    -

    extractant_rho: (float) density of extractant

    -
    -
    -
    - -
    -
    -get_extracted_species_ion_names() → list[source]
    -

    Returns list of extracted species ion names

    -
    -
    Returns
    -

    extracted_species_ion_names: (list) names of -extracted species ions in xml file

    -
    -
    -
    - -
    -
    -get_extracted_species_list() → list[source]
    -

    Returns list of extracted species names

    -
    -
    Returns
    -

    extracted_species_list: (list) names of extracted species in -xml file

    -
    -
    -
    - -
    -
    -get_in_moles() → pandas.core.frame.DataFrame[source]
    -

    Returns the in_moles DataFrame which contains the initial mole -fractions of each species for each experiment

    -
    -
    Returns
    -

    in_moles: (pd.DataFrame) DataFrame with initial mole fractions

    -
    -
    -
    - -
    -
    -get_objective_function()[source]
    -

    Returns objective function

    -
    -
    Returns
    -

    objective_function: (func) Objective function to quantify -error between model and experimental data

    -
    -
    -
    - -
    -
    -get_opt_dict() → dict[source]
    -

    Returns the dictionary containing optimization information

    -
    -
    Returns
    -

    (dict) dictionary containing info about which -species parameters are updated to fit model to experimental data

    -
    -
    -
    - -
    -
    -get_optimizer()[source]
    -

    Returns objective function

    -
    -
    Returns
    -

    optimizer: (func) Optimizer function to minimize objective -function

    -
    -
    -
    - -
    -
    -get_phases() → list[source]
    -

    Returns the list of Cantera solutions

    -
    -
    Returns
    -

    (list) list of Cantera solutions/phases

    -
    -
    -
    - -
    -
    -get_predicted_dict()[source]
    -

    Returns predicted dictionary of species concentrations -that xml parameters predicts given current in_moles

    -
    -
    Returns
    -

    predicted_dict: (dict) dictionary of species concentrations

    -
    -
    -
    - -
    -
    -get_temp_xml_file_path()[source]
    -

    Returns path to temporary xml file.

    -

    This xml file is a duplicate of the phases_xml_file name and is -modified during the optimization process to avoid changing the original -xml file.

    -
    -
    Returns
    -

    temp_xml_file_path: (str) path to temporary xml file.

    -
    -
    -
    - -
    -
    -log_mean_squared_error(predicted_dict, meas_df)[source]
    -

    Default objective function for LLEPE

    -

    Returns the log mean squared error of -predicted distribution ratios (d=n_org/n_aq) -to measured d.

    -

    np.sum((np.log10(d_pred)-np.log10(d_meas))**2)

    -
    -
    Parameters
    -
      -
    • predicted_dict -- (dict) contains predicted data

    • -
    • meas_df -- (pd.DataFrame) contains experimental data

    • -
    -
    -
    Returns
    -

    (float) log mean squared error between predicted and measured

    -
    -
    -
    - -
    -
    -parity_plot(compared_value=None, c_data=None, c_label=None, plot_title=None, save_path=None, print_r_squared=False, data_labels=None, legend=True)[source]
    -

    Parity plot between measured and predicted compared_value. -Default compared value is {ES_1}_aq_eq

    -
    -
    Parameters
    -
      -
    • compared_value -- (str) Quantity to compare predicted and -experimental data. Can be any column containing "eq" in exp_df i.e. -h_eq, z_eq, {ES}_d_eq, etc.

    • -
    • plot_title --

      (str or boolean)

      -
      -
      If None (default): Plot title will be generated from compared_value

      Recommend to just explore. If h_eq, plot_title is -"H^+ eq conc".

      -
      -
      -

      If str: Plot title will be plot_title string

      -

      If "False": No plot title

      -

    • -
    • c_data -- (list or np.ndarray) data for color axis

    • -
    • c_label -- (str) label for color axis

    • -
    • save_path -- (str) save path for parity plot

    • -
    • print_r_squared -- (boolean) To plot or not to plot r-squared -value. Prints 2 places past decimal

    • -
    • data_labels -- labels for the data such as paper's name where -experiment is pulled from.

    • -
    • legend -- whether to display legend for data_labels. Has no -effect if data_labels is None

    • -
    -
    -
    Return fig, ax
    -

    returns the figure and axes objects

    -
    -
    -
    - -
    -
    -static plot_3d_data(x_data, y_data, z_data, c_data=None, x_label=None, y_label=None, z_label=None, c_label=None)[source]
    -

    THis is for plotting 3d scatter plots. -We suggest use matplotlib's ax.scatter to make 3d plots.

    -
    -
    Parameters
    -
      -
    • x_data -- (list) list of data for x axis

    • -
    • y_data -- (list) list of data for y axis

    • -
    • z_data -- (list) list of data for z axis

    • -
    • c_data -- (list) list of data for color axis

    • -
    • x_label -- (str) label for x axis

    • -
    • y_label -- (str) label for y axis

    • -
    • z_label -- (str) label for z axis

    • -
    • c_label -- (str) label for color axis

    • -
    -
    -
    Returns
    -

    -
    -
    -
    - -
    -
    -r_squared(compared_value=None)[source]
    -

    r-squared value comparing measured and predicted compared value

    -

    Closer to 1, the better the model's predictions.

    -
    -
    Parameters
    -

    compared_value -- (str) Quantity to compare predicted and -experimental data. Can be any column containing "eq" in exp_df i.e. -h_eq, z_eq, {ES}_d_eq, etc. default is {ES}_aq_eq

    -
    -
    -
    - -
    -
    -static scipy_minimize(objective, x_guess, optimizer_kwargs=None)[source]
    -

    The default optimizer for LLEPE

    -

    Uses scipy.minimize

    -

    By default, options are

    -
    default_kwargs= {"method": 'SLSQP',
    -                "bounds": [(1e-1, 1e1)]*len(x_guess),
    -                "constraints": (),
    -                "options": {'disp': True,
    -                            'maxiter': 1000,
    -                            'ftol': 1e-6}}
    -
    -
    -
    -
    Parameters
    -
      -
    • objective -- (func) the objective function

    • -
    • x_guess -- (np.ndarray) the initial guess (always 1)

    • -
    • optimizer_kwargs -- (dict) dictionary of options for minimize

    • -
    -
    -
    Returns
    -

    ((np.ndarray, float)) Optimized parameters, -objective_function value

    -
    -
    -
    - -
    -
    -set_aq_solvent_name(aq_solvent_name)[source]
    -

    Change aq_solvent_name to input aq_solvent_name

    -
    -
    Parameters
    -

    aq_solvent_name -- (str) name of aqueous solvent in xml file

    -
    -
    -
    - -
    -
    -set_aq_solvent_rho(aq_solvent_rho)[source]
    -

    Changes aqueous solvent density (g/L) to input aq_solvent_rho

    -
    -
    Parameters
    -

    aq_solvent_rho -- (float) density of aqueous solvent

    -
    -
    -
    - -
    -
    -set_complex_names(complex_names)[source]
    -

    Change complex names list to input complex_names

    -
    -
    Parameters
    -

    complex_names -- (list) names of complexes in xml file.

    -
    -
    -
    - -
    -
    -set_custom_objects_dict(custom_objects_dict)[source]
    -

    Sets the custom_objects_dict

    -
    -
    Parameters
    -

    custom_objects_dict -- (dict) dictionary containing information -about about custom objects from user

    -
    -
    -
    - -
    -
    -set_dependant_params_dict(dependant_params_dict)[source]
    -

    Sets the dependant_params_dict

    -
    -
    Parameters
    -

    dependant_params_dict -- (dict) dictionary containing information -about parameters dependant on opt_dict

    -
    -
    -
    - -
    -
    -set_diluant_name(diluant_name)[source]
    -

    Change diluant_name to input diluant_name

    -
    -
    Parameters
    -

    diluant_name -- (str) name of diluant in xml file

    -
    -
    -
    - -
    -
    -set_diluant_rho(diluant_rho)[source]
    -

    Changes diluant density (g/L) to input diluant_rho

    -
    -
    Parameters
    -

    diluant_rho -- (float) density of diluant

    -
    -
    -
    - -
    -
    -set_exp_df(exp_data)[source]
    -

    Changes the experimental DataFrame to input exp_csv_filename data -and renames columns to internal LLEPE names

    -

    h_i, h_eq, z_i, z_eq, {ES}_aq_i, {ES}_aq_eq, {ES}_d

    -

    See class docstring on "exp_csv_filename" for further explanations.

    -
    -
    Parameters
    -

    exp_data -- (str or pd.DataFrame) -file name/path or DataFrame for experimental data csv

    -
    -
    -
    - -
    -
    -set_extractant_name(extractant_name)[source]
    -

    Change extractant_name to input extractant_name -:param extractant_name: (str) name of extractant in xml file

    -
    - -
    -
    -set_extractant_rho(extractant_rho)[source]
    -

    Changes extractant density (g/L) to input extractant_rho

    -
    -
    Parameters
    -

    extractant_rho -- (float) density of extractant

    -
    -
    -
    - -
    -
    -set_extracted_species_ion_names(extracted_species_ion_names)[source]
    -
    -
    Change list of extracted species ion names to input

    extracted_species_ion_names

    -
    -
    -
    -
    Parameters
    -

    extracted_species_ion_names -- (list) names of extracted species -ions in xml file

    -
    -
    -
    - -
    -
    -set_extracted_species_list(extracted_species_list)[source]
    -
    -
    Change list of extracted species ion names to input

    extracted_species_ion_names

    -
    -
    -
    -
    Parameters
    -

    extracted_species_list -- (list) names of extracted species in -xml file

    -
    -
    -
    - -
    -
    -set_in_moles(feed_vol)[source]
    -

    Function that initializes mole fractions to input feed_vol

    -

    This function is called at initialization

    -

    Sets in_moles to a pd.DataFrame containing initial mole fractions

    -

    Columns for species and rows for different experiments

    -

    This function also calls update_predicted_dict

    -
    -
    Parameters
    -

    feed_vol -- (float) feed volume of mixture (L)

    -
    -
    -
    - -
    -
    -set_objective_function(objective_function)[source]
    -

    Change objective function to input objective_function.

    -
    -

    See class docstring on "objective_function" for instructions

    -
    -
    -
    Parameters
    -

    objective_function -- (func) Objective function to quantify -error between model and experimental data

    -
    -
    -
    - -
    -
    -set_opt_dict(opt_dict)[source]
    -

    Change the dictionary to input opt_dict.

    -

    opt_dict specifies species parameters to be updated to -fit model to data

    -

    See class docstring on "opt_dict" for more information.

    -
    -
    Parameters
    -

    opt_dict -- (dict) dictionary containing info about which -species parameters are updated to fit model to experimental data

    -
    -
    -
    - -
    -
    -set_optimizer(optimizer)[source]
    -

    Change optimizer function to input optimizer.

    -
    -

    See class docstring on "optimizer" for instructions

    -
    -
    -
    Parameters
    -

    optimizer -- (func) Optimizer function to minimize objective -function

    -
    -
    -
    - -
    -
    -set_phases(phases_xml_filename, phase_names)[source]
    -

    Change list of Cantera solutions by inputting -new xml file name and phase names

    -

    Also runs set_in_moles to set feed volume to 1 L

    -
    -
    Parameters
    -
      -
    • phases_xml_filename -- (str) xml file with parameters -for equilibrium calc

    • -
    • phase_names -- (list) names of phases in xml file

    • -
    -
    -
    -
    - -
    -
    -set_temp_xml_file_path(temp_xml_file_path)[source]
    -

    Changes temporary xml file path to input temp_xml_file_path.

    -

    This xml file is a duplicate of the phases_xml_file name and is -modified during the optimization process to avoid changing the original -xml file.

    -
    -
    Parameters
    -

    temp_xml_file_path -- (str) path to temporary xml file.

    -
    -
    -
    - -
    -
    -update_custom_objects_dict(info_dict)[source]
    -

    updates internal custom_objects_dict with info_dict

    -
    -
    Parameters
    -

    info_dict -- Requires an identical structure to opt_dict -Ignores items with keys containing "custom_object_name"

    -
    -
    Returns
    -

    None

    -
    -
    -
    - -
    -
    -update_predicted_dict(phases_xml_filename=None, phase_names=None)[source]
    -

    Function that computes the predicted equilibrium concentrations -the fed phases_xml_filename parameters predicts given the initial -mole fractions set by in_moles()

    -
    -
    Parameters
    -
      -
    • phases_xml_filename -- (str)xml file with parameters -for equilibrium calc. If None, the -current phases_xml_filename is used.

    • -
    • phase_names -- (list) names of phases in xml file. -If None, the current phases_names is used.

    • -
    -
    -
    -
    - -
    -
    -update_xml(info_dict, phases_xml_filename=None, dependant_params_dict=None)[source]
    -

    updates xml file with info_dict

    -
    -
    Parameters
    -
      -
    • info_dict -- (dict) Requires an identical structure to opt_dict -Ignores items with keys containing "custom_object_name"

    • -
    • phases_xml_filename -- (str) xml filename if editing other xml -If None, the current xml will be modified and the internal -Cantera phases will be refreshed to the new values.

    • -
    • dependant_params_dict -- (dict) dictionary containing information -about parameters dependant on info_dict

    • -
    -
    -
    -
    - -
    - -
    -
    - - -
    - -
    - - -
    -
    - -
    - -
    - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_build/html/modules/reeps.html b/docs/_build/html/modules/reeps.html index 8f4ad8e..9275abb 100644 --- a/docs/_build/html/modules/reeps.html +++ b/docs/_build/html/modules/reeps.html @@ -34,7 +34,8 @@ - + + @@ -86,6 +87,13 @@
  • Installation
  • Getting Started
  • +

    Searchers

    + @@ -149,8 +157,8 @@
    -
    -

    LLEPE

    +
    +

    LLEPE

    Parameters

    @@ -162,7 +170,7 @@

    The order in which the extracted species (ES) appear in the csv file must be the same order as they appear in the xml, complex_names and extracted_species_ion_names.

    -

    For example, say in exp_data, ES_1 is Nd ES_2 is Pr, +

    For example, say in exp_csv_filename's csv, ES_1 is Nd ES_2 is Pr, and

    aq_solvent_name = 'H2O(L)'
     extractant_name = '(HA)2(org)'
    @@ -170,7 +178,7 @@ and

    Then:

    -

    The exp_data column ordering must be (names do not matter):

    +

    The csvs column ordering must be:

    [h_i, h_eq, z_i, z_eq, Nd_aq_i, Nd_aq_eq, Nd_d_eq, Pr_aq_i, Pr_aq_eq, Pr_d_eq]

    The aqueous speciesArray must be @@ -710,9 +718,7 @@ effect if data_labels is None

    static plot_3d_data(x_data, y_data, z_data, c_data=None, x_label=None, y_label=None, z_label=None, c_label=None)[source]
    -

    THis is for plotting 3d scatter plots. -We suggest use matplotlib's ax.scatter to make 3d plots.

    -
    +
    Parameters
    • x_data -- (list) list of data for x axis

    • @@ -1071,12 +1077,19 @@ about parameters dependant on info_dict