BioSim1D – Reference

Source code

Class BioSim1D

    1D simulations of diffusion and reactions, 
    with an early partial implementation of membranes
    
nameargumentsreturns
__init__self, n_bins=None, chem_data=None, reactions=None

        :param n_bins:      The number of compartments (bins) to use in the simulation
        :param chem_data:   (OPTIONAL) Object of class "ReactionData";
                                if not specified, it will get extracted from the "ReactionDynamics" class
        :param reactions:   (OPTIONAL) Object of class "ReactionDynamics";
                                if not specified, it'll get instantiated here   TODO: maybe no longer necessary
        
nameargumentsreturns
initialize_systemself, n_bins: int, chem_data=None, reactions=NoneNone
        Initialize all concentrations to zero.
        Membranes, if present, need to be set later.

        TODO?: maybe allow optionally passing n_species in lieu of chem_data,
              and let it create and return the "Chemicals" object in that case

        :param n_bins:      The number of compartments (bins) to use in the simulation
        :param chem_data:   (OPTIONAL) Object of class "ReactionData";
                                if not specified, it will get extracted from the "ReactionDynamics" class
        :param reactions:   (OPTIONAL) Object of class "ReactionDynamics";
                                if not specified, it'll get instantiated here
        :return:            None
        
nameargumentsreturns
system_sizeselfint
        Note: the bin numbers will range between 0 and system_size - 1
        :return:    The number of bins in the system
        
nameargumentsreturns
reset_systemselfNone
        WARNING - THIS IS VERY PARTIAL.  TODO: expand, or drop (not sure if really needed anymore)
        :return:
        
nameargumentsreturns
save_systemselfdict
        For now, just return a copy of self.system, with a "frozen" snapshot of the current system state
        TODO: deal with membranes, and anything else needed to later restore the complete system state

        :return:    A dict of (for now a part of) the elements needed to later restore the complete system state
        
nameargumentsreturns
restore_systemself, new_state: dictNone
        Replace (some, for now, of) the various parts the System's internal state.
        For details of the data structure, see the class variable "system"
        TODO: membranes aren't yet managed. System length and global_Dx are currently not modified

        :param new_state:   Numpy array containing the desired new System's internal state
        :return:
        
nameargumentsreturns
replace_systemself, new_state: np.arrayNone
        Replace the System's internal state.
        For details of the data structure, see the class variable "system"
        IMPORTANT: membranes aren't handled. System length and global_Dx are currently not modified

        :param new_state:   Numpy array containing the desired new System's internal state
        :return:
        
nameargumentsreturns
system_snapshotselfpd.DataFrame
        Return a snapshot of all the concentrations of all the species, across all bins
        as a Pandas dataframe
        TODO: make allowance for membranes

        :return:    A Pandas dataframe: each row is a bin,
                        and each column a chemical species
        
nameargumentsreturns
set_uniform_concentrationself, conc: float, species_index=None, species_name=NoneNone
        Assign the given concentration to all the bins of the specified species (identified by its index or name.)
        Any previous values get over-written

        :param conc:            The desired value of chemical concentration for the above species
        :param species_index:   Zero-based index to identify a specific chemical species
        :param species_name:    (OPTIONAL) If provided, it over-rides the value for species_index
        :return:                None
        
nameargumentsreturns
set_all_uniform_concentrationsself, conc_list: Union[list, tuple]None
        Set the concentrations of all species at once, uniformly across all bins
        :param conc_list:   List or tuple of concentration values for each of the chemical species
        :return:            None
        
nameargumentsreturns
set_bin_concself, bin_address: int, conc: float, species_index=None, species_name=None, across_membrane=False, both_sides=FalseNone
        Assign the requested concentration value to the given bin, for the specified chemical species.
        Optionally, set the value for the "alternate bin" ("other side" of the membrane)

        :param bin_address:     The zero-based bin number of the desired compartment
        :param conc:            The desired concentration value to assign to the specified location
        :param species_index:   Zero-based index to identify a specific chemical species
        :param species_name:    (OPTIONAL) If provided, it over-rides the value for species_index
        :param across_membrane: It True, consider the "other side" of the bin, i.e. the portion across the membrane
        :param both_sides:      If True, set the "regular" bin and the "other side" as well
        :return:                None
        
nameargumentsreturns
set_species_concself, conc_list: Union[list, tuple, np.ndarray], species_index=None, species_name=NoneNone
        Assign the requested list of concentration values to all the bins, in bin order, for the single specified species.

        :param conc_list:       A list, tuple or Numpy array with the desired concentration values
                                    to assign to all the bins.
                                    The dimensions must match the system's dimensions.
        :param species_index:   Zero-based index to identify a specific chemical species
        :param species_name:    (OPTIONAL) If provided, it over-rides the value for species_index
        :return:                None
        
nameargumentsreturns
inject_conc_to_binself, bin_address: int, species_index: int, delta_conc: float, zero_clip = FalseNone
        Add the requested concentration to the cell with the given address, for the specified chem species

        :param bin_address:     The zero-based bin number of the desired cell
        :param species_index:   Zero-based index to identify a specific chemical species
        :param delta_conc:      The concentration to add to the specified location
        :param zero_clip:       If True, any requested increment causing a concentration dip below zero, will make the concentration zero;
                                otherwise, an Exception will be raised
        :return:                None
        
nameargumentsreturns
inject_gradientself, species_name, conc_left = 0., conc_right = 0.None
        Add to the concentrations of the specified chemical species a linear gradient spanning across all bins,
        with the indicated values at the endpoints of the system.

        :param species_name:    The name of the chemical species whose concentration we're modifying
        :param conc_left:       The desired amount of concentration to add to the leftmost bin (the start of the gradient)
        :param conc_right:      The desired amount of concentration to add to the rightmost bin (the end of the gradient)
        :return:                None
        
nameargumentsreturns
inject_sine_concself, species_name, frequency, amplitude, bias=0, phase=0, zero_clip = FalseNone
        Add to the concentrations of the specified chemical species a sinusoidal signal across all bins.

        Note:   A sine wave of the form  f(x) = A sin(B x - C)
                has an amplitude of A, a period of 2Pi/B and a right phase shift of C (in radians)

        In Mathematica:  Plot[Sin[B x - C] /. {B -> 2 Pi, C -> 0} , {x, 0, 1}, GridLines -> Automatic]

        :param species_name:    The name of the chemical species whose concentration we're modifying
        :param frequency:       Number of waves along the length of the system
        :param amplitude:       Amplitude of the Sine wave.  Note that peak-to-peak values are double the amplitude
        :param bias:            Amount to be added to all values (akin to "DC bias" in electrical circuits)
        :param phase:           In degrees: phase shift to the RIGHT.  EXAMPLE: 180 to flip the Sine curve
        :param zero_clip:       If True, any requested change causing a concentration dip below zero,
                                will make the concentration zero;
                                otherwise, an Exception will be raised
        :return:                None
        
nameargumentsreturns
inject_bell_curveself, species_name, mean=0.5, sd=0.15, amplitude=1., bias=0None
        Add to the concentrations of the specified chemical species a signal across all bins in the shape of a Bell curve.
        The default values provide bell shape centered in the middle of the system, and fairly spread out
        (but pretty close to zero at the endpoints)

        :param species_name:    The name of the chemical species whose concentration we're modifying
        :param mean:            A value, generally between 0 and 1, indication the position of the mean relative to the system;
                                    if less than 0 or greater than 1, only one tail of the curve will be seen
        :param sd:              Standard deviation, in units of the system length
        :param amplitude:       Amount by which to multiply the signal
        :param bias:            Positive amount to be added to all values (akin to "DC bias" in electrical circuits)
        :return:                None
        
nameargumentsreturns
set_dimensionsself, lengthNone
        Set the overall length of the system.
        Doing so, will permit to convert bin numbers to positional values

        :param length:
        :return:
        
nameargumentsreturns
x_coordself, bin_address
        Return the x coordinate of the middle of the specified bin.
        By convention, for the leftmost bin, it's zero,
        and for the rightmost, it's the overall length of the system
        
nameargumentsreturns
uses_membranesselfbool
        Return True if membranes are part of the system

        :return:
        
nameargumentsreturns
bins_with_membranesself[int]

        :return:
        
nameargumentsreturns
set_membranesself, membrane_pos: Union[List, Tuple]None
        Set the presence of all membranes in the system,
        and optionally specify the fraction of the "A" part of the bin (by default 0.5)

        Initialize the class variables "membranes" and "A_fraction"

        EXAMPLES:   set_membranes([4, 20, 23])
                    set_membranes([4, (20, 0.7), 23])

        IMPORTANT: any previously-set membrane information is lost.

        :param membrane_pos:    A list or tuple of:
                                    1) EITHER indexes of bins that contain membranes
                                    2) OR pairs of bins numbers and fractional values
        :return:                None
        
nameargumentsreturns
assert_valid_binself, bin_address: intNone
        Raise an Exception if the given bin number isn't valid

        :param bin_address:  An integer that ought to be between 0 and (self.n_bins-1), inclusive
        :return:            None
        
nameargumentsreturns
lookup_speciesself, species_index=None, species_name=None, trans_membrane=False, copy=Falsenp.array
        Return the NumPy array of concentration values across the all bins (from left to right)
        for the single specified chemical species.
        NOTE: what is being returned NOT a copy, unless specifically requested

        :param species_index:   The index order of the chemical species of interest
        :param species_name:    (OPTIONAL) If provided, it over-rides the value for species_index
        :param trans_membrane:  If True, consider only the "other side" of the bins, i.e. the portion across the membrane
                                    (it will be zero for bins without membrane)
        :param copy:            If True, an independent numpy array will be returned: a *copy* rather than a view
        :return:                A NumPy 1-D array of concentration values across the bins (from left to right);
                                    the size of the array is the number of bins
        
nameargumentsreturns
bin_concentrationself, bin_address: int, species_index=None, species_name=None, trans_membrane=Falsefloat
        Return the concentration at the requested bin of the specified species

        :param bin_address:     The bin number
        :param species_index:   The index order of the chemical species of interest
        :param species_name:    (OPTIONAL) If provided, it over-rides the value for species_index
        :param trans_membrane:  If True, consider the "other side" of the bin, i.e. the portion across the membrane
        :return:                A concentration value at the indicated bin, for the requested species
        
nameargumentsreturns
bin_snapshotself, bin_address: intdict
        Extract the concentrations of all the chemical species at the specified bin,
        as a dict whose keys are the names of the species
        EXAMPLE:  {'A': 10.0, 'B': 50.0}

        :param bin_address: An integer with the bin number
        :return:            A dict of concentration values; the keys are the names of the species
        
nameargumentsreturns
bin_snapshot_arrayself, bin_address: int, trans_membrane=Falsenp.array
        Extract the concentrations of all the chemical species at the specified bin,
        as a Numpy array in the index order of the species
        EXAMPLE: np.array([10., 50.)]

        :param bin_address:     An integer with the bin number
        :param trans_membrane:  If True, consider the "other side" of the bin, i.e. the portion across the membrane
        :return:                A Numpy array  of concentration values, in the index order of the species
        
nameargumentsreturns
show_system_snapshotselfNone

        :return:    None
        
nameargumentsreturns
describe_stateself, concise=FalseNone
        A simple printout of the state of the system, for now useful only for small systems

        TODO: The goal for ASCII-based printouts involving membranes is something like.  Maybe use Pandas?

           _____________________
        A: |20|18|12|8( )  2| 6|    Diff rate: 0.2 (M: 0.01)
        B: |30| 2|56|4( )3.5|12|    Diff rate: 0.8 (M: 0.3)
           ---------------------
             0  1  2       3  4

        :param concise: If True, only produce a minimalist printout with just the concentration values
        :return:        None
        
nameargumentsreturns
show_membranesself, n_decimals=1str
        A simple-minded early method to visualize where the membranes are.
        Print, and return, a string with a diagram to visualize membranes and the fractions
        of their "left" sides

        EXAMPLE (with 2 membranes on the right part of a 5-bin system):
                _____________________
                |   |   |0.8|   |0.3|
                ---------------------

        :param n_decimals:  Number of decimal places to show in the fractions
        :return:            A string with the character-based diagram;
                            if no membranes were defined, return an empty string
        
nameargumentsreturns
increase_spatial_resolutionself, factor:intNone
        Increase the spatial resolution of the system by cloning and repeating
        each bin, by the specified number of times.
        Replace the System's internal state
        (note that the number of bins will increase by the requested factor)

        EXAMPLE: if the (2-chemicals) system is
                        [[11. 12. 13.]
                         [ 5. 15. 25.]]
                and factor=2, then the result will be
                        [[11. 11. 12. 12. 13. 13.]
                         [ 5.  5. 15. 15. 25. 25.]]

        :param factor:  Number of bins into which to split each bin (replicating their concentration values)
        :return:        None
        
nameargumentsreturns
double_spatial_resolution_linearselfNone
        Increase the spatial resolution of the system by inserting between bins
        their average value (of concentrations, for every chemical species.)
        Replace the System's internal state
        (note that if the number of bins is initially N, it'll become 2N-1).
        If the system has fewer than 2 bins, an Exception will be raised.

        EXAMPLE: if the (2-chemicals) system is
                        [[11. 12. 13.]
                         [ 5. 15. 25.]]
                then the result will be
                        [[11.  11.5 12.  12.5 13. ]
                         [ 5.  10.  15.  20.  25. ]]

        :return:    None
        
nameargumentsreturns
decrease_spatial_resolutionself, factor:intNone

        TODO: eliminate the restriction that the number of bins must be a multiple of factor

        EXAMPLE: if the system is
                        [[10., 20., 30., 40., 50., 60.]
                         [ 2., 8.,   5., 15., 4.,   2.]]
                and factor=2, then the result will be
                        [[15., 35., 55.]
                         [ 5., 10.,  3.]]

        :param factor:
        :return:
        
nameargumentsreturns
smooth_spatial_resolutionselfNone
        EXAMPLE: if the system is
                        [[10., 20., 30.]
                         [ 2., 8.,   4.]]
                then the result will be
                        [[10., 15., 20., 25., 30.]
                         [ 2.,  5.,  8.,  6.,  4.]]

        :return:
        
nameargumentsreturns
is_excessiveself, time_step, diff_rate, delta_xbool
        Use a loose heuristic to determine if the requested time step is too long,
        given the diffusion rate and delta_x.
        This is also based on the "Von Neumann stability analysis"
        (an explanation can be found at: https://www.youtube.com/watch?v=QUiUGNwNNmo)

        :param time_step:
        :param diff_rate:
        :param delta_x:
        :return:
        
nameargumentsreturns
max_time_stepself, diff_rate, delta_xfloat
        Determine a reasonable upper bound on the time step, for the given diffusion rate and delta_x
        This is also based on the "Von Neumann stability analysis"
        (an explanation can be found at: https://www.youtube.com/watch?v=QUiUGNwNNmo)

        :param diff_rate:
        :param delta_x:
        :return:
        
nameargumentsreturns
diffuseself, total_duration=None, time_step=None, n_steps=None, delta_x=1, algorithm=Nonedict
        Uniform-step diffusion, with 2 out of 3 criteria specified:
            1) until reaching, or just exceeding, the desired time duration
            2) using the given time step
            3) carrying out the specified number of steps

        :param total_duration:  The overall time advance (i.e. time_step * n_steps)
        :param time_step:       The size of each time step
        :param n_steps:         The desired number of steps
        :param delta_x:         Distance between consecutive bins
        :param algorithm:          (Optional) code specifying the method to use to solve the diffusion equation.
                                    Currently available options: "5_1_explicit"
        :return:                A dictionary with data about the status of the operation
                                    (for now, just the number of steps run; key: "steps")
        
nameargumentsreturns
diffuse_stepself, time_step, delta_x=1, algorithm=NoneNone
        Diffuse all the species for the given time step, across all bins;
        clear the delta_diffusion array, and then re-compute it from all the species.

        IMPORTANT: the actual system concentrations are NOT changed.

        :param time_step:   Time step over which to carry out the diffusion
                            If too large - as determined by the method is_excessive() - an Exception will be raised
        :param delta_x:     Distance between consecutive bins
        :param algorithm:      (Optional) code specifying the method to use to solve the diffusion equation.
                                Currently available options: "5_1_explicit"
        :return:            None (the array in the class variable "delta_diffusion" gets set)
        
nameargumentsreturns
diffuse_step_single_speciesself, time_step: float, species_index=0, delta_x=1np.array
        Diffuse the specified single chemical species, for the given time step, across all bins,
        and return a 1-D array of the changes in concentration ("Delta concentration")
        for the given species across all bins.

        IMPORTANT: the actual system concentrations are NOT changed.

        We're assuming an isolated environment, with nothing diffusing thru the "walls"

        This approach is based on a "3+1 stencil", aka "Explicit Forward-Time Centered Space".
        EXPLANATION:  https://life123.science/diffusion

        :param time_step:       Delta time over which to carry out this single diffusion step;
                                    if too large, an Exception will be raised.
        :param species_index:   ID (in the form of an integer index) of the chemical species under consideration
        :param delta_x:         Distance between consecutive bins

        :return:                A 1-D Numpy array with the CHANGE in concentration for the given species across all bins
        
nameargumentsreturns
diffuse_step_single_species_5_1_stencilsself, time_step: float, species_index=0, delta_x=1np.array
        Similar to diffuse_step_single_species(), but using a "5+1 stencil";
        i.e. spatial derivatives are turned into finite elements using 5 adjacent bins instead of 3.

        For more info, see diffuse_step_single_species()

        IMPORTANT: the actual system concentrations are NOT changed.

        :param time_step:       Delta time over which to carry out this single diffusion step;
                                    if too large, an Exception will be raised.
        :param species_index:   ID (in the form of an integer index) of the chemical species under consideration
        :param delta_x:         Distance between consecutive bins

        :return:                A Numpy array with the CHANGE in concentration for the given species across all bins
        
nameargumentsreturns
reactself, total_duration=None, time_step=None, n_steps=None, snapshots=NoneNone
        Update the system concentrations as a result of all the reactions in all bins - taking
        the presence of membranes into account, if applicable.

        CAUTION : NO diffusion is performed. Use this function
                  only if you intend to do reactions without diffusion!

        The duration and granularity of the reactions is specified with 2 out of the 3 parameters:
            total_duration, time_step, n_steps

        For each bin, or each membrane-separated side of bin, (or combined group of bins - not currently implemented),
        process all the reactions in it - based on
        the INITIAL concentrations (prior to this reaction step),
        which are used as the basis for all the reactions.

        Optionally, save some data from the individual reaction steps

        TODO: in case of any Exception, the state of the system is still valid, as of the time before this call

        :param total_duration:  The overall time advance (i.e. time_step * n_steps)
        :param time_step:       The size of each time step
        :param n_steps:         The desired number of steps
        :param snapshots:       OPTIONAL dict that may contain any the following keys:
                                        -"frequency"
                                        -"sample_bin" (Required integer; if not present, no snapshots are taken)
                                        -"species" (NOT YET IMPLEMENTED)
                                        -"initial_caption" (default blank. NOT YET IMPLEMENTED)
                                        -"final_caption" (default blank. NOT YET IMPLEMENTED)
                                    If provided, take a system snapshot after running a multiple
                                    of "frequency" run steps (default 1, i.e. at every step.)
                                    EXAMPLE: snapshots={"frequency": 2, "sample_bin": 0}
        :return:                None
        
nameargumentsreturns
reaction_stepself, delta_time: floatNone
        Compute and store the incremental concentration changes in all bins,
        from all reactions,
        for a single time step of duration delta_time.

        The incremental concentration changes are stored in the class variable
        "delta_reactions", which contains a Numpy array that gets cleared and set.

        IMPORTANT: the actual system concentrations are NOT changed.

        For each bin, process all the reactions in it - based on
        the INITIAL concentrations (prior to this reaction step),
        which are used as the basis for all the reactions.

        TODO: parallelize the computation over the separate bins
        TODO: explore looping over reactions first, and then over bins

        :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
        :return:            None (note: the class variable "delta_reactions" gets updated)
        
nameargumentsreturns
react_diffuseself, total_duration=None, time_step=None, n_steps=None, delta_x = 1None
        It expects 2 of the arguments:  total_duration, time_step, n_steps
        Perform a series of reaction and diffusion time steps.

        :param total_duration:  The overall time advance (i.e. time_step * n_steps)
        :param time_step:       The size of each time step
        :param n_steps:         The desired number of steps
        :param delta_x:         Distance between consecutive bins
        :return:                None
        

VISUALIZATION

nameargumentsreturns
visualize_systemself, caption=None, colors=NoneNone
        Visualize the current state of the system as a line plot,
        using plotly

        :param caption: Optional caption to prefix to the default one
        :param colors:  [Not yet used]
        :return:        None
        
nameargumentsreturns
single_species_heatmapself, species_index: int, heatmap_pars: dict, graphic_component, header=NoneNone
        Send to the HTML log, a heatmap representation of the concentrations of
        the single requested species.

        IMPORTANT: must first call GraphicLog.config(), or an Exception will be raised

        :param species_index:       Index identifying the species of interest
        :param heatmap_pars:        A dictionary of parameters for the heatmap
        :param graphic_component:   A string with the name of the graphic module to use.  EXAMPLE: "vue_heatmap_11"
        :param header:              Optional string to display just above the heatmap
        :return:                    None
        
nameargumentsreturns
single_species_line_plotself, species_index: int, plot_pars: dict, graphic_component, header=NoneNone
        Send to the HTML log, a line plot representation of the concentrations of
        the single requested species.  To plot more than 1 species, use line_plot() instead

        IMPORTANT: must first call GraphicLog.config(), or an Exception will be raised

        :param species_index:       Index identifying the species of interest
        :param plot_pars:           A dictionary of parameters for the plot
        :param graphic_component:   A string with the name of the graphic module to use.  EXAMPLE: "vue_curves_3"
        :param header:              Optional string to display just above the plot
        :return:                    None
        
nameargumentsreturns
line_plotself, plot_pars: dict, graphic_component, header=None, color_mapping=NoneNone
        Send to the HTML log, a line plot representation of the concentrations of
        all the chemical species species.
        TODO: offer an option to limit which chemical species to display

        IMPORTANT: must first call GraphicLog.config(), or an Exception will be raised

        :param plot_pars:           A dictionary of parameters (such as "outer_width") for the plot
        :param graphic_component:   A string with the name of the graphic module to use.  EXAMPLE: "vue_curves_4"
        :param header:              OPTIONAL string to display just above the plot
        :param color_mapping:       OPTIONAL dict mapping index numbers to color names or RBG hex values
        :return:                    None
        
nameargumentsreturns
add_snapshotself, data_snapshot: dict, caption =""None
        Preserve some data value (passed as dictionary) in the history, linked to the
        current System Time.

        EXAMPLE:  add_snapshot(data_snapshot = {"concentration_A": 12.5, "concentration_B": 3.7},
                                caption="Just prior to infusion")

        IMPORTANT: if the data is not immutable, then it ought to be cloned first,
                   to preserve it from possible later modifications

        :param data_snapshot:   A dictionary of data to preserve for later use
        :param caption:         Optional caption to attach to this preserved data
        :return:                None
        
nameargumentsreturns
get_historyselfpd.DataFrame
        Retrieve and return a Pandas dataframe with the system history that had been saved
        using add_snapshot()

        :return:        a Pandas dataframe
        
nameargumentsreturns
frequency_analysisself, species_name: str, threshold = 0.001, n_largest = Nonepd.DataFrame
        Return the individual frequencies, and their relative amplitudes,
        in the concentration values of the specified chemical species.
        A Discrete Fourier Transform is used for the computation.

        :param species_name:    The name of the chemical whose concentration we want to analyze
        :param threshold:       Minimum amplitudes of the frequency components to be considered non-zero
                                    (NOTE: these are the raw values returned by the DFT - not the normalized ones.)
        :param n_largest:       If specified, only the rows with the given number of largest amplitudes gets returned
                                    (if there are fewer rows to start with, they all get returned)

        :return:                A Pandas dataframe with 2 columns, "Frequency" and "Relative Amplitude";
                                    amplitudes are relative the the smallest nonzero frequency (which is taken to be 1.0)
                                    EXAMPLE:
                                                   Frequency  Relative Amplitude
                                                0        0.0                 3.0
                                                1        2.0                 1.0
                                                2        4.0                 0.5
                                                3        8.0                 0.2