Working with Models

This guide addresses working programmatically with models. This includes loading models from source, creating new models, modifying and running models, and writing models back to source. The examples in this guide will mostly focus on the mpilot.program.Program class, which is the Python representation of the MPilot model.

Loading a model from source

The from_source() class method will parse a string containing an MPilot model and return a new Program representing the model. For example, the following will open a model file, read the contents, and call from_source, then run the model:

from mpilot.program import Program

with open('model.mpt') as f:
  p = Program.from_source(f.read())
p.run()

from_source takes two optional arguments. The first is libraries, which determines which commands are available to the model. This defaults to EEMS_CSV_LIBRARIES, which contains all commands necessary to run EEMS models based on CSV data. If instead, you want to run an EEMS model which depends on NetCDF data, you could use EEMS_NETCDF_LIBRAIRES instead:

p = Program.from_source(f.read(), libraries=EEMS_NETCDF_LIBRARIES)

You can also use additional, custom libraries; in addition to or instead of the defaults provided by EEMS_CSV_LIBRARIES and EEMS_NETCDF_LIBRARIES. Libraries are referenced by their Python module path, and must be importable. As an example, let’s say you create some custom commands, which can be imported from the myproject.commands.custom module. You could use this in addition to built-in EEMS commands:

p = Program.from_source(
  f.read(),
  libraries=EEMS_CSV_LIBRARIES + ('myproject.commands.custom',)
)

The second optional argument, working_dir, defines the directly used to resolve any relative paths in the model. This argument can be omitted or set to None, but this will result in an exception if any relative paths are encountered. The CLI program sets working_dir to the directory of the model. For example:

model_path = '/path/to/model.mpt'
working_dir = os.path.dirname(model_path)

with open(model_path) as f:
  p = Program.from_source(f.read(), working_dir=working_dir)

Creating a new model

Creating a new, empty model is as simple as creating a new instance of mpilot.program.Program.

from mpilot.program import Program

p = Program()

The Program constructor takes the same arguments (libraries and working_dir) as from_source(), as described in the previous section.

Modifying the model

Whether you have loaded a model from source, or created a new, blank model, you can modify it by adding or removing commands.

Adding commands

Add commands with add_command(). At a minimum, you’ll need to provide a command class, a name for the command result, and arguments to run the command.

You can import the command class directly, or find it by name using find_command_class().

# Import command class
from mpilot.libraries.eems.csv.io import EEMSRead

# Look up by name
p = Program()
EEMSRead = p.find_command_class('EEMSRead')

The command arguments are passed to add_command as a dictionary.

 p.add_command(
   EEMSRead,
   'Var_A',
   {
     'InFileName': 'input.csv',
     'InFieldName': 'Var_A'
   }
)

This is equivalent to the following, in an MPilot command file:

Var_A = EEMSRead(
  InFileName = "input.csv",
  InFieldName = "Var_A"
)

Removing commands

Remove commands from the model by deleting them from the commands property. commands is a dictionary, where the key is the result name.

del p.commands['Var_A']

This will remove a command assigned to the result Var_A (e.g., Var_A = EEMSRead( ... )).

Running the model

Once the model has been created or loaded from source, and modified as needed, run it with run(). This will build a dependency tree and then execute each command in the model.

Creating an MPilot command file

Models can be serialized back to the MPilot Command File format using the to_string() and to_file().

p = Program()
EEMSRead = p.find_command_class('EEMSRead')
p.add_command(EEMSRead, 'Var_A', {'InFileName': 'input.csv', 'InFieldName': 'Var_A'})

# Returns the model as a string
s = p.to_string()

# Var_A = EEMSRead(
#   InFileName = "model.mpt",
#   InFieldName = "Var_A"
# )

# Writes the model to file
p.to_file('model.mpt')

# A file object works, too.
with open('model.mpt') as f:
  p.to_file(f)