This guide is for versions 1.0 Beta 33+
Static methods for variable time steps
name | arguments | returns |
---|---|---|
norm_A | delta_conc :np.array | float |
Return a measure of system change, based on the average concentration changes of ALL the specified chemicals across a time step, adjusted for the number of chemicals. A square-of-sums computation (the square of an L2 norm) is used. :param delta_conc: A Numpy array with the concentration changes of the chemicals of interest across a time step :return: A measure of change in the concentrations across the simulation step |
name | arguments | returns |
---|---|---|
norm_B | baseline_conc: np.array, delta_conc: np.array | float |
Return a measure of system change, based on the max absolute relative concentration change of all the chemicals across a time step (based on an L infinity norm - but disregarding any baseline concentration that is very close to zero) :param baseline_conc: A Numpy array with the concentration of the chemicals of interest at the start of a simulation time step :param delta_conc: A Numpy array with the concentration changes of the chemicals of interest across a time step :return: A measure of change in the concentrations across the simulation step |
name | arguments | returns |
---|---|---|
norm_C | prev_conc: np.array, baseline_conc: np.array, delta_conc: np.array | float |
Return a measure of system short-period oscillation; larger values might be heralding onset of simulation instability :param prev_conc: A numpy array with the concentration of the chemicals of interest, in the step prior to the current one (i.e. an "archive" value) :param baseline_conc: A Numpy array with the concentration of the chemicals of interest at the start of a simulation time step :param delta_conc: A Numpy array with the concentration changes of the chemicals of interest across a time step :return: |
name | arguments | returns |
---|---|---|
norm_D | prev_conc: np.array, baseline_conc: np.array, delta_conc: np.array | float |
Return a measure of curvature in the concentration vs. time curves; larger values might be heralding onset of simulation instability :param prev_conc: A numpy array with the concentration of the chemicals of interest, in the step prior to the current one (i.e. an "archive" value) :param baseline_conc: A Numpy array with the concentration of the chemicals of interest at the start of a simulation time step :param delta_conc: A Numpy array with the concentration changes of the chemicals of interest across a time step :return: |
Used to raise Exceptions arising from excessively large time steps (that lead to negative concentration values, i.e. "HARD" errors)
Used to raise Exceptions arising from excessively large time steps (that lead to norms regarded as excessive because of user-specified values, i.e. "SOFT" errors)
Used to simulate the dynamics of reactions (in a single compartment.) In the context of Life123, this may be thought of as a "zero-dimensional system" (This class was formerly named "ReactionDynamics")
name | arguments | returns |
---|---|---|
__init__ | self, chem_data=None, names=None, preset="mid" | |
Note: AT MOST 1 of the following 2 arguments can be passed :param chem_data: [OPTIONAL 1] Object of type "ChemData" (with data about the chemicals and their reactions) NOTE: This is the recommended argument; the other 2 options are, or might be, deprecated :param names: [OPTIONAL 2 - MIGHT GET DEPRECATED] A single name, or list or tuple of names, of the chemicals the reactions can be added later, with calls to add_reaction() :param preset: String with code that can be adjusted make the time resolution finer or coarser; it will stay in effect from now on, unless explicitly changed later |
name | arguments | returns |
---|---|---|
set_conc | self, conc: Union[list, tuple, dict], snapshot=True | None |
Set the concentrations of ALL the chemicals at once :param conc: EITHER (1) a list or tuple of concentration values for ALL the registered chemicals, in their index order OR (2) a dict indexed by the chemical names, for some or all of the chemicals EXAMPLE: {"A": 12.4, "B": 0.23, "E": 2.6} Anything not specified will be set to zero Note: any previous values will get over-written :param snapshot:[OPTIONAL] If True (default), add to the history a snapshot of this state being set :return: None |
name | arguments | returns |
---|---|---|
set_single_conc | self, conc, species_index=None, species_name=None, snapshot=True | None |
Set the concentrations of 1 chemical Note: if both species_index and species_name are provided, species_name is used TODO: generate an error instead; and pytest this part :param conc: A non-negative number with the desired concentration value of the chemical specified below. (Any previous value will get over-written) :param species_index: (OPTIONAL) An integer that indexes the chemical of interest (numbering starts at 0) :param species_name: (OPTIONAL) A name for the chemical of interest. If both species_index and species_name are provided, species_name is used At least one of "species_index" and "species_name" must be specified :param snapshot: (OPTIONAL) boolean: if True, add to the history a snapshot of this state being set. Default: True :return: None |
name | arguments | returns |
---|---|---|
get_system_conc | self | np.array |
Retrieve the concentrations of ALL the chemicals as a Numpy array :return: A Numpy array with the concentrations of ALL the chemicals, in their index order EXAMPLE: array([12.3, 4.56, 0.12]) The 0-th chemical has concentration 12.3, and so on... |
name | arguments | returns |
---|---|---|
get_chem_conc | self, name: str | float |
Return the current system concentration of the given chemical, specified by its name. If no chemical by that name exists, an Exception is raised :param name: The name of a chemical species :return: The current system concentration of the above chemical |
name | arguments | returns |
---|---|---|
get_conc_dict | self, species=None, system_data=None | dict |
Retrieve the concentrations of the requested chemicals (by default all), as a dictionary indexed by the chemical's name :param species: (OPTIONAL) list or tuple of names of the chemical species; by default, return all :param system_data: (OPTIONAL) a Numpy array of concentration values, in the same order as the index of the chemical species; by default, use the SYSTEM DATA (which is set and managed by various functions) :return: A dictionary, indexed by chemical name, of the concentration values; EXAMPLE: {"A": 1.2, "D": 4.67} |
name | arguments | returns |
---|---|---|
clear_reactions | self | None |
Get rid of all reactions; start again with "an empty slate" (but still with reference to the same data object about the chemicals) # TODO: maybe offer an option to clear just one reaction, or a list of them # TODO: provide support for "inactivating" reactions :return: None |
name | arguments | returns |
---|---|---|
describe_state | self | None |
Print out various data on the current state of the system :return: None |
name | arguments | returns |
---|---|---|
set_thresholds | self, norm :str, low=None, high=None, abort=None | None |
Create or update a rule based on the given norm (simulation parameters that affect the adaptive variable step sizes.) If no rule with the specified norm was previously set, it will be added. All None values in the arguments are ignored. :param norm: The name of the "norm" (criterion) being used - either a previously-set one or not :param low: The value below which the norm is considered to be good (and the variable steps are being made larger); if None, it doesn't get changed :param high: The value above which the norm is considered to be excessive (and the variable steps get reduced); if None, it doesn't get changed :param abort: The value above which the norm is considered to be dangerously large (and the last variable step gets discarded and back-tracked with a smaller size) ; if None, it doesn't get changed :return: None |
name | arguments | returns |
---|---|---|
delete_thresholds | self, norm :str, low=False, high=False, abort=False | None |
Delete one or more of the threshold values associated to a rule using the specified norm. If none of the threshold values remains in place, the whole rule gets eliminated altogether. Attempting to delete something not present, will raise an Exception :param norm: The name of the "norm" (criterion) being used - for a previously-set rule :param low: If True, this threshold value will get deleted :param high: If True, this threshold value will get deleted :param abort: If True, this threshold value will get deleted :return: None |
name | arguments | returns |
---|---|---|
set_step_factors | self, upshift=None, downshift=None, abort=None, error=None | None |
Over-ride current values for simulation parameters that affect the adaptive variable step sizes. Values not explicitly passed will remain the same. :param upshift: Fraction by which to increase the variable step size :param downshift: Fraction by which to decrease the variable step size :param abort: Fraction by which to decrease the variable step size in cases of step re-do :param error: Fraction by which to decrease the variable step size in cases of error :return: None |
name | arguments | returns |
---|---|---|
set_error_step_factor | self, value | None |
Over-ride the default value for the simulation parameter error_abort_step_factor :param value: Fraction by which to decrease the variable step size in cases of value errors (such as negative concentrations) during a variable step :return: None |
name | arguments | returns |
---|---|---|
show_adaptive_parameters | self | None |
Print out the current values for the adaptive time-step parameters :return: None |
name | arguments | returns |
---|---|---|
use_adaptive_preset | self, preset :str | None |
Lets the user choose a preset to use from now on, unless later explicitly changed, for use in ALL reaction simulations involving adaptive time steps. The preset will affect the degree to which the simulation will be "risk-taker" vs. "risk-averse" about taking larger steps. Note: for more control, use set_thresholds() and set_step_factors() For example, using the "mid" preset is the same as issuing: dynamics.set_thresholds(norm="norm_A", low=0.5, high=0.8, abort=1.44) dynamics.set_thresholds(norm="norm_B", low=0.08, high=0.5, abort=1.5) dynamics.set_step_factors(upshift=1.2, downshift=0.5, abort=0.4, error=0.25) :param preset: String with one of the available preset names; allowed values are (in generally-increasing speed): 'heavy_brakes', 'slower', 'slow', 'mid', 'fast' :return: None |
name | arguments | returns |
---|---|---|
add_reaction | self, **kwargs | int |
Register a new SINGLE chemical reaction, optionally including its kinetic and/or thermodynamic data. All the involved chemicals must be already registered - use add_chemical() if needed. For details, see ChemData.add_reaction() :param kwargs: Any arbitrary named arguments :return: Integer index of the newly-added reaction |
name | arguments | returns |
---|---|---|
describe_reactions | self, **kwargs | None |
Print out a user-friendly plain-text form of ALL the reactions. For details, see ChemData.describe_reactions() :param kwargs: Any arbitrary named arguments :return: None |
name | arguments | returns |
---|---|---|
number_of_reactions | self | int |
Return the number of registered chemical reactions :return: The number of registered chemical reactions |
name | arguments | returns |
---|---|---|
plot_reaction_network | self, graphic_component :str, unpack=False | None |
Send a plot of the network of reactions to the HTML log file, also including a brief summary of all the reactions EXAMPLE of usage: plot_reaction_network("vue_cytoscape_2") :param graphic_component: The name of a Vue component that accepts a "graph_data" argument, an object with the following keys 'structure', 'color_mapping' and 'caption_mapping' For more details, see ChemData.prepare_graph_network() :param unpack: Use True for Vue components that require their data unpacked into individual arguments; False for that accept a single data argument, named "graph_data" :return: None |
name | arguments | returns |
---|---|---|
specify_steps | self, total_duration=None, time_step=None, n_steps=None | (float, int) |
If either the time_step or n_steps is not provided (but at least 1 of them must be present), determine the other one from total_duration Their desired relationship is: total_duration = time_step * n_steps :param total_duration: Float with the overall time advance (i.e. time_step * n_steps) :param time_step: Float with the size of each time step :param n_steps: Integer with the desired number of steps :return: The pair (time_step, n_steps) |
name | arguments | returns |
---|---|---|
single_compartment_react | self, duration=None, target_end_time=None, stop=None, initial_step=None, n_steps=None, max_steps=None, snapshots=None, silent=False, variable_steps=True, explain_variable_steps=None, reaction_duration=None | None |
Perform ALL the reactions in the single compartment - based on the INITIAL concentrations, which are used as the basis for all the reactions. Update the system state and the system time accordingly (object attributes self.system and self.system_time) :param duration: The overall time advance for the reactions (it may be exceeded in case of variable steps) :param reaction_duration: [OBSOLETE OLD NAME for "duration"; being phased out] :param target_end_time: The final time at which to stop the reaction; it may be exceeded in case of variable steps If both `target_end_time` and `duration` are specified, an error will result :param initial_step: The suggested size of the first step (it might be reduced automatically, in case of "hard" errors resulting from overly-large steps) :param stop: Pair of the form (termination_keyword, termination_parameter), to indicate the criterion to use to stop the reaction EXAMPLES: ("conc_below", (chem_name, conc)) Stop when conc first dips below ("conc_above", (chem_name, conc)) Stop when conc first rises above TODO: add more options, such as ("before_time", t) Stop just before the given target time ("after_time", t) Stop just after the given target time ("equilibrium", tolerance) Stop when equilibrium reached :param n_steps: The desired number of steps :param max_steps: (OPTIONAL) Max numbers of steps; if reached, it'll terminate regardless of any other criteria :param snapshots: (OPTIONAL) Dict that may contain any the following keys: -"frequency" (default 1) -"show_intermediates" (default True) -"species" (default None, meaning all species) -"initial_caption" (default blank) -"final_caption" (default blank) If provided, take a system snapshot after running a multiple of "frequency" reaction steps (default 1, i.e. at every step.) EXAMPLE: snapshots={"frequency": 2, "species": ["A", "H"]} :param silent: If True, less output is generated :param variable_steps: If True, the steps sizes will get automatically adjusted, based on thresholds :param explain_variable_steps: If not None, a brief explanation is printed about how the variable step sizes were chosen, when the System time inside that range; only applicable if variable_steps is True :return: None. The object attributes self.system and self.system_time get updated |
name | arguments | returns |
---|---|---|
reaction_step_common | self, delta_time: float, conc_array=None, variable_steps=False, explain_variable_steps=None, step_counter=1 | (np.array, float, float) |
This is the common entry point for both single-compartment reactions, and the reaction part of reaction-diffusions in 1D, 2D and 3D. "Compartments" may or may not correspond to the "bins" of the higher layers; the calling code might have opted to merge some bins into a single "compartment". Using the given concentration data for all the applicable species in a single compartment, do a single reaction time step for ALL the reactions - based on the INITIAL concentrations (prior to this reaction step), which are used as the basis for all the reactions. Return the increment vector for all the chemical species concentrations in the compartment TODO: no longer pass conc_array . Use the object variable self.system instead NOTES: * the actual system concentrations are NOT changed * this method doesn't decide on step sizes - except in case of ("hard" or "soft") aborts, which are followed by repeats with a smaller step. Also, it makes suggestions to the calling module about the next step to best take (whether as a result of an abort, or for other considerations) :param delta_time: The requested time duration of the reaction step :param conc_array: [OPTIONAL]All initial concentrations at the start of the reaction step, as a Numpy array for ALL the chemical species, in their index order. If not provided, self.system is used instead :param variable_steps: If True, the step sizes will get automatically adjusted with an adaptive algorithm :param explain_variable_steps: If not None, a brief explanation is printed about how the variable step sizes were chosen, when the System time inside that range; only applicable if variable_steps is True :param step_counter: :return: The triplet: 1) increment vector for the concentrations of ALL the chemical species, in their index order, as a Numpy array EXAMPLE (for a single-reaction reactant and product with a 3:1 stoichiometry): array([7. , -21.]) TODO: is this really necessary? Maybe update self.system here? 2) time step size actually taken - which might be smaller than the requested one because of reducing the step to avoid negative-concentration errors 3) recommended_next_step : a suggestions to the calling module about the next step to best take |
name | arguments | returns |
---|---|---|
_attempt_reaction_step | self, delta_time, variable_steps, explain_variable_steps, step_counter | (np.array, float) |
Attempt to perform the core reaction step, and then raise an Exception if it needs to be aborted, based on various criteria. If variable_steps is True, determine a new value for the "recommended next step" :param delta_time: The requested time duration of the reaction step :param variable_steps: If True, the step sizes will get automatically adjusted with an adaptive algorithm :param explain_variable_steps: If not None, a brief explanation is printed about how the variable step sizes were chosen, when the System time inside that range; only applicable if variable_steps is True :param step_counter: A pair with a time range inside which to show in the explanations about the variable step sizes; only applicable if explain_variable_steps is True :return: The pair (delta_concentrations, recommended_next_step) |
name | arguments | returns |
---|---|---|
adjust_timestep | self, delta_conc: np.array, baseline_conc=None, prev_conc=None | dict |
Computes some measures of the change of concentrations, from the last step, in the context of the baseline initial concentrations of that same step, and the concentrations in the step before that. Based on the magnitude of the measures, propose a course of action about what to do for the next step. :param delta_conc: A numpy array of changes in concentrations for the chemicals of interest, across a simulation time step (typically, the current step a run in progress) :param baseline_conc: A numpy array of baseline concentration values for those same chemicals, prior to the above change, at the start of a simulation time step :param prev_conc: A numpy array of concentration values for those same chemicals, in the step prior to the current one (i.e. an "archive" value) :return: A dict: "action" - String with the name of the computed recommended action: either "low", "stay", "high" or "abort" "step_factor" - A factor by which to multiply the time step at the next iteration round; if no change is deemed necessary, 1 "norms" - A dict of all the computed norm name/values (any of the norms, except norm_A, may be missing) "applicable_norms" - The name of the norm that triggered the decision; if all norms were involved, it will be "ALL" |
name | arguments | returns |
---|---|---|
display_thresholds | self, rule :dict, value | str |
Examine how the specified value fits relatively to the 'low', 'high', and 'abort' stored in the given rule :param rule: A dict that must contain the key 'norm', and may contain the keys: 'low', 'high', and 'abort' (referring to 3 increasingly-high thresholds) :param value: Either None, or a number to compare to the thresholds :return: A string that visually highlights the relative position of the value relatively to the given thresholds |
name | arguments | returns |
---|---|---|
_reaction_elemental_step | self, delta_time: float, rxn_list=None | np.array |
Using the system concentration data of ALL the chemical species, do the specified SINGLE TIME STEP for ONLY the requested reactions (by default all). All computations are based on the INITIAL concentrations (prior to this reaction step), which are used as the basis for all the reactions (in "forward Euler" approach.) Return the Numpy increment vector for ALL the chemical species concentrations, in their index order (whether involved in these reactions or not) NOTES: - the actual System Concentrations and the System Time (stored in object variables) are NOT changed - if any of the concentrations go negative, an Exception is raised :param delta_time: The time duration of this individual reaction step - assumed to be small enough that the concentration won't vary significantly during this span. :param rxn_list: OPTIONAL list of reactions (specified by their indices) to include in this simulation step ; EXAMPLE: [1, 3, 7] If None, do all the reactions :return: The increment vector for the concentrations of ALL the chemical species (whether involved in the reactions or not), as a Numpy array for all the chemical species, in their index order EXAMPLE (for a single-reaction reactant and product with a 3:1 stoichiometry): array([7. , -21.]) |
name | arguments | returns |
---|---|---|
_reaction_elemental_step_SINGLE_REACTION | self, delta_time: float, increment_vector, rxn_index :int, delta_dict | |
:param delta_time: :param increment_vector: :param rxn_index: The integer index (0-based) to identify the reaction of interest :param delta_dict: :return: |
name | arguments | returns |
---|---|---|
validate_increment | self, delta_conc, baseline_conc: float, rxn_index :int, species_index: int, delta_time | None |
Examine the requested concentration change given by delta_conc (typically, as computed by an ODE solver), relative to the baseline (pre-reaction) value baseline_conc, for the given SINGLE chemical species and SINGLE reaction. If the concentration change would render the concentration negative, raise an Exception (of custom type "ExcessiveTimeStepHard") :param delta_conc: The change in concentration computed by the ode solver (for the specified chemical, in the given reaction) :param baseline_conc: The initial concentration [The remaining arguments are ONLY USED for error printing] :param rxn_index: The index (0-based) to identify the reaction of interest (ONLY USED for error printing) :param species_index: The index (0-based) to identify the chemical species of interest (ONLY USED for error printing) :param delta_time: The time duration of the reaction step (ONLY USED for error printing) :return: None (an Exception is raised if a negative concentration is detected) |
name | arguments | returns |
---|---|---|
compute_all_reaction_deltas | self, delta_time: float, rxn_list=None | dict |
For an explanation of the "reaction delta", see compute_reaction_delta(). Compute the "reaction delta" for all the specified reaction (by default, all.) Return a list with an entry for each reaction, in their index order. For background info: https://life123.science/reactions :param delta_time: The time duration of the reaction step - assumed to be small enough that the concentration won't vary significantly during this span :param rxn_list: OPTIONAL list of reactions (specified by their integer index); if None, do all the reactions. EXAMPLE: [1, 3, 7] :return: A dict of the differences between forward and reverse "conversions" - for explanation, see compute_reaction_delta(). The dict is indexed by the reaction number, and contains as many entries as the number of reactions being investigated |
name | arguments | returns |
---|---|---|
compute_reaction_delta_rate | self, rxn | float |
For the SINGLE given reaction, and the current concentrations of chemicals in the system, compute the reaction's "forward rate" minus its "reverse rate", as defined in https://life123.science/reactions :param rxn: An object of type "Reaction" :return: The differences between the reaction's forward and reverse rates |
name | arguments | returns |
---|---|---|
solve_exactly | self, rxn_index :int, A0 :float, B0 :float, t_arr | (np.array, np.array) |
Return the exact solution of the reaction with the requested index, PROVIDED that it is a 1st Order Reaction of the type A <=> B. Use the given initial conditions, and return the solutions sampled at the specified times. For details, see https://life123.science/reactions :param rxn_index: The integer index (0-based) to identify the reaction of interest :param A0: :param B0: :param t_arr: A Numpy array with the desired times at which the solutions are desired :return: A pair of Numpy arrays |
name | arguments | returns |
---|---|---|
_exact_solution | self, kF, kR, A0, TOT, t_arr | (np.array, np.array) |
Return the exact solution of the 1st Order Reaction A <=> B, with the specified parameters, sampled at the given times. For details, see https://life123.science/reactions :param kF: :param kR: :param A0: :param TOT: :param t_arr: A Numpy array with the desired times at which the solutions are desired :return: A pair of Numpy arrays |
name | arguments | returns |
---|---|---|
set_macromolecules | self, data=None | None |
Specify the macromolecules, and their counts, to be included in the system. The fractional occupancy is set to 0 at all binding sites of all the specified macromolecules. Any previous data gets over-written. Note: to set a single fractional occupancy value, use set_occupancy() :param data: A dict mapping macromolecule names to their counts EXAMPLE: {"M1": 1, "M2": 3, "M3": 1} If any of the requested macromolecules isn't registered, an Exception will be raised If data=None, then the set of registered macromolecules is used, and all their counts are set to 1 :return: None. The object variables self.macro_system and self.macro_system_state get set |
name | arguments | returns |
---|---|---|
set_occupancy | self, macromolecule, site_number: int, fractional_occupancy: float | None |
Set the fractional occupancy at the given binding site of the specified macromolecule, using the requested value. If the specified macromolecule hasn't yet been added to the dynamical system state, automatically add it with count 1 :param macromolecule: Name of a previously-registered macromolecule :param site_number: Integer to identify a binding site on the macromolecule :param fractional_occupancy: A number between 0. and 1., inclusive :return: None |
name | arguments | returns |
---|---|---|
get_occupancy | self, macromolecule, site_number | float |
Get the fractional occupancy at the given binding site of the specified macromolecule. :param macromolecule: Name of a previously-registered macromolecule :param site_number: Integer to identify a binding site on the macromolecule :return: A number between 0. and 1., representing the fractional occupancy |
name | arguments | returns |
---|---|---|
update_occupancy | self | None |
Update the fractional occupancy at all binding sites, based on the current system concentrations of the relevant ligands :return: None |
name | arguments | returns |
---|---|---|
sigmoid | self, conc: float, Kd: float | float |
Return an estimate of fractional occupancy (between 0 and 1) on a particular binding site on a particular macromolecule, from the concentration of the ligand (such as a Transcription Factor) and its affinity to that binding site. A sigmoid curve is expected. Based on fig. 3A of the 2019 paper "Low-Affinity Binding Sites and the Transcription Factor Specificity Paradox in Eukaryotes" (https://doi.org/10.1146/annurev-cellbio-100617-062719): - at extremely low concentration, the occupancy is 0 - when the concentration is 10% of Kd, the occupancy is about 0.1 - when the concentration matches Kd, the occupancy is 1/2 by definition - when the concentration is 10 times Kd, the occupancy is about 0.9 - at concentrations beyond that, the occupancy saturates to 1.0 :param conc: Concentration of the ligand (such as a Transcription Factor), in microMolars :param Kd: Binding-side Affinity, in microMolars :return: Estimated binding-site fractional occupancy : a value between 0. (no occupancy at all during the previous time step) and 1. (continuous occupancy) |
name | arguments | returns |
---|---|---|
logistic | self, x: float, x0 = 0., k = 1. | float |
Compute the value of the Logistic function, in the range (0, 1), at the given point See: https://en.wikipedia.org/wiki/Logistic_function :param x: :param x0: :param k: :return: The value of the Logistic function at the given point x |
name | arguments | returns |
---|---|---|
stoichiometry_checker | self, rxn_index :int, conc_arr_before: np.array, conc_arr_after: np.array | bool |
For the indicated reaction, investigate the change in the concentration of the involved chemicals, to ascertain whether the change is consistent with the reaction's stoichiometry. See https://life123.science/reactions IMPORTANT: this function is currently meant for simulations involving only 1 reaction (TODO: generalize) NOTE: the concentration changes in chemicals not involved in the specified reaction are ignored :param rxn_index: The integer index (0-based) to identify the reaction of interest :param conc_arr_before: Numpy array with the concentrations of ALL the chemicals (whether involved in the reaction or not), in their index order, BEFORE the reaction step :param conc_arr_after: Same as above, but after the reaction TODO: maybe also accept a Panda's dataframe row :return: True if the change in reactant/product concentrations is consistent with the reaction's stoichiometry, or False otherwise |
name | arguments | returns |
---|---|---|
_stoichiometry_checker_from_deltas | self, rxn_index :int, delta_arr: np.array | bool |
Helper function. For the indicated reaction, investigate the change in the concentration of the involved chemicals, to ascertain whether the change is consistent with the reaction's stoichiometry. See https://life123.science/reactions IMPORTANT: this function is currently meant for simulations involving only 1 reaction (TODO: generalize) NOTE: the concentration changes in chemicals not involved in the specified reaction are ignored :param rxn_index: The integer index (0-based) to identify the reaction of interest :param delta_arr: Numpy array of numbers, with the concentrations changes of ALL the chemicals (whether involved in the reaction or not), in their index order, as a result of JUST the reaction of interest :return: True if the change in reactant/product concentrations is consistent with the reaction's stoichiometry, or False otherwise Note: if any of the elements of the passed Numpy array is NaN, then True is returned (because NaN values are indicative of aborted steps; can't invalidate the stoichiometry check because of that) |
name | arguments | returns |
---|---|---|
stoichiometry_checker_entire_run | self | bool |
Verify that the stoichiometry is satisfied in all the reaction steps, using the diagnostic data from an earlier run IMPORTANT: this function is currently meant for simulations involving only 1 reaction (TODO: generalize) :return: True if everything checks out, or False otherwise |
name | arguments | returns |
---|---|---|
_delta_names | self | [str] |
Return a list of strings, with the names of ALL the registered chemicals, in their index order, each prefixed by the string "Delta " EXAMPLE: ["Delta A", "Delta B", "Delta X"] :return: A list of strings |
name | arguments | returns |
---|---|---|
_delta_conc_dict | self, delta_conc_arr: np.ndarray | dict |
Convert a Numpy array into a dict, based on all the registered chemicals. The keys are the chemical names, prefixed by "Delta " :param delta_conc_arr: A Numpy array of "delta concentrations". EXAMPLE: array[1.23, 52.2] :return: A dictionary such as {"Delta A": 1.23, "Delta X": 52.2} |
name | arguments | returns |
---|---|---|
set_diagnostics | self | |
name | arguments | returns |
---|---|---|
unset_diagnostics | self | |
name | arguments | returns |
---|---|---|
save_diagnostic_rxn_data | self, time_step, increment_vector_single_rxn: Union[np.array, None], rxn_index :int, caption="" | None |
Save up diagnostic data for 1 reaction, for a simulation step (by convention, regardless of whether the step is completed or aborted) :param time_step: The duration of the current simulation step :param increment_vector_single_rxn: A Numpy array of size equal to the total number of chemical species, containing the "delta concentrations" for ALL the chemicals (whether involved in the reaction or not) :param rxn_index: The integer index (0-based) to identify the reaction of interest :param caption: OPTIONAL string to describe the snapshot :return: None |
name | arguments | returns |
---|---|---|
comment_diagnostic_rxn_data | self, msg: str | None |
Set the comment field of the last record for EACH of the reaction-specific dataframe :param msg: Value to set the comment field to :return: None |
name | arguments | returns |
---|---|---|
get_diagnostic_rxn_data | self, rxn_index :int, head=None, tail=None, t=None, print_reaction=True | pd.DataFrame |
Return a Pandas dataframe with the diagnostic run data of the requested SINGLE reaction, from the time that the diagnostics were activated by a call to set_diagnostics(). In particular, the dataframe contains the "Delta" values for each of the chemicals involved in the reaction - i.e. the change in their concentrations over the time interval that *STARTS* at the value in the "TIME" column. (So, there'll be no row with the final current System Time) Note: entries are always added, even if an interval run is aborted, and automatically re-done. Optionally, print out a brief description of the reaction. Optionally, limit the dataframe to a specified numbers of rows at the end, or just return one entry corresponding to a specific time (the row with the CLOSEST time to the requested one, which will appear in an extra column called "search_value") :param rxn_index: The integer index (0-based) to identify the reaction of interest TODO: if not specified, show all reactions in turn :param head: (OPTIONAL) Number of records to return, from the start of the diagnostic dataframe. :param tail: (OPTIONAL) Number of records to return, from the end of the diagnostic dataframe. If either the "head" arguments is passed, this argument will get ignored :param t: (OPTIONAL) Individual time to pluck out from the dataframe; the row with closest time will be returned. If this parameter is specified, an extra column - called "search_value" - is inserted at the beginning of the dataframe If either the "head" or the "tail" arguments are passed, this argument will get ignored :param print_reaction: (OPTIONAL) If True (default), concisely print out the requested reaction :return: A Pandas data frame with (all or some of) the diagnostic data of the specified reaction. Columns of the dataframes: 'START_TIME' 'Delta A' 'Delta B'... 'time_step' 'caption' |
name | arguments | returns |
---|---|---|
save_diagnostic_conc_data | self, system_data | None |
To save the diagnostic concentration data during the run, indexed by the current System Time. Note: if an interval run is aborted, by convention NO entry is created here :return: None |
name | arguments | returns |
---|---|---|
get_diagnostic_conc_data | self | pd.DataFrame |
Return the diagnostic concentration data saved during the run. This will be a complete set of simulation steps, even if we only saved part of the history during the run Note: if an interval run is aborted, by convention NO entry is created here :return: A Pandas dataframe, with the columns: 'TIME' 'A' 'B' ... 'caption' where 'A', 'B', ... are all the chemicals |
name | arguments | returns |
---|---|---|
save_diagnostic_decisions_data | self, data, caption="" | None |
Used to save the diagnostic concentration data during the run, indexed by the current System Time. Note: if an interval run is aborted, by convention an entry is STILL created here :return: None |
name | arguments | returns |
---|---|---|
get_diagnostic_decisions_data | self | pd.DataFrame |
Determine and return the diagnostic data about concentration changes at every step - EVEN aborted ones :return: A Pandas dataframe with a "TIME" column, and columns for all the "Delta concentration" values |
name | arguments | returns |
---|---|---|
get_diagnostic_decisions_data_ALT | self | pd.DataFrame |
Determine and return the diagnostic data about concentration changes at every step - EVEN aborted ones TODO: OBSOLETE - BEING PHASED OUT :return: A Pandas dataframe with a "TIME" column, and columns for all the "Delta concentration" values |
name | arguments | returns |
---|---|---|
explain_reactions | self | bool |
Provide a detailed explanation of all the steps of the reactions, from the saved diagnostic data WARNING: Currently designed only for exactly 2 reactions! TODO: generalize to any number of reactions TODO: test and validate usefulness, now that substeps got eliminated TODO: allow arguments to specify the min and max reaction times during which to display the explanatory data :return: True if the diagnostic data is consistent for all the steps of all the reactions, or False otherwise |
name | arguments | returns |
---|---|---|
_explain_reactions_helper | self, active_list, row_baseline, row_list | bool |
Helper function for explain_reactions() :param active_list: :param row_baseline: :param row_list: :return: True is the diagnostic data is consistent for this step, or False otherwise |
name | arguments | returns |
---|---|---|
explain_time_advance | self, return_times=False, silent=False, use_history=False | Union[None, tuple] |
Use the saved-up diagnostic data, to print out details of the timescales of the reaction run If diagnostics weren't enabled ahead of calling this function, an Exception is raised EXAMPLE of output: From time 0 to 0.0304, in 17 FULL steps of 0.0008 (for a grand total of 38 FULL steps) :param return_times: If True, all the critical times (times where the interval steps change) are saved and returned as a list :param silent: If True, nothing gets printed out :param use_history: If True, use the system history in lieu of the diagnostic data; to keep in mind is the fact that the user might only have asked for PART of the history to be saved :return: Depending on the argument return_times, either None, or a pair with 2 lists: 1 - list of time values 2 - list of step sizes (will have one less element than the first list) |
name | arguments | returns |
---|---|---|
_explain_time_advance_helper | self, t_start, t_end, delta_baseline, silent: bool | Union[int, float] |
Using the provided data, about a group of same-size steps, create and print a description of it for the user :param t_start: :param t_end: :param delta_baseline: :param silent: If True, nothing gets printed; otherwise, a line is printed out :return: The corresponding number of FULL steps taken |
name | arguments | returns |
---|---|---|
plot_history | self, chemicals=None, colors=None, title=None, title_prefix=None, xrange=None, ylabel=None, vertical_lines=None, show_intervals=False, show=False | go.Figure |
Using plotly, draw the plots of concentration values over time, based on history data that gets automatically saved when running reactions. Note: if this plot is to be later combined with others, use PlotlyHelper.combine_plots() :param chemicals: (OPTIONAL) List of the names of the chemicals whose concentration changes are to be plotted, or a string with just one name; if None, then display all :param colors: (OPTIONAL) Either a single color (string with standard plotly name, such as "red"), or list of names to use, in order; if None, then use the hardwired defaults :param title: (OPTIONAL) Title for the plot; if None, use default titles that will vary based on the # of reactions; EXAMPLES: "Changes in concentrations for 5 reactions" "Reaction `A <-> 2 B` . Changes in concentrations with time" "Changes in concentration for `2 S <-> U` and `S <-> X`" :param title_prefix: (OPTIONAL) If present, it gets prefixed (followed by ". ") to the title, whether the title is specified by the user or automatically generated :param xrange: (OPTIONAL) list of the form [t_start, t_end], to initially show only a part of the timeline. Note: it's still possible to zoom out, and see the excluded portion :param ylabel: (OPTIONAL) Caption to use for the y-axis. By default, the name in `the chemicals` argument, in square brackets, if only 1 chemical, or "Concentration" if more than 1 (a legend also shown) :param vertical_lines: (OPTIONAL) Ignored if the argument `show_intervals` is specified. TODO: rename add_vertical_lines List or tuple or Numpy array or Pandas series of x-coordinates at which to draw thin vertical dotted gray lines. If the number of vertical line is so large as to overwhelm the plot, only a sample of them is shown. Note that vertical lines, if requested, go into the plot's "layout"; as a result they might not appear if this plot is later combined with another one. :param show_intervals: (OPTIONAL) If True, it over-rides any value passed to the `vertical_lines` argument, and draws thin vertical dotted gray lines at all the x-coords of the data points in the saved history data; also, it adds a comment to the title. :param show: If True, the plot will be shown Note: on JupyterLab, simply returning a plot object (without assigning it to a variable) leads to it being automatically shown :return: A plotly "Figure" object |
name | arguments | returns |
---|---|---|
plot_step_sizes | self, show_intervals=False | None |
Using plotly, draw the plot of the step sizes vs. time (only meaningful when the variable-step option was used). The same scale as plot_curves() will be used. This function requires the diagnostics option to be turned on, prior to running the simulation :param show_intervals: If True, will add to the plot thin vertical dotted gray lines at the time steps :return: None |
name | arguments | returns |
---|---|---|
add_snapshot | self, species=None, caption="", time=None, system_data=None | None |
Preserve some or all the chemical concentrations into the history, linked to the passed time (by default the current System Time), with an optional caption. EXAMPLES: add_snapshot() add_snapshot(species=['A', 'B']), caption="Just prior to infusion") :param species: (OPTIONAL) list of name of the chemical species whose concentrations we want to preserve for later use. If not specified, save all :param caption: (OPTIONAL) caption to attach to this preserved data :param time: (OPTIONAL) time value to attach to the snapshot (default: current System Time) :param system_data: (OPTIONAL) a Numpy array of concentration values, in the same order as the index of the chemical species; by default, use the SYSTEM DATA (which is set and managed by various functions) :return: None |
name | arguments | returns |
---|---|---|
get_history | self, t_start=None, t_end=None, head=None, tail=None, t=None, columns=None | pd.DataFrame |
Retrieve and return a Pandas dataframe with the system history that had been saved using add_snapshot(). Optionally, restrict the result with a start and/or end times, or by limiting to a specified numbers of rows at the end :param t_start: (OPTIONAL) Start time in the "SYSTEM TIME" column. Watch out for roundoff errors! :param t_end: (OPTIONAL) End time. Watch out for roundoff errors! :param head: (OPTIONAL) Number of records to return, from the start of the history dataframe. :param tail: (OPTIONAL) Number of records to consider, from the end of the history dataframe :param t: (OPTIONAL) Individual time to pluck out from the dataframe; the row with closest time will be returned. If this parameter is specified, an extra column - called "search_value" - is inserted at the beginning of the dataframe. If either the "head" or the "tail" arguments are passed, this argument will get ignored :param columns: (OPTIONAL) List of columns to return; if not specified, all are returned. Make sure to include "SYSTEM TIME" in the list, if the time variable needs to be included :return: A Pandas dataframe |
name | arguments | returns |
---|---|---|
get_historical_concentrations | self, row=None, t=None, df=None | np.array |
Typically used to retrieve a system snapshot from its history. Return a Numpy array with ALL the chemical concentrations (in their index order) from one row in the given Pandas data frame (by default, the system history); the row can be identified either by it row number, or by the system time. :param row: (OPTIONAL) Integer with the zero-based row number of the system history (which is a Pandas data frame) :param t: (OPTIONAL) Individual time to pluck out from the dataframe; the row with closest time will be returned. Exactly one of "t" and "row" must be specified :param df: (OPTIONAL) A Pandas data frame with concentration information in columns that have the names of the chemicals (if None, the system history is used) :return: A Numpy array of floats. EXAMPLE: array([200., 40.5]) |
name | arguments | returns |
---|---|---|
is_in_equilibrium | self, rxn_index=None, conc=None, tolerance=1, explain=True, verbose=None | Union[bool, dict] |
Ascertain whether the given concentrations (by default the current System concentrations) are in equilibrium for the specified reactions (by default, for all reactions) :param rxn_index: The integer index (0-based) to identify the reaction of interest; if None, then check all the reactions :param conc: Dict with the concentrations of the species involved in the reaction(s). The keys are the chemical names EXAMPLE: {'A': 23.9, 'B': 36.1} If None, then use the current System concentrations instead :param tolerance: Allowable relative tolerance, as a PERCENTAGE, to establish satisfactory match with expected values :param explain: If True, print out details about the analysis, incl. the formula(s) being used to check the equilibrium EXAMPLES: "([C][D]) / ([A][B])" "[B] / [A]^2" :param verbose: Alternate name for argument `explain` :return: Return True if ALL the reactions are close enough to an equilibrium, as allowed by the requested tolerance; otherwise, return a dict of the form {False: [list of reaction indexes]} for all the reactions that failed the criterion EXAMPLE: {False: [3, 6]} |
name | arguments | returns |
---|---|---|
reaction_in_equilibrium | self, rxn_index :int, conc, tolerance, explain :bool | bool |
Ascertain whether the given concentrations are in equilibrium for the specified SINGLE reaction; return True or False, accordingly. Pathological case: if at least one of the reactants AND at least one of the products have zero concentration, then the reaction is "stuck" - and thus regarded in "equilibrium" :param rxn_index: The integer index (0-based) to identify the reaction of interest :param conc: Dictionary with the concentrations of the species involved in the reaction. The keys are the chemical names EXAMPLE: {'A': 23.9, 'B': 36.1} :param tolerance: Allowable relative tolerance, as a PERCENTAGE, to establish satisfactory match with expected values :param explain: If True, print out the formula being used, as well as the concentrations (reactants, then products) and some other info. EXAMPLES of formulas: "([C][D]) / ([A][B])" "[B] / [A]^2" :return: True if the given reaction is close enough to an equilibrium, as allowed by the requested tolerance |
name | arguments | returns |
---|---|---|
find_equilibrium_conc | self, rxn_index :int | dict |
Determine the equilibrium concentrations that would be reached by the chemicals participating in the specified reaction, given their current concentrations, IN THE ABSENCE of any other reaction. IMPORTANT: currently limited to just aA + bB <-> cC + dD reactions, first-order in all chemicals, (some of terms can be missing) An Exception will be raised in all other cases :param rxn_index: The integer index (0-based) to identify the reaction of interest :return: A dictionary of the equilibrium concentrations of the chemicals involved in the specified reaction EXAMPLE: {'A': 24.0, 'B': 36.0, 'C': 1.8} |
name | arguments | returns |
---|---|---|
estimate_rate_constants | self, t :np.array, reactant_conc :np.array, product_conc :np.array, reactant_name="Reactant", product_name="Product" | |
Estimate the rate constants for a 1-st order reaction of the type A <-> B, given time evolution of [A] and [B] on a grid of time points (don't need to be equally spaced) IMPORTANT : Currently restricted to reactions with a 1:1 stoichiometry between the given reactant and product :param t: A numpy array of time grid points where the other functions are specified :param reactant_conc: :param product_conc: :param reactant_name: :param product_name: :return: A plotly "Figure" object. The estimated rate constants are printed out |
name | arguments | returns |
---|---|---|
reach_threshold | self, chem :str, threshold | Union[float, None] |
:param chem: The name of the chemical of interest :param threshold: A number with the concentration value being sought :return: The time at which the linearly-interpolated concentration of the specified chemical first reaches the given threshold; or None if it never does (in which case a message is printed) |
name | arguments | returns |
---|---|---|
curve_intersect | self, chem1 :str, chem2 :str, t_start, t_end, explain=False | (float, float) |
Find and return the intersection of the concentrations of the chemicals chem1 and chem2, in the time interval [t_start, t_end] If more than one is present, only the first (smallest value of x-coord) one will be returned; so, the specified time interval should be narrow enough to bracket the intersection of interest :param chem1: The name of the 1st chemical of interest :param chem2: The name of the 2nd chemical of interest :param t_start: The start of the time interval being considered :param t_end: The end of the time interval being considered :param explain: [OPTIONAL] If True, print out some details of the computation :return: The pair (time of intersection, common value) ; if not found, a message is printed, and None is returned |
name | arguments | returns |
---|---|---|
curve_intersection | self, chem1, chem2, t_start, t_end | (float, float) |
TODO: OBSOLETE Find and return the intersection of the 2 curves in the columns var1 and var2, in the time interval [t_start, t_end] If there's more than one intersection, only one - in an unpredictable choice - is returned; so, the specified time interval should be narrow enough to avoid that :param chem1: The name of the 1st chemical of interest :param chem2: The name of the 2nd chemical of interest :param t_start: The start of the time interval being considered :param t_end: The end of the time interval being considered :return: The pair (time of intersection, common value) |
name | arguments | returns |
---|---|---|
extract_delta_concentrations | self, df, row_from :int, row_to :int, chem_list: [str] | np.array |
Extract the concentration changes of the specified chemical species from a Pandas dataframe of concentration values EXAMPLE: extract_delta_concentrations(my_dataframe, 7, 8, ['A', 'B']) :param df: A Pandas dataframe of concentration values (it MUST contain columns with the names given in chem_list :param row_from: Row number of the first row of data we're interested in :param row_to: Row number of the last row of data we're interested in :param chem_list: A list of names of chemicals :return: A Numpy array of floats |