=============================================
Using the Sumatra API within your own scripts
=============================================

Using the ``smt run`` command is quick and convenient, but it does require you to
change the way you launch your simulations.

One way to avoid this is to use the ``sumatra`` package within your own simulation
scripts to perform the record-keeping tasks performed by ``smt run``.

You may also wish to write your own custom script for creating a Sumatra project,
instead of using ``smt init``, but we do not cover this scenario here.
    
We will start with a simple example script, a dummy simulation, that reads a
parameter file, generates some random numbers, and writes some data to file::

    import numpy
    import sys
    
    parameter_file = sys.argv[1]
    parameters = {}
    execfile(parameter_file, parameters) # this way of reading parameters
                                         # is not necessarily recommended
    numpy.random.seed(parameters["seed"])
    distr = getattr(numpy.random, parameters["distr"])
    data = distr(size=parameters["n"])
    
    output_file = "example.dat"
    numpy.savetxt(output_file, data)
    
Let's suppose this script is in a file named ``myscript.py``, and that we have a
parameter file named ``defaults.param``, which contains::

    seed = 65784
    distr = "uniform"
    n = 100
    
Without Sumatra, we would normally run this script using something like::

    $ python myscript.py defaults.param

To run the script using the ``smt`` command line tool, we would use::

    $ smt run --reason="reason for running this simulation" defaults.param
    
(This assumes we have previously used ``smt init`` or ``smt configure`` to specify that
our executable is ``python`` and our main file is ``myscript.py``.)

To benefit from the functionality of Sumatra without having to use ``smt run``, we
have to integrate the steps performed by ``smt run`` into our script.

First, we have to load the simulation project::

    from sumatra.projects import load_simulation_project
    project = load_simulation_project()
    
We're going to want to record the simulation duration, so we import the standard
Python ``time`` module and record the start time::

    import time
    start_time = time.time()
    
We need to slightly modify the procedure for reading parameters. Sumatra stores
the parameters for later use in searching and comparison, so they need to be
transformed into a form Sumatra can use. This is very simple, we just replace
the ``execfile()`` call with a ``build_parameters()`` call::

    from sumatra.parameters import build_parameters
    parameters = build_parameters(parameter_file)
    
Now we create a new ``SimRecord`` object, telling it that the script is the
current file, then we register information about the simulation environment::
    
    sim_record = project.new_record(parameters=parameters,
                                    main_file=__file__,
                                    label="api_example",
                                    reason="reason for running this simulation")
    sim_record.register()

Now comes the main body of the simulation, which is unchanged except that we
take the opportunity to give the output data file a more informative name::

    output_file = "%s.dat" % sim_record.label

At the end of the simulation, we
calculate the simulation duration and search for newly created files::

    sim_record.duration = time.time() - start_time
    sim_record.data_key = sim_record.datastore.find_new_files(sim_record.timestamp)

Now we add this simulation record to the project, and save the project::

    project.add_record(sim_record)
    project.save()
    
Putting this all together::

    import numpy
    import sys
    import time
    from sumatra.projects import load_simulation_project
    from sumatra.parameters import build_parameters
    
    project = load_simulation_project()
    start_time = time.time()
        
    parameter_file = sys.argv[1]
    parameters = build_parameters(parameter_file)
        
    sim_record = project.new_record(parameters=parameters,
                                    main_file=__file__,
                                    label="api_example",
                                    reason="reason for running this simulation")
    sim_record.register()
    
    numpy.random.seed(parameters["seed"])
    distr = getattr(numpy.random, parameters["distr"])
    data = distr(size=parameters["n"])
        
    numpy.savetxt("%s.dat" % sim_record.label, data)
        
    sim_record.duration = time.time() - start_time
    sim_record.data_key = sim_record.datastore.find_new_files(sim_record.timestamp)
    project.add_record(sim_record)

    project.save()

Now you can run the simulation in the original way::

    python myscript.py defaults.param
    
and still have the simulation recorded in your Sumatra project. For such a
simple script and simple run environment there is no advantage to doing it this
way: ``smt run`` is much simpler. However, if you already have a fairly complex run
environment, this provides a straightforward way to integrate Sumatra's
functionality into your existing system.
