Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
ego_script [2011/08/23 16:02]
hermann [Overview]
ego_script [2013/07/31 00:11]
admin
Line 5: Line 5:
 EGO Script is a simple language used to create and edit Dinamica EGO models. The file describing the model using the EGO Script format uses the extension "​.ego"​. EGO Script is a simple language used to create and edit Dinamica EGO models. The file describing the model using the EGO Script format uses the extension "​.ego"​.
  
-They behave just like XML models, so it is possible to edit, load them on the graphical interface and save them again. However, beware that the Dinamica EGO graphical interface can change the model layout and input/​output format based on the currently defined options. More tips on saving EGO scripts on the GUI at the end of this language tutorial.+They behave just like any XML models, so it is possible to edit, load them on the graphical interface and save them again. However, beware that the Dinamica EGO graphical interface can change the model layout and input/​output format based on the currently defined options. More tips on saving EGO scripts on the GUI at the end of this language tutorial.
  
 ===== Overview ===== ===== Overview =====
Line 11: Line 11:
 A simple EGO script model can be seen below: A simple EGO script model can be seen below:
  
-<​file ​cpp ego1.ego>​+<​file ​java ego1.ego>​
 Script {{ Script {{
   // Loads a GeoTiff map.   // Loads a GeoTiff map.
Line 28: Line 28:
 The variables and parameters after the functor name are bound to the functor input ports. Those variables before the operator '':​=''​ are bound to the functor output ports. The variables and parameters after the functor name are bound to the functor input ports. Those variables before the operator '':​=''​ are bound to the functor output ports.
  
-The sequence ''​%%//​%%'' ​mark the beginning of a comment. The comment ​continue ​until the end of line.+The sequence ''​%%//​%%'' ​marks the beginning of a comment. The comment ​continues ​until the end of line.
  
 Here is a slightly more complex example: Here is a slightly more complex example:
  
-<​file ​cpp ego2.ego>​+<​file ​java ego2.ego>​
 Script {{ Script {{
   landscape := LoadCategoricalMap "​c:/​landscape.tif";​   landscape := LoadCategoricalMap "​c:/​landscape.tif";​
Line 44: Line 44:
 It is possible to omit variables representing outputs or ignore them using the variable ''​_''​ (underline). So the previous example can be re-written as shown below: It is possible to omit variables representing outputs or ignore them using the variable ''​_''​ (underline). So the previous example can be re-written as shown below:
  
-<​file ​cpp ego3.ego>​+<​file ​java ego3.ego>​
 Script {{ Script {{
   landscape := LoadCategoricalMap "​c:/​landscape.tif";​   landscape := LoadCategoricalMap "​c:/​landscape.tif";​
Line 64: Line 64:
 It is also possible to use the input and output names to bind variables and parameters. The previous example can be rewritten as It is also possible to use the input and output names to bind variables and parameters. The previous example can be rewritten as
  
-<​file ​cpp ego4.ego>​+<​file ​java ego4.ego>​
 Script {{ Script {{
   { landscape=map } := LoadCategoricalMap { filename="​c:/​landscape.tif"​ };   { landscape=map } := LoadCategoricalMap { filename="​c:/​landscape.tif"​ };
Line 78: Line 78:
 It is possible to freely mix both styles. So you can write the previous input as It is possible to freely mix both styles. So you can write the previous input as
  
-<​file ​cpp ego4.ego>​+<​file ​java ego4.ego>​
 Script {{ Script {{
   landscape := LoadCategoricalMap { filename="​c:/​landscape.tif"​ };   landscape := LoadCategoricalMap { filename="​c:/​landscape.tif"​ };
Line 88: Line 88:
 It is also possible to inline a definition of functor pretty much like nesting function calls in other programming languages: It is also possible to inline a definition of functor pretty much like nesting function calls in other programming languages:
  
-<​file ​cpp ego5.ego>​+<​file ​java ego5.ego>​
 Script {{ Script {{
   { hects=cellAreaInHectares } := CalcAreas (LoadCategoricalMap { filename="​c:/​landscape.tif"​ });   { hects=cellAreaInHectares } := CalcAreas (LoadCategoricalMap { filename="​c:/​landscape.tif"​ });
Line 103: Line 103:
 You can define a single line comment preceding the text with a '​%%//​%%'​. You can define a single line comment preceding the text with a '​%%//​%%'​.
  
-<​code ​cpp>+<​code ​java>
 // This is a single line comment. // This is a single line comment.
 </​code>​ </​code>​
Line 109: Line 109:
 Multi-line comments can be defined surrounding the text with '​%%/​*%%'​ and '​%%*/​%%'​. Multi-line comments can be defined surrounding the text with '​%%/​*%%'​ and '​%%*/​%%'​.
  
-<​code ​cpp>+<​code ​java>
 /* This is a multi-line /* This is a multi-line
 comment */ comment */
Line 116: Line 116:
 It is worth noting that there is a very important difference between both comment styles: multi-line comment style are not preserved if the model is opened using the graphical interface. Usually this is not a problem since multi-line comment can be defined using the '​%%//​%%'​ style. Ex: It is worth noting that there is a very important difference between both comment styles: multi-line comment style are not preserved if the model is opened using the graphical interface. Usually this is not a problem since multi-line comment can be defined using the '​%%//​%%'​ style. Ex:
  
-<​code ​cpp>+<​code ​java>
 // This is a multi-line // This is a multi-line
 // comment // comment
Line 123: Line 123:
 === Brief and Extended Comments === === Brief and Extended Comments ===
  
-FIXME+The sequence ''​===''​ is used to separate the brief and extended comments of a functor. 
 + 
 +<code java> 
 +// Generate the initial '​seed'​  
 +// 
 +// === 
 +// Living cells are represented by 1 and dead cells by 0  
 +</​code>​
  
 ==== Functor Input/​Outputs ==== ==== Functor Input/​Outputs ====
Line 155: Line 162:
 ==== Properties ==== ==== Properties ====
  
-FIXME+Properties can be represented using two different syntaxes. The property definition is always relative to the next functor defined in the model.
  
-==== Expression Calculation Syntax ====+The first syntax represents properties using comments. 
 +<code java> 
 +/** name value */ 
 +</​code>​
  
-FIXME+The other syntax uses the special symbol @. 
 + 
 +<code java> 
 +@name = value 
 +</​code>​ 
 + 
 +Property names must start with a letter or '​_'​ followed by letters, ​ '​_'​ and '​.'​. Property values can include any character (including blanks). Property values including line breaks must be surrounded by '"'​. 
 + 
 +Examples of properties can be seen below: 
 + 
 +<code java> 
 +/** 
 +  dff.date = Wed Oct 21 18:19:21 2009 
 +  dff.version = 1.4.0.20090812 
 +  metadata.author = Dinamica Team 
 +  metadata.description = Calculate the largest patch index of different categories. 
 +  metadata.notes = "The model input is a map where the non-null values identify the patches. 
 + 
 +The output is a table containing the largest patch index per category."​ 
 +  metadata.organization = CSR / UFMG 
 +  metadata.showproperties = yes 
 +  metadata.title = Calc Largest Patch Index 
 +  metadata.version = 1.0 
 +*/ 
 +</​code>​ 
 + 
 +<code java> 
 +@alias = Largest Patch Area 
 +@collapsed = yes 
 +</​code>​ 
 + 
 +Note the declaration of a "​metadata.notes"​ above using line breaks. 
 + 
 +The syntax ''​@property = value''​ forces the expansion of the property name if it represents a special property. 
 + 
 +Some properties are used internally by Dinamica to store special information about functors and the model script. The list of special properties can be found below: 
 + 
 +=== Functor Properties === 
 + 
 +^ Alias ^ Full Name ^ Description ^ Possible Values ^ 
 +| alias | dff.functor.alias | The alias used to represent the functor in the model | Any string | 
 +| inline | dff.functor.inline | Used to indicate that functor definition must not be inlined | yes/no or true/false |  
 +| comment | dff.functor.comment | The functor comment | Any string | 
 +| collapsed | dff.container.collapsed | Used to indicate that the contained must appear closed in the graphical interface | yes/no or true/false |  
 + 
 +=== Script Properties === 
 + 
 +^ Full Name ^ Description ^ Possible Values ^ 
 +| dff.date | The date when the model was written for the last time | Any string | 
 +| dff.version | The version of Dinamica EGO used to update the model the last time | Any string | 
 +| metadata.title | The model title | Any string | 
 +| metadata.version | The model version | Any string | 
 +| metadata.author | The list of model authors | Any string | 
 +| metadata.organization | The list of organization of each model author | Any string |  
 +| metadata.description | The model description | Any string | 
 +| metadata.keywords | The list of model keywords | Any string | 
 +| metadata.notes | The model notes | Any string | 
 +| metadata.showproperties | Flag indicating if the property window should be displayed upon opening the model | yes/no or true/false | 
 + 
 +Comments are a special property that uses a different syntax. Internally, they are expanded to their equivalent property format. 
 + 
 +The syntax 
 + 
 +<code java> 
 +// The input map.  
 +// 
 +// Non-null values identify the patches.  
 +</​code>​ 
 + 
 +and 
 + 
 +<code java> 
 +@comment = "The input map.  
 + 
 +Non-null values identify the patches."​ 
 +</​code>​ 
 + 
 +are equivalent. 
 + 
 +If used before the "​Script"​ keyword, the <​nowiki>//</​nowiki>​ syntax is converted into a "​metadata.title"​ and assigned to the model. 
 + 
 + 
 +==== Expression Calculation Syntax ====
  
-/* +Since Dinamica EGO version 2.0, expressions in EGO Script can be represented using an additional special syntax. The example below illustrates:​
-''​sigil''​ é o nome desses simbolos engraçados ao lado das variáveis.+
  
-<​code ​cpp>+<​code ​java>
 if #random <= ($mean - $min) / ($max - $min) then if #random <= ($mean - $min) / ($max - $min) then
    $min + sqrt(#​random * ($max - $min) * ($mean - $min))    $min + sqrt(#​random * ($max - $min) * ($mean - $min))
Line 171: Line 262:
 </​code>​ </​code>​
  
-**Pros**: +The symbols prefixing the variable names are called sigils. The represents maps, $ represents values and represents tables((The sigils are used by some popular programming languages like Perl, PHP e Ruby [[wp>Sigil_%28computer_programming%29#​Language_comparison]]))
-  * Simples de implementar (é bem direta a implementação) +
-  * É facil ver a que uma variável se refere só olhando o sigil que está sendo usado: em princípio, ​representaria mapa, $ representaria valor numérico e %representaria tabela. +
-  * Usado por algums linguagens populares como Perl, PHP e Ruby (http://​en.wikipedia.org/​wiki/​Sigil_%28computer_programming%29#​Language_comparison) +
-  * É facil manter compatibilitada com a sintaxe usada hoje: i1, v1, t1 etc, sem o sigil, ainda seria aceito para compatibilidade com os modelos que já existem. +
-  * Não cria conflitos com nomes existentes. Como exemplo, "​rand",​ "​line"​ e "​column"​ são nomes de variáveis especiais que são usados hoje nos cálculos de mapa. Usando o sigil a expressão "rand + #rand" é a soma de um valor alteatorio com um mapa cujo nome na expressão é "​rand"​.+
  
-**Cons**: +The use of sigils has some advantages including making easy to determine the data type represented by the variables. They also prevent clashes between special names like "​rand"​, "line" ​and "​column"​ and the user defined ones. ((Using sigils the expression "rand + #rand" is the sum of a random value with a the value of map named "​rand"​))
-  * Feia +
-  * O mesmo nome pode ser usado para representar mapatabela e valor tal como em "%var[? #var] + $var" (Isso poderia ser visto como uma vantagem, mas fica confuso).+
  
-=== Exemplos ​===+=== Examples ​===
  
-Uma extensão no formato EGO usado hoje seria:+The example below represents a fragment of a real model using the original syntax:
  
-(parte de um exemplo real hoje) +<​code ​java>
- +
-<​code ​cpp>+
     patches := LoadCategoricalMap "​../​originals/​landscape.ers"​ .no .no 0 0 .none;     patches := LoadCategoricalMap "​../​originals/​landscape.ers"​ .no .no 0 0 .none;
     // ...     // ...
Line 205: Line 287:
 </​code>​ </​code>​
  
-(modelo modificado com uma sintaxe adicional que passaria a ser válida)+The model modified to use the special expression calculation syntax can be seen below:
  
-<​code ​cpp>+<​code ​java>
     patches := LoadCategoricalMap "​../​originals/​landscape.ers"​ .no .no 0 0 .none;     patches := LoadCategoricalMap "​../​originals/​landscape.ers"​ .no .no 0 0 .none;
     // ...     // ...
Line 214: Line 296:
     // Isolate the patches of a single category. ​     // Isolate the patches of a single category. ​
     @collapsed = yes     @collapsed = yes
-    singleCategoryPatches := #[ if #patches = $currenteCategoryId then 1 else null ];+    singleCategoryPatches := #[ if #patches = $currenteCategoryId then 1 else null ] .uint8 0 .no;
 </​code>​ </​code>​
  
-Notem que se se um mapa externo tivesse um nome como "​rand"​ ainda não haveria problemas pois o sigil garante que o nome não causa conflito. O #[ ] mais externo indica que isso tudo produz um mapa (equivalente ao CalculateMap). Se fosse (equivalente CalculateValue) seria $[ ]. +===== Complex Example =====
-Caso não fossem usados os sigils, a expressão final seria +
  
-<​code ​cpp+<​code ​java> 
-    patches := LoadCategoricalMap "​../​originals/​landscape.ers"​ .no .no 0 0 .none; +@title = Calc Patch Sizes, Mean Patch Sizes and Patch Size Standard Deviations 
-    // ... +@author = Dinamica Team 
-    ​currentCategoryId ​:= Step step; +@organization = CSR / UFMG 
-    // ..+@metaversion = 1.0 
-    // Isolate the patches of a single category.  +@description = Calculate the patch sizes, the mean patch sizes and the patch size standard deviation of different categories. 
-    @collapsed = yes +@notes = "The model input is a map where the non-null values identify the patches. 
-    ​singleCategoryPatches ​:= #[ if patches = currenteCategoryId ​then else null ];+ 
 +The output is a table per category containing the patch sizes and two additional tables containing the mean patch size and the patch size standard deviation per category."​ 
 +@showproperties = yes 
 +@version = 1.9.32 
 +Script {{ 
 +    // The input map.  
 +    // 
 +    // Non-null values identify the patches. ​ 
 +    patches := LoadCategoricalMap "​../​originals/​landscape.ers"​ .no .no 0 0 .none .none; 
 + 
 +    ​ForEachCategory patches {{ 
 +        step = step; 
 + 
 +        ​// Patch size standard deviations 
 +        currentPatchSizeStandardDeviations := MuxLookupTable [ 
 +            "​Category"​ "​Patch_Size_Standard_Deviations_In_Hectares"​ 
 +        ] updatedPatchSizeStandardDeviations;​ 
 + 
 +        // Mean Patch sizes 
 +        currentMeanPatchSizes := MuxLookupTable [ 
 +            "​Category"​ "​Mean_Patch_Sizes_In_Hectares"​ 
 +        ] updatedPatchMeans;​ 
 + 
 +        // Current category.  
 +        ​currentCategory ​:= Step step; 
 + 
 +        ​// Calculate the sizes of a set of patches and their corresponding mean and  
 +        // standard deviation.  
 +        ​@collapsed = yes 
 +        Group {{ 
 +            ​// Isolate the patches of a single category.  
 +            @collapsed = yes 
 +            ​singleCategoryIndividualizedPatches ​:= # [ 
 +                ​if #patches = $currentCategory ​then 
 +                    #patches 
 +                ​else  
 +                    ​null         
 +            ​.int32 .default .no .none; 
 + 
 +            // Calculate the patch size, the mean patch size and patch size standard  
 +            // deviation.  
 +            @collapsed = yes 
 +            Group {{ 
 +                // Individualize the patches.  
 +                individualizedPatches := CalcPatchLabelMap { 
 +                    source = singleCategoryIndividualizedPatches,​ 
 +                    initialPatchLabel = 1, 
 +                    onlyOrthogonalsAreAllowed = .no, 
 +                    windowLines = 3, 
 +                    windowColumns = 3, 
 +                    cellType = .int32, 
 +                    nullValue = .default, 
 +                    patchLabelsAreSparse = .no 
 +                }; 
 + 
 +                attributes := ExtractMapAttributes individualizedPatches .yes .yes; 
 + 
 +                // Calculate the mean patch size.  
 +                // 
 +                // The calculation uses the total patch size and the number of individual patches.  
 +                @collapsed = yes 
 +                mean := $ [ 
 +                    (%attributes["​cellArea"​] * %attributes["​nonNullCells"​] / %attributes["​uniqueCells"​]) ? 0 
 +                ] .no 0; 
 + 
 +                // Calculate the patch sizes.  
 +                _ patchSizesInHectares _ := CalcAreas individualizedPatches;​ 
 + 
 +                // Calculate the patch size standard deviation.  
 +                @collapsed = yes 
 +                Group {{ 
 +                    // Calculate the patch size standard deviation.  
 +                    @collapsed = no 
 +                    LogPolicy .warning .no {{ 
 +                        // Calculate the SUM(Xi - MEAN)^2, where Xi is the current patch size.  
 +                        @collapsed = yes 
 +                        ForEachCategory individualizedPatches {{ 
 +                            step0 = step; 
 + 
 +                            // Accumulated value of SUM(Xi - MEAN)^2.  
 +                            currentAccumulatedValue := MuxValue 0 updatedAccumulatedValue;​ 
 + 
 +                            // Current patch id.  
 +                            currentPatchId := Step step0; 
 + 
 +                            // Calculate the updated accumulated value of SUM(Xi - MEAN)^2 for the current  
 +                            // patch size.  
 +                            @collapsed = yes 
 +                            updatedAccumulatedValue := $ [ 
 +                                $currentAccumulatedValue + ((%patchSizesInHectares[$currentPatchId] - $mean) ^ 2) 
 +                            ] .no 0; 
 +                        }}; 
 +                    }}; 
 + 
 +                    // Provide 0 as the default accumulated value even if the input map has no patches  
 +                    // for the current categories.  
 +                    accumulatedValue := ValueJunction updatedAccumulatedValue 0; 
 + 
 +                    // Calculate the standard deviation using the SUM(Xi - MEAN)^2.  
 +                    @collapsed = yes 
 +                    standardDeviation := $ [ 
 +                        sqrt($accumulatedValue / %attributes["​uniqueCells"​]) ? 0 
 +                    ] .no 0; 
 +                }}; 
 + 
 +                // Update the mean table with the mean patch size of the current category.  
 +                updatedPatchMeans := SetLookupTableValue currentMeanPatchSizes currentCategory mean; 
 + 
 +                // Update the table of standard deviations with the standard deviation of the  
 +                // current category.  
 +                updatedPatchSizeStandardDeviations := SetLookupTableValue currentPatchSizeStandardDeviations currentCategory standardDeviation;​ 
 +            }}; 
 +        }}; 
 + 
 +        // Save a table of patch sizes per category.  
 +        SaveLookupTable patchSizesInHectares "​patch_sizes.csv"​ 2 step .none; 
 +    }}; 
 + 
 +    // Save the mean patch sizes as a table.  
 +    SaveLookupTable updatedPatchMeans "​mean_patch_sizes.csv"​ 2 .none .none; 
 + 
 +    // Save the patch size standard deviations as a table.  
 +    SaveLookupTable updatedPatchSizeStandardDeviations "​patch_size_standard_deviations.csv"​ 2 .none .none; 
 +}};
 </​code>​ </​code>​
  
-Ambos os casos seria expandidos para o CalculateMap/​CalculateValue equivalente. +
-*/+