Adding a new module - GLOBIO4/GlobioModelPublic GitHub Wiki

Creating a new calculation

In GLOBIO 4 every calculation is programmed as a class. The class should be derived from the base class "CalculationBase". The main method which is executed when calculation is run, is the method "run". This should be the starting point of your own calculation. It is allowed to extend your class with new methods.

To prevent errors when you edit the source code it is preferred to used an editor with Python syntax highlighting, for example PythonWin or PyScripter. In most cases type errors are shown as soon as you type. When using Eclipse with PyDev the Python code is checked for additional errors.

For extending GLOBIO 4 and adding new calculations do the following steps.

Step 1 - Create new GLOBIO_ file

Create a new file in the directory \Calculations. The file name must start with "GLOBIO_" in capital characters.

It is important to use the proper name because the calculation module is located, loaded and executed by using this name.

To save much typing copy an existing calculation file and rename.

Step 2 - Edit the contents of the file

Open the file in an editor and add or modify the following items.

Change the name of the class and add a description. The name of the class should be exactly the same as the name of the file (but without the extension .py).

For example:

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
class GLOBIO_CalcLanduseBiomesMSA(CalculationBase):
  """
  Calculates a raster with the MSA of landuse and biomes.
  """

Add or modify the run method.

For example:

  #-------------------------------------------------------------------------------
  def run(self,*args):
    """
    IN EXTENT Extent
    IN RASTER Landuse
    IN RASTER Biomes
    IN FILE LookupCsv
    OUT RASTER LanduseMSA
    """

The structure of the docstring (starting and ending with """) is important and should contain the definitions of the arguments. They are defined in the same way as the arguments of scenarios and modules and are also used to do type checking and checking input and output.

Add or modify the checking and getting of the run arguments.

For example:

    # Check number of arguments.
    if len(args)<=4:
      Err.raiseGlobioError(Err.InvalidNumberOfArguments2,len(args),self.name)
    
    # Get arguments.
    extent = args[0]
    luRasterName = args[1]
    bioRasterName = args[2]
    lookupFileName = args[3]
    outRasterName = args[4]

Check if the arguments are valid. For output variables add an extra option: True.

For example:

    # Check arguments.
    self.checkExtent(extent)
    self.checkRaster(luRasterName)
    self.checkRaster(bioRasterName)
    self.checkLookup(lookupFileName)
    self.checkRaster(outRasterName,True)

Do some general tasks like getting the minimum cell size, aligning the extent and setting some class members.

For example:

    # Get the minimum cellsize for the output rasters.
    inRasterNames = [luRasterName,bioRasterName]
    cellSize = self.getMinimalCellSize(inRasterNames)
    Log.info("Using cellsize: %s" % cellSize)

    # Align extent.
    extent = RU.alignExtent(extent,cellSize)

    # Set members.
    self.extent = extent
    self.cellSize = cellSize
    self.outDir = os.path.dirname(outRasterName)

Read the input rasters and check their extent and cell size. If necessary resize the extent and resample to the proper cell size.

For example:

    #-----------------------------------------------------------------------------
    # Read the landuse raster and prepare.
    #-----------------------------------------------------------------------------
  
    # Reads the landuse raster and resizes to extent and resamples to cellsize.
    luRaster = self.readAndPrepareInRaster(extent,cellSize,luRasterName,"landuse")

    #-----------------------------------------------------------------------------
    # Read the biomes raster and prepare.
    #-----------------------------------------------------------------------------
  
    # Reads the biomes raster and resizes to extent and resamples to cellsize.
    bioRaster = self.readAndPrepareInRaster(extent,cellSize,bioRasterName,"biomes")

Do your calculations.

For example:

    #-----------------------------------------------------------------------------
    # Lookup the MSA value for landuse and biomes.
    #-----------------------------------------------------------------------------

    # Do lookup.
    lookupFieldTypes = ["I","I","F"]
    lookupMainFieldName = "LANDUSE"
    outRaster = self.reclassUniqueValuesTwoKeys(luRaster,bioRaster,
                                          lookupFileName,lookupFieldTypes,
                                          lookupMainFieldName,np.float32)

Save the output raster and cleanup.

For example:

    # Close and free the input rasters.
    del luRaster
    del bioRaster
 
    # Save the output raster.
    Log.info("Writing %s..." % outRasterName)
    outRaster.write(outRasterName)
           
    # Close and free the output raster.
    del outRaster

Add some test code.

For example:

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
if __name__ == "__main__":
  try:
    indir = r"Q:\Data\Globio4\G_data\pbl\tif"
    lookupdir = r"P:\Project\Globio4\data\Lookup"
    outdir = r"C:\Temp\Globio4\out"
    
    pCalc = GLOBIO_CalcLanduseBiomesMSA()
    ext = GLOB.constants["world"].value
    lu = os.path.join(indir,"glc2000.tif")
    bio = os.path.join(indir,"gmnlct_2010.tif")
    lut = os.path.join(lookupdir,"LanduseBiomesMSA.csv") 
    out = os.path.join(outdir,"LanduseBiomesMSA.tif")
    
    if RU.rasterExists(out):
      RU.rasterDelete(out)
      
    pCalc.run(ext,lu,bio,lut,out)
  except:
    Log.err()

And test the calculation by executing the Python file in for example PythonWin. PyScripter or Eclipse.

Step 3 - Call the GLOBIO calculation in a run configuration file

For example create a module which calls the GLOBIO calculation.

#-------------------------------------------------------------------------------
BEGIN_MODULE CalcLanduseBiomesMSA(IN EXTENT Extent,
                                  IN RASTER Landuse,
                                  IN RASTER Biomes,
                                  IN FILE LanduseBiomesMSALookup,
                                  OUT RASTER LanduseMSA)
  GLOBIO_CalcLanduseBiomesMSA($Extent,$Landuse,$Biomes,
                              $LanduseBiomesMSALookup,$LanduseMsa)
END_MODULE

It is not necessary to do any additional configuration to use your new calculation.

Naming guidelines

When modifying the Python code or creating new Python modules the following naming guidelines can be used:

  • Use <name>RasterName for the full path and name of a raster.
  • Use <name>Raster for the Raster class instance.
  • Use <name>Ras for the raster numpy array.
⚠️ **GitHub.com Fallback** ⚠️