Source code for llepe.llepe
-from datetime import datetime
+# 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.
+
+from datetime import datetime
import cantera as ct
import pandas as pd
import numpy as np
@@ -169,7 +174,7 @@
from .utils import set_size
-[docs]class LLEPE:
+[docs]class LLEPE:
r"""
Liquid-Liquid Extraction Parameter estimator
@@ -180,7 +185,7 @@
must be the same order as they appear in the xml, complex_names and
extracted_species_ion_names.
- For example, say in exp_csv_filename's csv, ES_1 is Nd ES_2 is Pr,
+ For example, say in exp_data, ES_1 is Nd ES_2 is Pr,
and
.. code-block:: python
@@ -191,7 +196,7 @@
Then:
- The csvs column ordering must be:
+ 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]
@@ -224,7 +229,7 @@
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.
+ e.g. Nd, Pr, La, etc.
Below is an explanation of the columns.
@@ -261,12 +266,12 @@
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+++
+ (ES_1-ES_N) represent ES ion names e.g. 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)
+ e.g. Nd(H(A)2)3(org), Pr(H(A)2)3(org)
:param phase_names: (list) names of phases in xml file
@@ -281,7 +286,7 @@
:param 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'
+ without '+' e.g. 'Nd+++'->'Nd'
:param aq_solvent_rho: (float) density of solvent (g/L)
@@ -352,7 +357,7 @@
| ES distribution ratio | predicted_dict['{ES}_d_eq'] |
+---------------------------+--------------------------------+
- Replace "{ES}" with extracted species element i.e. Nd, La, etc.
+ Replace "{ES}" with extracted species element e.g. Nd, La, etc.
For measured values, use the same names, but
replace ``predicted_dict`` with ``measured_df``
@@ -526,7 +531,8 @@
self._predicted_dict = None
self.update_predicted_dict()
-[docs] @staticmethod
+ # TODO: move scipy_minimize to optimizers
+[docs] @staticmethod
def scipy_minimize(objective, x_guess, optimizer_kwargs=None):
""" The default optimizer for LLEPE
@@ -560,7 +566,8 @@
est_parameters = res.x
return est_parameters, res.fun
-[docs] def log_mean_squared_error(self, predicted_dict, meas_df):
+ # TODO: move log_mean_squared_error to objectives
+[docs] def log_mean_squared_error(self, predicted_dict, meas_df):
"""Default objective function for LLEPE
Returns the log mean squared error of
@@ -584,14 +591,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
@@ -632,7 +639,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
@@ -640,7 +647,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
@@ -673,7 +680,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
@@ -682,7 +689,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.
@@ -698,14 +705,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
@@ -713,14 +720,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
@@ -728,13 +735,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
@@ -743,14 +750,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.
@@ -758,7 +765,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
@@ -766,7 +773,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
@@ -776,7 +783,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
@@ -784,7 +791,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
@@ -794,14 +801,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
@@ -809,14 +816,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
@@ -824,14 +831,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
@@ -839,7 +846,12 @@
self._diluant_rho = diluant_rho
return None
-[docs] def set_in_moles(self, feed_vol):
+ # 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):
"""Function that initializes mole fractions to input feed_vol
This function is called at initialization
@@ -922,7 +934,9 @@
for extracted_species in extracted_species_list])
extracted_species_charge_sum = np.sum(
extracted_species_charges * extracted_species_moles)
- chlorine_moles = extracted_species_charge_sum + h_plus_moles
+ anion_moles = extracted_species_charge_sum + h_plus_moles
+ # TODO: Replace feed_vol in line 785 and line 787 with
+ # row['oa_ratio']*feed_vol (oa_ratio from restructured DataFrame)
extractant_moles = feed_vol * row['z_i']
extractant_vol = extractant_moles * extractant_mw / extractant_rho
diluant_vol = feed_vol - extractant_vol
@@ -932,7 +946,7 @@
species_moles_aq = [aq_phase_solvent_moles,
h_plus_moles,
hydroxide_ions,
- chlorine_moles]
+ anion_moles]
species_moles_aq.extend(list(extracted_species_moles))
species_moles_org = [extractant_moles, diluant_moles]
species_moles_org.extend(list(complex_moles))
@@ -946,7 +960,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
@@ -954,7 +968,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
@@ -979,7 +993,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
@@ -987,7 +1001,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
@@ -1012,7 +1026,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
@@ -1020,7 +1034,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
@@ -1031,7 +1045,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
@@ -1043,7 +1057,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
@@ -1052,7 +1066,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
@@ -1062,7 +1076,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
@@ -1071,7 +1085,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
@@ -1081,7 +1095,11 @@
self._custom_objects_dict = custom_objects_dict
return None
-[docs] def update_predicted_dict(self,
+ # TODO: Change DataFrame structure 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,
phases_xml_filename=None,
phase_names=None):
"""Function that computes the predicted equilibrium concentrations
@@ -1148,7 +1166,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
@@ -1212,7 +1230,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,
@@ -1255,7 +1273,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):
@@ -1362,7 +1380,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
@@ -1387,7 +1405,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,
@@ -1401,7 +1419,7 @@
Default compared value is {ES_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.
+ experimental data. Can be any column containing "eq" in exp_df e.g.
h_eq, z_eq, {ES}_d_eq, etc.
:param plot_title: (str or boolean)
@@ -1496,7 +1514,9 @@
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')
@@ -1531,13 +1551,13 @@
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.
:param compared_value: (str) Quantity to compare predicted and
- experimental data. Can be any column containing "eq" in exp_df i.e.
+ experimental data. Can be any column containing "eq" in exp_df e.g.
h_eq, z_eq, {ES}_d_eq, etc. default is {ES}_aq_eq
"""
exp_df = self.get_exp_df()
@@ -1571,7 +1591,7 @@
r_2 = (1 - num / den)
return r_2
-[docs] @staticmethod
+[docs] @staticmethod
def plot_3d_data(x_data,
y_data,
z_data,
@@ -1581,6 +1601,8 @@
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
@@ -1631,7 +1653,7 @@
- © Copyright 2020, Titus Quah, Nwike Iloeje
+ © Copyright 2020, UChicago Argonne, LLC.
diff --git a/docs/_build/html/_sources/guide/about.rst.txt b/docs/_build/html/_sources/guide/about.rst.txt
new file mode 100644
index 0000000..dbd1116
--- /dev/null
+++ b/docs/_build/html/_sources/guide/about.rst.txt
@@ -0,0 +1,61 @@
+.. _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 ce1a1f9..e7306d7 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://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git
+ pip install git+https://github.com/ANL-CEEESA/LLEPE.git
Development version
===================
-To contribute to Stable-Baselines, with support for running tests and building the documentation.
+To contribute to LLEPE, with support for running tests and building the documentation.
.. code-block:: bash
- git clone https://xgitlab.cels.anl.gov/summer-2020/parameter-estimation.git && cd parameter-estimation
+ git clone https://github.com/ANL-CEEESA/LLEPE.git
pip install -e .[docs,tests]
diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt
index 9a973a9..a0c905b 100644
--- a/docs/_build/html/_sources/index.rst.txt
+++ b/docs/_build/html/_sources/index.rst.txt
@@ -1,9 +1,8 @@
-.. 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.
+.. 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.
-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
@@ -19,12 +18,13 @@ Error between predicted and experimental data is then minimized.
guide/install
guide/quickstart
+ guide/about
.. toctree::
:maxdepth: 1
:caption: Searchers
- modules/reeps
+ modules/LLEPE
diff --git a/docs/_build/html/_sources/modules/LLEPE.rst.txt b/docs/_build/html/_sources/modules/LLEPE.rst.txt
new file mode 100644
index 0000000..41daa9d
--- /dev/null
+++ b/docs/_build/html/_sources/modules/LLEPE.rst.txt
@@ -0,0 +1,15 @@
+.. _LLEPE:
+
+.. automodule:: llepe
+
+LLEPE
+=====
+
+
+
+Parameters
+----------
+
+.. autoclass:: LLEPE
+ :members:
+ :inherited-members:
\ No newline at end of file
diff --git a/docs/_build/html/_static/jquery-3.5.1.js b/docs/_build/html/_static/jquery-3.5.1.js
new file mode 100644
index 0000000..5093733
--- /dev/null
+++ b/docs/_build/html/_static/jquery-3.5.1.js
@@ -0,0 +1,10872 @@
+/*!
+ * jQuery JavaScript Library v3.5.1
+ * https://jquery.com/
+ *
+ * Includes Sizzle.js
+ * https://sizzlejs.com/
+ *
+ * Copyright JS Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2020-05-04T22:49Z
+ */
+( function( global, factory ) {
+
+ "use strict";
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+// enough that all such attempts are guarded in a try block.
+"use strict";
+
+var arr = [];
+
+var getProto = Object.getPrototypeOf;
+
+var slice = arr.slice;
+
+var flat = arr.flat ? function( array ) {
+ return arr.flat.call( array );
+} : function( array ) {
+ return arr.concat.apply( [], array );
+};
+
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var fnToString = hasOwn.toString;
+
+var ObjectFunctionString = fnToString.call( Object );
+
+var support = {};
+
+var isFunction = function isFunction( obj ) {
+
+ // Support: Chrome <=57, Firefox <=52
+ // In some browsers, typeof returns "function" for HTML