#+options: toc:nil author:nil num:nil
#+number-offset: 5

* Adding Complexity
** Model forcing
ESBMTK realizes model forcing through the @@rst::py:class:`esbmtk.extended_classes.Signal()`@@ class. Once defined, a signal instance can be associated with a @@rst::py:class:`esbmtk.connections.Species2Species()`@@ instance that will then act on the associated connection. This class provides the following keywords to create a signal:

- =square()=, =pyramid()=, =bell()=  These are defined by specifying the signal start time (relative to the model time), its size (as mass) and duration, or as duration and magnitude (see the example below)
- =filename()= a string pointing to a CSV file that specifies the following columns: =Time [yr]=, =Rate/Scale [units]=, =delta value [dimensionless]= The class will attempt to convert the data into the correct model units. This process is however not very robust.

The default is to add the signal to a given connection. It is however also possible to use the signal data as a scaling factor. Signals are cumulative, i.e., complex signals are created by adding one signal to another (i.e., Snew = S1 + S2). Using the P-cycle model from the previous chapter (see =po4_1.py=) we can add a signal by first defining a signal instance, and then associating the instance with a weathering connection instance (this model is available as =po4_2.p4= see https://github.com/uliw/ESBMTK-Examples)
# import the model code from manual-1
#+name:po42_1
#+BEGIN_SRC ipython :noweb yes :tangle po4_2.py :exports none
<<manual-1.org:po41definition()>>
#+END_SRC

#+name:po42_2
#+BEGIN_SRC ipython :tangle po4_2.py
from esbmtk import Signal

Signal(
    name="CR",  # Signal name
    species=M.PO4,  # SpeciesProperties
    start="1 Myrs",
    shape="pyramid",
    duration="1 Myrs",
    mass="45 Pmol",
)

ConnectionProperties(
    source=M.weathering,  # source of flux
    sink=M.S_b,  # target of flux
    rate=F_w,  # rate of flux
    id="river",  # connection id
    signal=M.CR,
    species=[M.PO4],
    ctype="regular",
)
M.run()
#+END_SRC
Note that the =plot()= method accepts the signal object as well. In general, any ESBMTK object that has data that varies with time, can be plotted by the =plot()= method. ESBMTK also provides classes to include
external data  @@rst::py:class:`esbmtk.extended_classes.ExternalData()`@@   as well as classes to mix and match data into the same plot @@rst::py:class:`esbmtk.extended_classes.DataField()`@@. The file =is92a_comparison_plots.py= (see  https://github.com/uliw/ESBMTK-Examples/tree/main/Boudreau/2010) shows a use case. Furthermore, @@rst::py:class:`esbmtk.esbmtk.Model.plot()`@@  returns a tuple with the figure instance, list of axs objects, which allows even more complex figure manipulations (see =steady_state_plots.py= in the same repository).
#+BEGIN_SRC ipython :tangle po4_2.py
M.plot([M.S_b.PO4, M.D_b.PO4, M.CR], fn="po4_2.png")
#  M.save_data()
#+END_SRC

This will result in the following output:
#+attr_org: :width 300
#+attr_rst: :width 400
#+attr_latex: :width 0.5\textwidth
#+name: pcycle
#+name: sig
#+caption: Example output for the =CR= signal above. See =po4_2.py=
#+caption: in the examples directory.
[[./po4_2.png]]

#+BEGIN_SRC org :noweb yes :tangle po4_2_test.py :exports none
<<po42_1>>
<<po42_2>>
#+END_SRC

# define a test function
#+name: testrunner
#+BEGIN_SRC ipython :exports none
# run tests
@pytest.mark.parametrize("test_input, expected", test_values)
def test_values(test_input, expected):
    t = 1e-12
    assert abs(expected) * (1 - t) <= abs(test_input) <= abs(expected) * (1 + t)
#+END_SRC

# define a testcase
#+BEGIN_SRC ipython :noweb yes :tangle test_po4_2.py :exports none
import pytest
import po4_2_test  # import script

M = po4_2_test.M  # get model handle 
tol = 1e-12  # tolerance

test_values = [ # result, reference value
    (M.S_b.PO4.c[-1], 3.3378336265779095e-05),
    (M.D_b.PO4.c[-1], 4.9100854586867445e-05),
]

<<testrunner>>
#+END_SRC


** Working with multiple species
The basic building blocks introduced so far, are sufficient to create a single species model. Adding further species, is straightforward. First one needs to import the species definitions. They than can be simply used by extending the dictionaries and lists used in the previous example.
Using the previous example of a simple P-cycle model, we now express the P-cycling as a function of photosynthetic organic matter (OM) production and remineralization. First, we import the new classes and we additionally load the species definitions for carbon (this code is available as =po4_3.p4= see https://github.com/uliw/ESBMTK-Examples).
#+name: po43_1
#+BEGIN_SRC ipython :tangle po4_3.py
from esbmtk import (
    Model,
    Reservoir,  # the reservoir class
    ConnectionProperties,  # the connection class
    SourceProperties,  # the source class
    SinkProperties,  # sink class
    data_summaries,
    Q_,
)
M = Model(
    stop="6 Myr",  # end time of model
    max_timestep="1 kyr",  # upper limit of time step
    element=["Phosphor", "Carbon"],  # list of species definitions
)

# boundary conditions
F_w_PO4 =  M.set_flux("45 Gmol", "year", M.PO4) # P @280 ppm (Filipelli 2002)
tau = Q_("100 year")  # PO4 residence time in surface boxq
F_b = 0.01  # About 1% of the exported P is buried in the deep ocean
thc = "20*Sv"  # Thermohaline circulation in Sverdrup
Redfield = 106 # C:P

SourceProperties(
    name="weathering",
    species=[M.PO4, M.DIC],
)
SinkProperties(
    name="burial",
    species=[M.PO4, M.DIC],
)
Reservoir(
    name="S_b",
    volume="3E16 m**3",  # surface box volume
    concentration={M.DIC: "0 umol/l", M.PO4: "0 umol/l"},
)
Reservoir(
    name="D_b",
    volume="100E16 m**3",  # deeb box volume
    concentration={M.DIC: "0 umol/l", M.PO4: "0 umol/l"},
)
#+END_SRC
The @@rst::py:class:`esbmtk.connections.ConnectionProperties.()`@@ class definition is equally straightforward, and the following expression will apply the thermohaline downwelling to all species in the =M.S_b= group.
#+name:po43_2
#+BEGIN_SRC ipython :tangle po4_3.py
ConnectionProperties(  # thermohaline downwelling
    source=M.S_b,  # source of flux
    sink=M.D_b,  # target of flux
    ctype="scale_with_concentration",
    scale=thc,
    id="thc_up",
)
ConnectionProperties(  # thermohaline upwelling
    source=M.D_b,  # source of flux
    sink=M.S_b,  # target of flux
    ctype="scale_with_concentration",
    scale=thc,
    id="thc_down",
)
#+END_SRC
It is also possible, to specify individual rates or scales using a dictionary, as in this example that sets two different weathering fluxes:
#+name:po43_3
#+BEGIN_SRC ipython :tangle po4_3.py
ConnectionProperties(
    source=M.weathering,  # source of flux
    sink=M.S_b,  # target of flux
    rate={M.DIC: F_w_PO4 * Redfield, M.PO4: F_w_PO4},  # rate of flux
    ctype="regular",
    id="weathering",  # connection id
)
#+END_SRC
The following code defines primary production and its effects on DIC in the surface and deep box. The example is a bit contrived but demonstrates the principle. Note the use of the =ref_reservoirs= keyword and =Redfield= ratio
#+name:po43_4
#+BEGIN_SRC ipython :tangle po4_3.py
# P-uptake by photosynthesis
ConnectionProperties(  #
    source=M.S_b,  # source of flux
    sink=M.D_b,  # target of flux
    ctype="scale_with_concentration",
    scale=M.S_b.volume / tau,
    id="primary_production",
    species=[M.PO4],  # apply this only to PO4
)
# OM Primary production as a function of P-concentration
ConnectionProperties(  #
    source=M.S_b,  # source of flux
    sink=M.D_b,  # target of flux
    ref_reservoirs=M.S_b.PO4,
    ctype="scale_with_concentration",
    scale=Redfield * M.S_b.volume / tau,
    species=[M.DIC],
    id="OM_production",
)
# P burial 
ConnectionProperties(  #
    source=M.D_b,  # source of flux
    sink=M.burial,  # target of flux
    ctype="scale_with_flux",
    ref_flux=M.flux_summary(filter_by="primary_production",return_list=True)[0],
    scale={M.PO4: F_b, M.DIC: F_b * Redfield},
    id="burial",
)
#+END_SRC
One can now proceed to define the particulate phosphate transport as a function of organic matter export
#+BEGIN_SRC ipython :tangle po4_3.py
M.run()
pl = data_summaries(
    M,  # model instance 
    [M.DIC, M.PO4],  # SpeciesProperties list 
    [M.S_b, M.D_b],  # Reservoir list
)
M.plot(pl, fn="po4_3.png")
#+END_SRC
which results in the below plot. The full code is available in the examples directory as =po4_2.py=
#+attr_org: :width 300
#+attr_rst: :width 400
#+attr_latex: :width 0.5\textwidth
#+name: po4_2
#+caption: Output of =po4_3.py= demonstrating the use of the 
#+caption: =data_summaries()= function
[[./po4_3.png]]
# Build a testcase
#+BEGIN_SRC ipython :noweb yes :tangle po4_3_test.py :exports none
<<po43_1>>
<<po43_2>>
<<po43_3>>
<<po43_4>>
M.run()
#+END_SRC

# create unit test
#+BEGIN_SRC ipython :noweb yes :tangle test_po4_3.py :exports none
import pytest
import po4_3_test  # import script

M = po4_3_test.M  # get model handle 
tol = 1e-12  # tolerance

test_values = [ # result, reference value
    (M.S_b.PO4.c[-1], 1.4999891897165636e-05),
    (M.S_b.DIC.c[-1], 0.0015899885410995674),
    (M.D_b.PO4.c[-1], 2.2058362084399994e-05),
    (M.D_b.DIC.c[-1], 0.002338186380946409),
]

<<testrunner>>
#+END_SRC

** Adding isotopes
 Let's assume that the weathering flux of carbon has \delta^{13}C value of 0 mUr, that photosynthesis fractionates by -28 mUr, and that organic matter burial does not fractionate . These changes require the following changes to the previous model code (the full code is available in the examples directory as =po4_4= at https://github.com/uliw/ESBMTK-Examples):
  1. Isotope ratios require non-zero concentrations to avoid a division by zero,
  2. You need to specify the initial isotope ratio for each reservoir
  3. Sources and Sinks require a flag for each Species that uses isotopes
  4. You need to indicate for each reservoir that =DIC= requires isotope calculations
  5. You  need to specify the isotope ratio of the weathering flux
  6. You  need to specify the fractionation factor during photosynthesis
  7. You need to specify the fractionation factor during burial
#+name: po44_1
#+BEGIN_SRC ipython :tangle po4_4.py :exports none
from esbmtk import (
    Model,
    Reservoir,  # the reservoir class
    ConnectionProperties,  # the connection class
    SourceProperties,  # the source class
    SinkProperties,  # sink class
    data_summaries,
    Q_,
)
M = Model(
    stop="1 Myr",  # end time of model
    max_timestep="1 kyr",  # upper limit of time step
    element=["Phosphor", "Carbon"],  # list of species definitions
)

# boundary conditions
F_w_PO4 =  M.set_flux("45 Gmol", "year", M.PO4) # P @280 ppm (Filipelli 2002)
tau = Q_("100 year")  # PO4 residence time in surface boxq
F_b = 0.01  # About 1% of the exported P is buried in the deep ocean
thc = "20*Sv"  # Thermohaline circulation in Sverdrup
Redfield = 106 # C:P
#+END_SRC

#+name: po44_2
#+BEGIN_SRC ipython :tangle po4_4.py
SourceProperties(
    name="weathering",
    species=[M.PO4, M.DIC],
    isotopes={M.DIC: True},
)
SinkProperties(
    name="burial",
    species=[M.PO4, M.DIC],
    isotopes={M.DIC: True},
)
Reservoir(
    name="S_b",
    volume="3E16 m**3",  # surface box volume
    concentration={M.DIC: "2 umol/l", M.PO4: "0 umol/l"},
    isotopes={M.DIC: True},
    delta={M.DIC: 0},
)
Reservoir(
    name="D_b",
    volume="100E16 m**3",  # deeb box volume
    concentration={M.DIC: "2 umol/l", M.PO4: "0 umol/l"},
    isotopes={M.DIC: True},
    delta={M.DIC: 0},
)
ConnectionProperties(  # thermohaline downwelling
    source=M.S_b,  # source of flux
    sink=M.D_b,  # target of flux
    ctype="scale_with_concentration",
    scale=thc,
    id="thc_up",
)
ConnectionProperties(  # thermohaline upwelling
    source=M.D_b,  # source of flux
    sink=M.S_b,  # target of flux
    ctype="scale_with_concentration",
    scale=thc,
    id="thc_down",
)
ConnectionProperties(  # weathering
    source=M.weathering,  # source of flux
    sink=M.S_b,  # target of flux
    rate={M.DIC: F_w_PO4 * Redfield, M.PO4: F_w_PO4},  # rate of flux
    ctype="regular",
    id="weathering",  # connection id
    delta={M.DIC: 0},
)
ConnectionProperties(  # P-uptake by photosynthesis
    source=M.S_b,  # source of flux
    sink=M.D_b,  # target of flux
    ctype="scale_with_concentration",
    scale=M.S_b.volume / tau,
    id="primary_production",
    species=[M.PO4],  # apply this only to PO4
)
ConnectionProperties(  # OM Primary production as a function of P-concentration
    source=M.S_b,  # source of flux
    sink=M.D_b,  # target of flux
    ref_reservoirs=M.S_b.PO4,
    ctype="scale_with_concentration",
    scale=Redfield * M.S_b.volume / tau,
    species=[M.DIC],
    id="OM_production",
    epsilon=-28,  # mUr
)
ConnectionProperties(  # P burial
    source=M.D_b,  # source of flux
    sink=M.burial,  # target of flux
    ctype="scale_with_flux",
    ref_flux=M.flux_summary(filter_by="primary_production", return_list=True)[0],
    scale={M.PO4: F_b, M.DIC: F_b * Redfield},
    id="burial",
    epsilon={M.DIC: 0},
)
#+END_SRC
Note that in order to enable isotope calculations, we only had to add/modify 8 lines (4, 9, 15, 16, 22, 32, 63, 72).
Running this code and using the @@rst::py:class:`esbmtk.utility_functions.data_summaries()`@@ class to simplify the plotting command
#+name: 
#+name: po44_3
#+BEGIN_SRC ipython :tangle po4_4.py 
M.run()
pl = data_summaries(
    M,  # model instance 
    [M.DIC, M.PO4],  # SpeciesProperties list 
    [M.S_b, M.D_b],  # Reservoir list
)
M.plot(pl, fn="po4_4.png")
#+END_SRC
 results in the following graph. Note that the run-time has been reduced to 1000 years so that the graph does not just show the steady state.
#+attr_org: :width 300
#+attr_rst: :width 400
#+attr_latex: :width 0.5\textwidth
#+name: po4_2_with_isotopes
#+caption: Output of =po4_4.py= Note that the run-time has 
#+caption: been reduced to 1000 years, so that the graph does not just show the steady state.
#+caption: The upper box shows the gradual increase in DIC concentrations and the lower
#+caption: shows the corresponding isotope ratios. The system will achieve isotopic 
#+caption: equilibrium within approximately 2000 years. 
[[./po4_4.png]]

# create testable script
#+BEGIN_SRC ipython :noweb yes :tangle po4_4_test.py :exports none
<<po44_1>>
<<po44_2>>
M.run()
#+END_SRC

# create unit test
#+BEGIN_SRC ipython :noweb yes :tangle test_po4_4.py :exports none
import pytest
import po4_4_test  # import script

M = po4_4_test.M  # get model handle
test_values = [  # result, reference value
    (M.S_b.PO4.c[-1], 1.2921127934553388e-05),
    (M.D_b.PO4.c[-1], 1.899171422689367e-05),
    (M.S_b.DIC.c[-1], 0.0013716395610626638),
    (M.D_b.DIC.c[-1], 0.0020151217080507343),
    (M.S_b.DIC.d[-1], 9.03802309217078),
    (M.D_b.DIC.d[-1], -0.057647879068921326),
]

<<testrunner>>
#+END_SRC


** Using many boxes
Using the ESBMTK classes introduced so far is sufficient to build complex models. However, it is easy to leverage Python syntax to create a few utility functions that help in reducing overly verbose code. The ESBMTK library comes with a few routines that help in this regard. However, they are not part of the core API, are not (yet) well documented and have not seen much testing. The following provides a brief introduction, but it may be useful to study the code for the Boudreau 2010 and LOSCAR-type models in the example directory. All of these make heavy use of the Python dictionary class.

For this function to work correctly, box names need to be specified following this template =Area_depth=, e.g., =A_sb= for the Atlantic surface water box, or =A_ib= for the Atlantic intermediate water box. The actual names, do not matter, but the underscore is used to differentiate between ocean area and depth interval. The following code uses two dictionaries to specify the species and initial conditions for a multi-box model. Both dictionaries are then used as input for a function that creates the actual instances. Note that the meaning and syntax for the geometry list and seawater parameters are explained in the next chapter. Both dictionaries are than passed to the @@rst::py:class:`esbmtk.utility_functions.create_reservoirs()`@@  function to instantiate the respective =Reservoir= objects.
#+BEGIN_SRC ipython
# ud = upper depth datum, ld = lower depth datum, ap = area percentage
# T = Temperature (C), P = Pressure (bar), S = Salinity in PSU 
"""
box_parameters = {  # name: [[ud, ld ap], T, P, S]
        # Atlantic Ocean
        "M.A_sb": {"g": [0, -100, A_ap], "T": 20, "P": 5, "S": 34.7},
        "M.A_ib": {"g": [-100, -1000, A_ap], "T": 10, "P": 100, "S": 34.7},
        "M.A_db": {"g": [-1000, -6000, A_ap], "T": 2, "P": 240, "S": 34.7},
        # Indian Ocean
        "I_sb": {"g": [0, -100, I_ap], "T": 20, "P": 5},
        "I_ib": {"g": [-100, -1000, I_ap], "T": 10, "P": 100, "S": 34.7},
        "I_db": {"g": [-1000, -6000, I_ap], "T": 2, "P": 240, "S": 34.7},
        # Pacific Ocean
        "P_sb": {"g": [0, -100, P_ap], "T": 20, "P": 5, "S": 34.7},
        "P_ib": {"g": [-100, -1000, P_ap], "T": 10, "P": 100, "S": 34.7},
        "P_db": {"g": [-1000, -6000, P_ap], "T": 2, "P": 240, "S": 34.7},
         # High latitude box
        "H_sb": {"g": [0, -250, H_ap], "T": 2, "P": 10, "S": 34.7},
        # Weathering sources
        "Fw": {"ty": "Source", "sp": [M.DIC, M.TA, M.PO4]},
        # Burial Sinks
        "Fb": {"ty": "Sink", "sp": [M.DIC, M.TA, M.PO4]},
    }

initial_conditions= {
        # species: [concentration, Isotopes, delta value]
        M.PO4: [Q_("2.1 * umol/kg"), False, 0],
        M.DIC: [Q_("2.21 mmol/kg"), True, 2],
        M.TA: [Q_("2.31 mmol/kg"), False, 0],
    }

create_reservoirs(box_names, initial_conditions, M)
#+END_SRC


The above code could also be written with explicit initial conditions on a per reservoir/species base and then initialized with the @@rst::py:class:`esbmtk.utility_functions.initialize_reservoirs()`@@ function. The =Boudrea2010.py= example at https://github.com/uliw/ESBMTK-Examples shows a use case for this approach.
#+BEGIN_SRC ipython
box_parameters = {  # name: [[ud, ld ap], T, P, S]
    # Atlantic Ocean
    "M.A_sb": {
        "g": [0, -100, A_ap],
        "T": 20,
        "P": 5,
        "S": 34.7,
        "c": {M.PO4: "2.1 mmol/kg",
              M.DIC: "2.21 mmol/kg",
              M.TA: "2.31 mmol/kg",
              }
species_list = initialize_reservoirs(M, box_parameters)
#+END_SRC
Similarly, we can leverage  Python dictionaries to set up the transport matrix. The dictionary key must use the following template: =boxname_to_boxname@id= where the =id= is used similarly to the connection id in the =Species2Species= and =ConnectionProperties= classes. So to specify thermohaline upwelling from the Atlantic deep water to the Atlantic intermediate water you would use =A_db_to_A_ib@thc=  as the dictionary key, followed by the rate. The following examples define the thermohaline transport in a LOSCAR-type model:
#+BEGIN_SRC ipython
# Conveyor belt
thc = Q_("20*Sv")
ta = 0.2  # upwelling coefficient Atlantic ocean
ti = 0.2  # upwelling coefficient Indian ocean

# Specify the mixing and upwelling terms as dictionary
thx_dict = {  # Conveyor belt
    "H_sb_to_A_db@thc": thc,
    # Upwelling
    "A_db_to_A_ib@thc": ta * thc,
    "I_db_to_I_ib@thc": ti * thc,
    "P_db_to_P_ib@thc": (1 - ta - ti) * thc,
    "A_ib_to_H_sb@thc": thc,
    # Advection
    "A_db_to_I_db@adv": (1 - ta) * thc,
    "I_db_to_P_db@adv": (1 - ta - ti),
    "P_ib_to_I_ib@adv": (1 - ta - ti),
    "I_ib_to_A_ib@adv": (1 - ta) * thc,
}
#+END_SRC
to create the actual connections we need to:
 1. Assemble a list of all species that are affected by thermohaline circulation
 2. Specify the connection type that describes thermohaline transport, i.e., =scale_by_concentration=
 3. Combine #1 & #2 into a dictionary that can be used by the =create_bulk_connections()= function to instantiate the necessary connections.
#+BEGIN_SRC ipython
species_names = list(ic.keys())  # get species list
connection_type = {"ty": "scale_with_concentration", "sp": sl}
connection_dictionary = build_ct_dict(thx_dict, species_names)
create_bulk_connections(connection_dictionary, M, mt="1:1")
#+END_SRC

In the following example, we build the =connection_dictinary= in a more explicit way to define primary production as a function of P upwelling: The first line finds all the upwelling fluxes, and we can then use them as an argument in the =connection_dictionary= definition:
#+BEGIN_SRC ipython
# get all upwelling P fluxes except for the high latitude box
pfluxes = M.flux_summary(filter_by="PO4_mix_up", exclude="H_", return_list=True)

# define export productivity in the high latitude box
PO4_ex = Q_(f"{1.8 * M.H_sb.area/M.PC_ratio} mol/a")

c_dict = {  # Surface box to ib, about 78% is remineralized in the ib
    ("A_sb_to_A_ib@POM_P", "I_sb_to_I_ib@POM_P", "P_sb_to_P_ib@POM_P"): {
        "ty": "scale_with_flux",
        "sc": M.PUE * M.ib_remin,
        "re": pfluxes,
        "sp": M.PO4,
    },  # surface box to deep box
    ("A_sb_to_A_db@POM_P", "I_sb_to_I_db@POM_P", "P_sb_to_P_db@POM_P"): {
        "ty": "scale_with_flux",
        "sc": M.PUE * M.db_remin,
        "re": pfluxes,
        "sp": M.PO4,
    },  # high latitude box to deep ocean boxes POM_P
    ("H_sb_to_A_db@POM_P", "H_sb_to_I_db@POM_P", "H_sb_to_P_db@POM_P"): {
        # here we use a fixed rate following Zeebe's Loscar model
        "ra": [
            PO4_ex * 0.3,
            PO4_ex * 0.3,
            PO4_ex * 0.4,
        ],
        "sp": M.PO4,
        "ty": "Regular",
    },
}
create_bulk_connections(c_dict, M, mt="1:1")
#+END_SRC

In the last example, we use the =gen_dict_entries= function to extract a list of connection keys that can be used in the =connection_dictionary= . The following code finds all connection keys that match the particulate organic phosphor fluxes (=POM_P=) defined in the code above, and to replace them with a connection key that uses =POM_DIC= as id-string. The function returns a list of fluxes and matching keys that can be used to specify new connections. See also =boudreau2010.py= which uses a less complex setup (https://github.com/uliw/ESBMTK-Examples).
#+BEGIN_SRC ipython
keys_POM_DIC, ref_fluxes = gen_dict_entries(M, ref_id="POM_P", target_id="POM_DIC")

c_dict = {
    keys_POM_DIC: {
        "re": ref_fluxes,
        "sp": M.DIC,
        "ty": "scale_with_flux",
        "sc": M.PC_ratio,
        "al": M.OM_frac,
    }
}
create_bulk_connections(c_dict, M, mt="1:1")
#+END_SRC

 
