Menu

Creating Python scripts Log in to Edit

Anonymous

How to create a python script for saga

Instead of running through the GUI or thecommand line

you can also run modules from python. Compared to the saga cmd interface this has the advantage that you don't have to save all intermediate results, apart from the fact that you can use all the useful features of python to eg iterate over a number of files.

Prior to starting it is very useful to generate the module documentation. You can do this by clicking module libraries in the workspace. This is useful for finding out the identifiers and types used in the different modules.

Study an existing script

Prior to creating our own script we will study an existing script: 01_grid_asc_to_saga.py from this zipfile

In the main function, a short test is made to check whether a filename is supplied. If this is the case the grid_asc2sgrd function is run.

This function applies the different steps which will be needed whenever a saga module is run:

  1. a module library is created
  2. one module of this library is chosen
  3. the parameters of this module are set
  4. the module is run
  5. the module results are saved (or used in a next processing step)

So let's have a look at these steps in our concrete script:

1. Create a module library

    fmlb    = '/usr/lib/saga/libio_grid.so' # Linux
    mlb     = saga_api.CSG_Module_Library()

    print 'load module library: ' + fmlb
    if not mlb.Create(saga_api.CSG_String(fmlb)):
        print '... failed'
        return 0
    print '... success'

2. Choose a module from the library

    m       = mlb.Get_Module(1)

The '1' refers to the ID of module the library, you could also give the name:

m       = mlb.Get_Module('Import ESRI Arc/Info Grid')

The list of modules in a library is shown where you generated your documentation: eg /saga-doc/libio_grid/index.html . You can also try to find it out using saga_cmd. If you run saga_cmd io_grid (on windows) or saga_cmd libio_grid (on linux) you will see the identifiers and names of the modules within a module library.

3) The parameters of the module are set

    p       = m.Get_Parameters()
    p('FILE').Set_Value(fASC)

The parameters are listed in the saga-doc/libio_grid/libio_grid_01.html; you can also find them by running saga_cmd [lib]io_grid 1

4) The module is run

    print m.Get_Name() + ': ' + p('FILE').asString()
    if not m.Execute():
        print '... failed'
        return 0
    print '... success'

5) the module results are saved. This is done to the filename fASC which is first converted to a saga string using the function sag_api.CSG_String().

    print 'save as SAGA grid'
    if p('GRID').asGrid().Save(saga_api.CSG_String(fASC)) == 0:
        print '... failed'
        return 0
    print '... success'

Combining different modules

The script that we built up to now was not very useful. If we would use the command line:

saga_cmd libio_grid 1 -FILE=in.asc -GRID=out.asc

would have done the same.

It gets more interesting if we combine modules. We can do this by putting both functions in one file and combining the two main functions:

if __name__ == '__main__':
    if len( sys.argv ) != 4:
        print 'Usage: asc2morphometry.py <in: elevation.asc> <out: slope> <out: aspect>'
        fDEM    = './test.sgrd'
        fSlope  = './slope'
        fAspect = './aspect'
    else:
        fASC    = sys.argv[1]
        if os.path.split(fASC)[0] == '':
            fASC    = './' + fASC

        grid_asc2sgrd(fASC)
################################
    fDEM    = fASC #(but with .asc) 
        if os.path.split(fDEM)[0] == '':
            fDEM    = './' + fDEM

        fSlope  = sys.argv[2]
        if os.path.split(fSlope)[0] == '':
            fSlope  = './' + fSlope

        fAspect = sys.argv[3]
        if os.path.split(fAspect)[0] == '':
            fAspect = './' + fAspect
        morphometry(fDEM, fSlope, fAspect)

But this is still not very useful and actually identical to running:

saga_cmd libio_grid 1 -FILE=in.asc -GRID=temp.sgrd 
saga_cmd libta_morphometry 0 -ELEVATION=temp.sgrd -SLOPE=slope.sgrd -ASPECT=aspect.sgrd

It still svaes our grid to disc, and then loads it again. Time to really use the advantage of python: we can change our function grid_asc2sgrd to return a pointer to the grid in memory instead of saving it on disc:

def grid_asc2sgrd(fASC):
#Return a pointer to the created sgrd in memory
    print saga_api.SAGA_API_Get_Version()

    fmlb    = '/usr/lib/saga/libio_grid.so' # Linux
    mlb     = saga_api.CSG_Module_Library()

    print 'load module library: ' + fmlb
    if mlb.Create(saga_api.CSG_String(fmlb)) == 0:
        print '... failed'
        return 0
    print '... success'

    m       = mlb.Get_Module(1)
    p       = m.Get_Parameters()
    p('FILE').Set_Value(fASC)

    print m.Get_Name() + ': ' + p('FILE').asString()
    if not m.Execute():
        print '... failed'
        return 0
    print '... success'

    '''return p('GRID').asGrid()'''

Once this is done we can also update our morphometry function to use this grid in memory (pDEM) instead of loading it from disc:

def morphometry(pDEM, fSlope, fAspect):
    print saga_api.SAGA_API_Get_Version()

    fmlb    = '/usr/lib/saga/libta_morphometry.so' # Linux
#    fmlb    = os.environ['SAGA'] + '/bin/saga_vc/modules/ta_morphometry.dll' # Windows
    mlb     = saga_api.CSG_Module_Library()

    print 'load module library: ' + fmlb
    if mlb.Create(saga_api.CSG_String(fmlb)) == 0:
        print '... failed'
        return 0
    print '... success'

    m       = mlb.Get_Module_Grid(0)
    p       = m.Get_Parameters()

    Slope   = saga_api.SG_Create_Grid(pDEM.Get_System())
    Aspect  = saga_api.SG_Create_Grid(pDEM.Get_System())

    m.Get_System().Assign(pDEM.Get_System()) # module needs to use conformant grid system!
    p('ELEVATION').Set_Value(pDEM)
    p('SLOPE')    .Set_Value(Slope)
    p('ASPECT')   .Set_Value(Aspect)

    print 'execute module: ' + m.Get_Name()
    if not m.Execute():
        print '... failed'
        return 0
    print '... success'

    Slope .Set_Name('Slope')
    Aspect.Set_Name('Aspect')
    Slope .Save(saga_api.CSG_String(fSlope))
    Aspect.Save(saga_api.CSG_String(fAspect))

    return 1

Finally also our main function is updated:

if __name__ == '__main__':
    if len( sys.argv ) != 4:
        print 'Usage: asc2morphometry.py <in: elevation.asc> <out: slope> <out: aspect>'
        fDEM    = './test.sgrd'
        fSlope  = './slope'
        fAspect = './aspect'
    else:
        fASC    = sys.argv[1]
        if os.path.split(fASC)[0] == '':
            fASC    = './' + fASC

        fSlope  = sys.argv[2]
        if os.path.split(fSlope)[0] == '':
            fSlope  = './' + fSlope

        fAspect = sys.argv[3]
        if os.path.split(fAspect)[0] == '':
            fAspect = './' + fAspect

    pDEM  = grid_asc2sgrd(fASC)
        morphometry(pDEM, fSlope, fAspect)

Creating your own script for a module

There is an experimental feature which can help you getting started quicker when creating a new script: You can right-click a library in the module tab of the workspace and choose create script file. This will generate a script which already contains the right name of the library and the parameters. The script itself will not run right away: you will have to update the main function and the Call_SAGA_Module arguments