next up previous print clean
Next: Simple parallel jobs Up: Examples Previous: Examples

Creating a flow

Creating a wrapper to a serial code involves creating two objects. The first object is a class that knows the parameters for the program and how to execute it. An example is scale.py which tells how to run a simple scaling program.
import SEP.opt_prog       #handle the parameters for the program
class scale(SEP.opt_prog.options): #inherit from both
  def __init__(self,name="scale"):  #initialization method
    SEP.opt_prog.options.__init__(self,name) #initialize parameters
    self.set_prog("Scale.x")
  def add_doc_params(self):
    """Add the parameters for scaling a dataset"""
    self.add_doc_param("stdout",doc="Output file")
    self.add_doc_param("scale",doc="Scale the dataset by a given value")
The second object will use the above class as in input to a program (SEP.prog.prog) object. The script Scale.py is an example of using the above scale object.
#!/usr/bin/env python
import scale        #the scale object code
import SEP.prog     #the program object code
 
scale=scale.scale("Scale")      #initialize the scale object
program=SEP.prog.prog("Scale.py  ",  #the name of the program for self-doc
   "Scale.py pars ",  #Usage for self-doc
    [scale],  #the components of the program
     ["Scale  using the SEP python library"]) #description doc
program.get_options()        #read the command line arguments
program.prep_run()           #run the program
The script functions the same way as normal SEPlib program. If no arguments are given, self-doc is returned. If an argument that is needed isn't present an error is given (in this case including the self-doc for the parameter).

Things get more interesting when we add a second program. In this case, we will add a simple program that will create a 2-D array with a plane of ones at some location. The script line.py provides the wrapper for the program.

import SEP.opt_prog  #parameters
class line(SEP.opt_prog.options):
  def __init__(self,name="scale"):
    SEP.opt_prog.options.__init__(self,name)
    self.add_prog("Line.x")
  def add_doc_params(self):
    """Add the parameters for scaling a dataset"""
    #add parameters with default values 
    self.add_doc_param("stdout",doc="Output file")
    self.add_doc_param("n1",10,doc="The number of sample first axis ") 
    self.add_doc_param("o1",0.,doc="Origin of the first axis")
    self.add_doc_param("d1",1.,doc="Sampling of the first axis")
    self.add_doc_param("n2",10,doc="The number of sample second axis ")
    self.add_doc_param("o2",0.,doc="Origin of the second axis")
    self.add_doc_param("d2",1.,doc="Sampling of the second axis")
    self.add_doc_param("sample",5,doc="Sample number at which to create line")
We can write a script that combines these two programs. The new program Line_scale.py will first create the array with the program line, then use that output as input to the scaling program. Combining the programs involves three additional steps. First, we will need to create a parameter object, SEP.opt_prog.options, that will be responsible for storing the input and output file information. Second, we will need to inherit from both the line and scale objects. We will change the initialization of these object is to include the new parameter object. We will remove from the documentation the input and output file requests. We will set the input and output file names based on the new parameter object. The final changes involve how to recognize the parameters for the various programs. We will introduce a new dictionary prefixes which maps a prefix to the parameter objects. In the example below, you will now use line_n1 to set the number of samples in the output space.
#!/usr/bin/env python
import scale,line       #import both objects
import SEP.opt_prog
import SEP.prog
 
class main_args(SEP.prog):  #the main parameters
  def __init__(self):
     SEP.opt_prog.options.__init__(self,"MAIN")
     self.add_doc_param("stdout",doc="Output file")
 
class my_line(line.line):  #inherit from the line object
  def __init__(self,main_pars,name):
    line.line.__init__(self,name)  #initialize the line.line structure
    self.main=main_pars   #store the main programs parameter class
  def add_doc_params(self): 
    line.line.add_doc_params(self)  #add the parameters described in line
    self.del_par("stdout")a  #delete the line parameter
  def prep_run(self,restart):
    #set the stdout a temp file based on the stdout of the main program
    self.add_param("stdout","%s.temp"%self.main.param("stdout")) 
    line.line.prep_run(self,restart)
                                                                                
class my_scale(scale.scale):   #inherit the scale calss
  def __init__(self,main_pars,name):
    scale.scale.__init__(self,name) #initialize the scale class
    self.main=main_pars
  def add_doc_params(self):
    scale.scale.add_doc_params(self)
    self.del_par("stdin") ;self.del_par("stdout") #delete in and out
  def prep_run(self,restart):
    #add in out  (in is temp file from line)
    self.add_param("stdin","%s.inter"%self.main.param("stdout"))
    self.add_param("stdout",self.main.param("stdout"))
    scale.scale.prep_run(self)
     
 
main=main_args()   #create the main arguments
line=my_line(main,"Line")  #create the line arguments
scale=my_scale(main,"Scale")  #create the scale arguments
prefixes={}  #prefix dictionary
prefixes["Line"]="line_"  #prefix for all line parameters
prefixes["Scale"]="scale_" #prefix for all scale parameters
program=SEP.prog.prog("Scale_line  ",
   "Scale_line.py pars  outtag= ",
    [line,scale],  #now we have two objects in the flow
     ["Create a line and then scale it  using the SEP python library"],
     prefixes=prefixes  #the prefixes associated with the objects
   )
     
program.get_options() #get the options
program.prep_run()     #run the flow

next up previous print clean
Next: Simple parallel jobs Up: Examples Previous: Examples
Stanford Exploration Project
5/3/2005