Metatasks
A metatask is a "task of tasks," an ENVITask that contains two or more ENVITasks linked together to process data. Creating a metatask provides a way to coordinate complex processes by combining several tasks. It consists of a .task
file that you can share with others or run in an enterprise environment using ENVI Server.
This topic provides a simple example of a metatask that includes ISODATA classification and post-classification smoothing. The example will show how you can display a dynamic user interface for entering input and output parameters, as follows:
See the following sections:
Components of a Metatask
A metatask is essentially an ENVITask whose base_class
key is set to ENVIMETATASK
, for example:
{
"name": "ISODATAClassificationWithSmoothing",
"base_class": "ENVIMETATASK",
"display_name": "ISODATA Classification with Smoothing",
"description": "This task performs ISODATA unsupervised classification, followed by post-classification smoothing.",
"schema": "envitask_3.2",
Next are the parameters, which include input parameters that the end-user provides, along with references to output parameters that the metatask will create upon execution. The input parameters in this example are INPUT_RASTER
, NUMBER_OF_CLASSES
, KERNEL_SIZE
, and OUTPUT_RASTER_URI
. The OUTPUT_RASTER
is an output parameter.
In this example, we have chosen to hide additional ISODATA classification parameters to simplify its usage. These are CHANGE_THRESHOLD
and ITERATIONS
.
"parameters": [
{
"name": "INPUT_RASTER",
"type": "ENVIRASTER",
"direction": "INPUT",
"required": true,
"hidden": false,
"description": "Specify a raster on which to perform unsupervised classification.",
"display_name": "Input Raster",
"keyword": "TARGET"
},
{
"name": "NUMBER_OF_CLASSES",
"type": "UINT",
"direction": "INPUT",
"required": false,
"hidden": false,
"default": 5,
"description": "The requested number of classes to generate.",
"display_name": "Number Of Classes",
"keyword": "NUMBER_CLASSES",
"test_overflow": 1,
"test_exact": 0
},
{
"name": "KERNEL_SIZE",
"type": "UINT",
"direction": "INPUT",
"required": false,
"hidden": false,
"default": 3,
"description": "The smooth kernel size, using an odd number (e.g., 3 = 3x3 pixels).",
"display_name": "Kernel Size",
"test_overflow": 1,
"test_exact": 0
},
{
"name": "OUTPUT_RASTER",
"type": "ENVIRASTER",
"direction": "OUTPUT",
"required": true,
"hidden": false,
"description": "This is a reference to the output classification raster of filetype ENVI.",
"display_name": "Output Raster",
"uri_param": "OUTPUT_RASTER_URI",
"keyword": "OUT_FILENAME"
},
{
"name": "OUTPUT_RASTER_URI",
"type": "ENVIURI",
"direction": "INPUT",
"required": false,
"hidden": false,
"description": "Specify a string with the fully-qualified path and filename for OUTPUT_RASTER.",
"display_name": "Output Raster URI",
"keyword": "OUT_FILENAME",
"fold_case": 1,
"is_directory": 0,
"auto_extension": ".dat",
"is_temporary": 1
}
]
Mapping Scheme
Once the parameters have been defined, the next step is to define the input/output/parameter connections between the metatask and its individual tasks within. Add a new parameter with the name
key set to DAG
. Then set the type
key to ENVIMETATASKDAG
; for example:
{
"name": "DAG",
"display_name": "DAG",
"type": "ENVIMETATASKDAG",
"direction": "INPUT",
"required": true,
"description": "This is the graph that describes the metatask.",
"hidden": true,
"default": {
Note: DAG stands for directed acyclic graph, which is a mathematical term for a graph of nodes and edges, where each edge has a single direction and no loops exist. We use this concept in the metatask definition to specify the connections between the tasks that comprise the metatask. Nodes represent child tasks, and the directed edges are dependencies between the tasks, where the output of the independent task is an input to the dependent task.
Within the elements
code block, connect (or map) parameters to one another using the following keys:
external_input
: Use this key to connect parameters of individual tasks to parameters at the metatask level. These are the parameters that an end-user would enter via a dynamic user interface or at the IDL command line.internal_input
: Use this key to connect parameters from one task to another (inside of the metatask).static_input
: Use this key to define a fixed value for a parameter, something that cannot be changed before executing the metatask.
The following diagram shows the example classification metatask that consists of two individual tasks: ISODATAClassification and ClassificationSmoothing.
The definition for the ISODATA classification task has two external inputs, input_raster
and number_of_classes
. It has one static input, iterations
.
The definition for the Classication Smoothing task has:
- Two external inputs,
kernel_size
andoutput_raster_uri
- One internal input, which is connected to the
output_raster
from ISODATA Classification - One output parameter,
output_raster
, which is the final output raster for the metatask
Run the Metatask
Follow these steps to run the metatask:
- Start IDL.
- See the Full Example in JSON Format below. Copy this code into the IDL Editor.
- Save the file as
ISODATAClassificationWithSmoothing.task
in thecustom_code
directory of your ENVI installation:- Windows:
C:\Program Files\INSTALL_DIR\ENVIxx\custom_code
- Linux:
/usr/local/INSTALL_DIR/envixx/custom_code
- Windows:
- Copy and paste the following code into the IDL command line:
; Start the application
e = ENVI()
; Select an input file
file = FILEPATH('qb_boulder_msi', $
SUBDIR=['data'], ROOT_DIR=e.Root_Dir)
raster = e.OpenRaster(file)
; Get the task from the catalog of ENVITasks
task = ENVITask('ISODATAClassificationWithSmoothing')
; Define input parameters
task.INPUT_RASTER = raster
task.NUMBER_OF_CLASSES = 6
; Run the task
task.Execute
; Add the result to the Data Manager
dataColl = e.Data
dataColl.Add, task.OUTPUT_RASTER
; Display the result
view = e.GetView()
layer = view.CreateLayer(task.OUTPUT_RASTER)
view.Zoom, /FULL_EXTENT
Or, use the following code to enter the input and output parameters using a dynamic user interface:
; Start the application
e = ENVI()
; Select an input file
file = FILEPATH('qb_boulder_msi', $
SUBDIR=['data'], ROOT_DIR=e.Root_Dir)
raster = e.OpenRaster(file)
; Get the task from the catalog of ENVITasks
task = ENVITask('ISODATAClassificationWithSmoothing')
; Display the dynamic UI
result = e.UI.SelectTaskParameters(task)
; Run the task
task.Execute
; Add the result to the Data Manager
dataColl = e.Data
dataColl.Add, task.OUTPUT_RASTER
; Display the result
view = e.GetView()
layer = view.CreateLayer(task.OUTPUT_RASTER)
view.Zoom, /FULL_EXTENT
Full Example in JSON Format
{
"name": "ISODATAClassificationWithSmoothing",
"base_class": "ENVIMETATASK",
"display_name": "ISODATA Classification with Smoothing",
"description": "This task performs ISODATA unsupervised classification, followed by post-classification smoothing.",
"schema": "envitask_3.2",
"parameters": [
{
"name": "INPUT_RASTER",
"type": "ENVIRASTER",
"direction": "INPUT",
"required": true,
"hidden": false,
"description": "Specify a raster on which to perform unsupervised classification.",
"display_name": "Input Raster",
"keyword": "TARGET"
},
{
"name": "NUMBER_OF_CLASSES",
"type": "UINT",
"direction": "INPUT",
"required": false,
"hidden": false,
"default": 5,
"description": "The requested number of classes to generate.",
"display_name": "Number Of Classes",
"keyword": "NUMBER_CLASSES",
"test_overflow": 1,
"test_exact": 0
},
{
"name": "KERNEL_SIZE",
"type": "UINT",
"direction": "INPUT",
"required": false,
"hidden": false,
"default": 3,
"description": "The smooth kernel size, using an odd number (e.g., 3 = 3x3 pixels).",
"display_name": "Kernel Size",
"test_overflow": 1,
"test_exact": 0
},
{
"name": "OUTPUT_RASTER",
"type": "ENVIRASTER",
"direction": "OUTPUT",
"required": true,
"hidden": false,
"description": "This is a reference to the output classification raster of filetype ENVI.",
"display_name": "Output Raster",
"uri_param": "OUTPUT_RASTER_URI",
"keyword": "OUT_FILENAME"
},
{
"name": "OUTPUT_RASTER_URI",
"type": "ENVIURI",
"direction": "INPUT",
"required": false,
"hidden": false,
"description": "Specify a string with the fully-qualified path and filename for OUTPUT_RASTER.",
"display_name": "Output Raster URI",
"keyword": "OUT_FILENAME",
"fold_case": 1,
"is_directory": 0,
"auto_extension": ".dat",
"is_temporary": 1
},
{
"name": "DAG",
"display_name": "DAG",
"type": "ENVIMETATASKDAG",
"direction": "INPUT",
"required": true,
"description": "This is the graph that describes the metatask.",
"hidden": true,
"default": {
"ISODATAClassification": {
"name": "ISODATAClassification",
"external_input": {
"input_raster": "INPUT_RASTER",
"number_of_classes": "NUMBER_OF_CLASSES"
},
"static_input": {
"iterations" : 5
}
},
"ClassificationSmoothing" : {
"name": "ClassificationSmoothing",
"external_input": {
"kernel_size": "KERNEL_SIZE",
"output_raster_uri": "OUTPUT_RASTER_URI"
},
"internal_input": {
"input_raster": "ISODATAClassification.OUTPUT_RASTER"
},
"output": {
"output_raster": "OUTPUT_RASTER"
}
}
}
}
]
}