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
ego_script [2026/07/15 01:03]
hermann
ego_script [2026/07/22 20:26] (current)
hermann
Line 3: Line 3:
 ====== Introduction ====== ====== Introduction ======
  
-EGO Script is a simple, text-based language for creating and editing Dinamica EGO models. A model written in this format is stored in a file with the ''​.ego''​ extension. An ''​.ego''​ file is just another way of describing a model — it is equivalent to the XML form Dinamica EGO uses internally. Because the two are interchangeable,​ you can write a model as an EGO script, open it in the graphical interface, edit it there, and save it again, moving freely between the textual and visual representations.+EGO Script is a simple, text-based language for creating and editing Dinamica EGO models. A model written in this format is stored in a file with the ''​.ego''​ extension. An ''​.ego''​ file is just another way of describing a model — it is equivalent to the XML form Dinamica EGO uses internally. Because the two are interchangeable,​ you can write a model as an EGO script, open it in the graphical interface, edit it there, and save it again, moving freely between the textual and visual representations. See [[basic_data_flow|Basic Data Flow]] for the execution model shared by both representations;​ this tutorial covers the textual notation specifically.
  
 > **Caution:​** When you round-trip a model through the graphical interface, the interface can rewrite a model'​s layout and the format of its inputs and outputs according to the options currently in effect, so a script reopened and saved from the GUI may not come back byte-for-byte identical to what you wrote. This is normal, and the resulting model is equivalent. > **Caution:​** When you round-trip a model through the graphical interface, the interface can rewrite a model'​s layout and the format of its inputs and outputs according to the options currently in effect, so a script reopened and saved from the GUI may not come back byte-for-byte identical to what you wrote. This is normal, and the resulting model is equivalent.
Line 43: Line 43:
 A variable name must begin with an underscore or a letter, and may be followed by any combination of underscores,​ letters, and digits (''​[_a-zA-Z][_a-zA-Z0-9]*''​). Variable names are case-sensitive. A variable name must begin with an underscore or a letter, and may be followed by any combination of underscores,​ letters, and digits (''​[_a-zA-Z][_a-zA-Z0-9]*''​). Variable names are case-sensitive.
  
-Variables are the primary mechanism by which functors pass data to one another, and data dependencies are the main source of execution ordering. A variable must be bound by the functor that produces it before any functor that reads it can run — this is what creates a **dependency** between the two. Functors that do not share a variable, directly or through a chain of intermediate variables, have no dependency on each other and may execute in any order or at the same time. [[#​container_functors|Container functors]], described in the Container functors section of the reference, impose a second ordering constraint on top of this.+Variables are the primary mechanism by which functors pass data to one another, and data dependencies are the main source of execution ordering. A variable must be bound by the functor that produces it before any functor that reads it can run — this is what creates a **dependency** between the two. Functors that do not share a variable, directly or through a chain of intermediate variables, have no dependency on each other and may execute in any order or at the same time. [[#​container_functors|Container functors]], described in the Container functors section of the reference, impose a second ordering constraint on top of this. This is a property of the underlying functor graph, not of EGO Script specifically — see [[basic_data_flow|Basic Data Flow]].
  
 > **Note:** The position of a functor definition in the script file does not determine when it runs. Unless two functors are connected by a data dependency — directly or through a chain of variables — never assume anything about their relative execution order. The only exception is [[#​container_functors|containers]],​ covered later in this section. > **Note:** The position of a functor definition in the script file does not determine when it runs. Unless two functors are connected by a data dependency — directly or through a chain of variables — never assume anything about their relative execution order. The only exception is [[#​container_functors|containers]],​ covered later in this section.
Line 71: Line 71:
 ==== Constants ==== ==== Constants ====
  
-Constants supply a fixed value directly to an input port, without connecting a functor. They come in several ​forms:+Constants supply a fixed value directly to an input port, without connecting a functor. Despite often looking similar in syntax, every constant is interpreted and validated according to the type of the port it is supplied to — a value that is valid for one port type may be rejected by another. They come in four forms.
  
-  * **Numeric literals** — integer or real values written directly ​(''​0'',​ ''​250'',​ ''​3.14''​). +**Numeric literals** — integer or real values written directly''​0'',​ ''​250'',​ ''​3.14''​.
-  * **Text constants** — text enclosed in double quotes. The syntax is identical regardless of the specific type: the port determines whether the value is treated as a ''​String'',​ a ''​MapFilename'',​ a ''​TableFilename'',​ a ''​LookupTableFilename'',​ a ''​WeightsFilename'',​ a ''​GenericFilename'',​ a ''​Folder'',​ a ''​Name'',​ or a ''​Code''​. For example, ''​%%"​%%c:/​data/​landscape.tif%%"​%%''​ supplied to a ''​MapFilename''​ port is a map filename constant, not a generic string. +
-  * **Dot constants** — a leading dot followed by a keyword (''​.yes'',​ ''​.no'',​ ''​.int32'',​ ''​.default''​). Each data type defines its own set of dot constants; for example, boolean ports accept ''​.yes''​ and ''​.no'',​ cell type ports accept ''​.int32'',​ ''​.float32'',​ and so on, and storage mode ports accept ''​.default''​. The constants accepted by a port depend entirely on its type. +
-  * **Structured constants** — complex values such as tables, matrices, or transition specifications,​ enclosed in square brackets ''​[ … ]''​. These are specific to individual functors and can be multi-line.+
  
-A call can mix all constant forms with variable references ​in a single argument listThis call loads mapsupplying ​map filename constanttwo dot constants for the null-value ​override ​and storage mode, and a numeric literal ​for the suffix ​digit count:+**Text constants** — text enclosed ​in double quotes. Despite looking identical in syntax, text constants are interpreted and validated according to the port's type. The types that accept the basic ''​%%"​%%text%%"​%%''​ form include ''​String'',​ ''​MapFilename'',​ ''​TableFilename'',​ ''​LookupTableFilename'',​ ''​WeightsFilename'',​ ''​GenericFilename'',​ ''​Folder'',​ and ''​Name''​ — but each imposes its own validation:​ 
 + 
 +  * **Filename ports** (''​MapFilename'',​ ''​TableFilename'',​ etc.) typically verify that the file extension is appropriate for that type. For example, ''"​test.tif"''​ is accepted by ''​MapFilename''​ port but rejected by a ''​TableFilename''​ port, since ''​.tif''​ is not valid table file extension. 
 +  * **''​Name''​ ports** only accept identifiers that follow the same naming rules as variables — starting with a letter or underscorefollowed only by letters, digits, and underscores. ''"​distance_to_roads"''​ is valid; ''"​Distance To Roads"''​ is not. 
 + 
 +<​code>​ 
 +// used as MapFilename 
 +"​c:/​data/​landscape.tif"​ 
 +// used as a Name 
 +"​distanceToRoads"​ 
 +</​code>​ 
 + 
 +For ''​String''​ ports that contain line breaks or double-quote charactersuse the extended form ''​$"​DELIMITER(content)DELIMITER"''​. The content is everything between the opening ''​(''​ and the closing ''​)'',​ and the DELIMITER — any sequence of characters placed between the ''​%%"​%%''​ and the ''​('',​ including empty — makes the closing ''​)"''​ unambiguous. The delimiter must be identical on both sides. This extended form is **only accepted by ''​String''​ ports**: 
 + 
 +<​code>​ 
 +// basic form — line break inside the content 
 +$"​(Hello 
 +world)"​ 
 + 
 +// X as delimiter — content contains )" which would otherwise terminate the basic form early 
 +$"​X(some )" text)X"​ 
 +</​code>​ 
 + 
 +**Dot constants** — a leading dot followed by a keyword: ''​.yes'',​ ''​.no'',​ ''​.int32'',​ ''​.default''​. Each data type defines its own set of dot constants ​and the constants accepted by a port depend entirely on its type. Two dot constants are predefined and available ​for **any** input port regardless of type: 
 + 
 +  * ''​.UNBOUND''​ — the port is not connected, or its connection is deliberately being ignored. This appears in particular when a script fragment is copied from the GUI to a text editor and some of the original connections are not part of the copied selection. 
 +  * ''​.none''​ — the port is intentionally left without a value. Valid **only for optional nullable input ports**. 
 + 
 +**Structured constants** — complex values enclosed in square brackets ''​[ … ]'',​ specific to individual functors and can be multi-line: ''​[ 2->1 0.05 ]'',​ ''​[ "​Key"​ "​Value"​ ]''​. 
 + 
 +Lookup table literals support an additional shorthand: ''​startKey startValue .. endKey endValue''​ auto-generates every key from ''​startKey''​ to ''​endKey''​ (incrementing by one), with values linearly interpolated between ''​startValue''​ and ''​endValue''​. Range entries and plain ''​key ​value''​ entries can be mixed freely, ​and commas between entries are optional: 
 + 
 +<​code>​ 
 +[ "​Key"​ "​Value"​1 1 .. 4 1, 5 -8, 6 1 .. 9 1 ] 
 +</​code>​ 
 + 
 +Since the start and end values in each range above are equal, interpolating between them keeps the value constant — keys 1–4 and 6–9 all map to ''​1'',​ and key 5 maps to ''​-8''​. When script is saved from the GUI, ranges like this are automatically collapsed back into ''​..''​ notation where possible. See [[lookup_table_type|Lookup Table Type]] ​for the full syntax, including optional key/value column names, and [[table_type|Table Type]] for the syntax rules that apply to tables in general. 
 + 
 +A general table follows the same bracket syntax but allows any number of columns, mixing Real and String data, with types inferred from each column'​s own values unless overridden with a ''#​type'' ​suffix
 + 
 +<​code>​ 
 +
 +  "​PatchId*#​string",​ "​Area",​ "​Category",​ 
 +  007, 12.4, "​forest",​ 
 +  013, 8.7, "​pasture"​ 
 +
 +</​code>​ 
 + 
 +Without the ''#​string''​ override, ''​PatchId'''​s unquoted values would be inferred as Real numbers — ''​007''​ would collapse to the number ''​7'',​ losing its leading zero. The explicit type forces String interpretation instead, preserving each value exactly as written. ''​Area''​ and ''​Category''​ are left to plain inference: Real from ''​12.4''/''​8.7'',​ String from the quoted ''"​forest"''/''"​pasture"''​. 
 + 
 +A call can mix all forms with variable references in a single argument list:
  
 <​code>​ <​code>​
Line 85: Line 132:
  
 Here ''"​c:/​data/​landscape.tif"''​ is a map filename constant (the ''​filename''​ port is type ''​MapFilename''​),​ ''​.none''​ leaves the nullable ''​nullValue''​ port without a value, ''​.default''​ is a storage mode dot constant, and ''​0''​ is a numeric literal. Here ''"​c:/​data/​landscape.tif"''​ is a map filename constant (the ''​filename''​ port is type ''​MapFilename''​),​ ''​.none''​ leaves the nullable ''​nullValue''​ port without a value, ''​.default''​ is a storage mode dot constant, and ''​0''​ is a numeric literal.
- 
-Structured constants use the same square-bracket syntax as expressions but appear as positional arguments. This call passes a transition matrix directly as a structured constant, specifying one transition (from class 2 to class 1) and its rate: 
  
 <​code>​ <​code>​
Line 94: Line 139:
 Here ''​[ 2->1 0.05 ]''​ is a structured constant representing a transition matrix with a 5% rate from class 2 to class 1. Here ''​[ 2->1 0.05 ]''​ is a structured constant representing a transition matrix with a 5% rate from class 2 to class 1.
  
-Two dot constants have special predefined meanings: +> **Note:** ''​Code''​ — the type used for expression inputs such as the Python code in [[Calculate Python Expression]] — is not a text constant. Code values are stored as base64 ​in the underlying script, making them impractical ​to write directly. When a port expects ​a ''​Code'' ​value, supply a ''​String'' ​carrier functor containing the expression text; the automatic ​''​String → Code'' ​conversion handles ​the rest.
- +
-  ​* ''​.UNBOUND''​ — available ​for **any** input port regardless of type. Indicates ​the port is not connected, or its connection is being deliberately ignored. This constant ​appears ​in particular when a script fragment is copied from the GUI to a text editor and some of the original inputs are not part of the copied selection — those unresolved connections are written as ''​.UNBOUND''​+
-  * ''​.none'' ​— available only for **optional nullable input ports** (ports that explicitly accept a missing value as meaningful input and whose default value is already ​''​.none''​). Indicates ​the port is intentionally left without a value.+
  
 ==== Positional syntax ==== ==== Positional syntax ====
Line 219: Line 261:
 A **container functor** is a functor that holds other functors inside it. The contained functors execute within the container'​s scope. A **container functor** is a functor that holds other functors inside it. The contained functors execute within the container'​s scope.
  
-Containers are the second source of execution ordering in Dinamica EGO, alongside data dependencies. All functors inside a container execute as part of that container'​s execution. This means that if container B depends on container A — for example, B consumes a value produced by something inside A — then B will only start after A has fully completed. As a consequence,​ every functor inside B is guaranteed to run after every functor inside A, and the contents of the two containers will never execute simultaneously.+Containers are the second source of execution ordering in Dinamica EGO, alongside data dependencies. All functors inside a container execute as part of that container'​s execution. This means that if container B depends on container A — for example, B consumes a value produced by something inside A — then B will only start after A has fully completed. As a consequence,​ every functor inside B is guaranteed to run after every functor inside A, and the contents of the two containers will never execute simultaneously. See [[basic_data_flow|Basic Data Flow]] for how this fits into the broader, notation-independent execution model — including how containers also control whether and how many times their contents run.
  
 Containers fall into a few families: Containers fall into a few families:
Line 357: Line 399:
 }}; }};
 </​code>​ </​code>​
 +
 +> **Note:** A mux's feedback input is the one exception to the dependency rule in [[#​functors_variables_and_binding|Functors,​ variables, and binding]] — the mux does not wait for the functor that produces its feedback value to run before it runs; it emits the value that functor produced on the previous iteration instead. This is also why, in the example above, ''​nextCount''​ is passed into ''​MuxValue''​ on a line above the line that assigns ''​nextCount'':​ the mux and the calculator each depend on the other'​s output, so no matter which one is written first in the script, the other'​s variable is necessarily used before it is assigned.
  
 A **junction** selects between two dataflows. It reads its first input; if that input carries data, the junction passes it through. If the first input is empty, it passes the second input through instead. If both are empty, the junction reports an error. Junctions are typed, with one per data kind — [[Map Junction]], [[Categorical Map Junction]], [[Table Junction]], [[Lookup Table Junction]], [[Value Junction]], [[String Junction]], and so on: A **junction** selects between two dataflows. It reads its first input; if that input carries data, the junction passes it through. If the first input is empty, it passes the second input through instead. If both are empty, the junction reports an error. Junctions are typed, with one per data kind — [[Map Junction]], [[Categorical Map Junction]], [[Table Junction]], [[Lookup Table Junction]], [[Value Junction]], [[String Junction]], and so on:
Line 481: Line 525:
  
 Converting abbreviated syntax to verbose is always lossless. Converting verbose to abbreviated is only possible when all hooks are free of comments, properties, and identifiers that do not appear in the expression. Converting abbreviated syntax to verbose is always lossless. Converting verbose to abbreviated is only possible when all hooks are free of comments, properties, and identifiers that do not appear in the expression.
 +
 +> **Note:** This distinction applies only to saved or generated script text. The graphical interface always displays and edits a calculator functor'​s expression in the verbose ''​i1''/''​t1''/''​v1''​ form, with each hook represented as its own functor node, regardless of whether the //Use abbreviated syntax// option is enabled or which form the underlying file uses. The ''#​name''/''​%name''/''​$name''​ abbreviated form exists only in script text; the graphical interface has no corresponding abbreviated representation.
  
 A common situation where this matters: if you connect a map or lookup table purely to define the output format — not because it is referenced in the expression — connecting it via a ''​NumberMap''​ or ''​NumberTable''​ hook will block abbreviated syntax, since the hook defines an identifier absent from the expression. Use the dedicated port instead: the ''​Result Format''​ input port for map calculators,​ or the ''​Base Lookup Table''​ input port for lookup table calculators. These connections do not create hooks and do not affect the availability of abbreviated syntax. A common situation where this matters: if you connect a map or lookup table purely to define the output format — not because it is referenced in the expression — connecting it via a ''​NumberMap''​ or ''​NumberTable''​ hook will block abbreviated syntax, since the hook defines an identifier absent from the expression. Use the dedicated port instead: the ''​Result Format''​ input port for map calculators,​ or the ''​Base Lookup Table''​ input port for lookup table calculators. These connections do not create hooks and do not affect the availability of abbreviated syntax.
Line 624: Line 670:
 </​code>​ </​code>​
  
-A property name must start with a letter or ''​_'',​ followed by letters, ''​_'',​ and ''​.''​. A value may contain any characters, including blanks; a value that spans line breaks must be surrounded by double quotes:+A property name must start with a letter or ''​_'',​ followed by letters, ''​_'',​ and ''​.''​. A value may contain any characters, including blanks; a value that spans line breaks must be surrounded by double quotes. If the value itself contains a double-quote character, it must be escaped as ''​\"''​:
  
 <​code>​ <​code>​
Line 632: Line 678:
  
 The output is a table containing the largest patch index per category."​ The output is a table containing the largest patch index per category."​
 +@description = "The input map must have values in the range [0, 1].
 +Use \"​null\"​ to mark cells that should be excluded from the analysis."​
 </​code>​ </​code>​
  
Line 647: Line 695:
 | ''​extendedcomment''​ | ''​dff.functor.extendedcomment''​ | The functor'​s extended comment — the text after ''​===''​ in a ''<​nowiki>//</​nowiki>''​ comment (see [[#​comments|Comments]]). | | ''​extendedcomment''​ | ''​dff.functor.extendedcomment''​ | The functor'​s extended comment — the text after ''​===''​ in a ''<​nowiki>//</​nowiki>''​ comment (see [[#​comments|Comments]]). |
 | ''​collapsed''​ | ''​dff.container.collapsed''​ | Indicates that a container is drawn closed (its contents hidden) in the graphical interface. Applies to containers only. Values: ''​yes''/''​no''​ or ''​true''/''​false''​. | | ''​collapsed''​ | ''​dff.container.collapsed''​ | Indicates that a container is drawn closed (its contents hidden) in the graphical interface. Applies to containers only. Values: ''​yes''/''​no''​ or ''​true''/''​false''​. |
 +| ''​ignoredIssues''​ | ''​dff.functor.ignoredissues''​ | Suppresses a specific category of GUI warning for the functor — observed values include ''​Experimental''​ (the functor is experimental) and ''​ResultIgnored''​ (an output is intentionally left unused). |
  
 > **Note:** A few per-functor properties exist only while a model is open in the editor and are never written to the saved model: ''​dff.functor.text'',​ ''​dff.functor.file'',​ ''​dff.functor.line'',​ and ''​dff.functor.column''​. > **Note:** A few per-functor properties exist only while a model is open in the editor and are never written to the saved model: ''​dff.functor.text'',​ ''​dff.functor.file'',​ ''​dff.functor.line'',​ and ''​dff.functor.column''​.
Line 702: Line 751:
 | ''​map2Region''​ | ''​Map 2 Region''​ | | ''​map2Region''​ | ''​Map 2 Region''​ |
 | ''​saddleHeight2''​ | ''​Saddle Height 2''​ | | ''​saddleHeight2''​ | ''​Saddle Height 2''​ |
 +
 +One case is excluded from this reconstruction:​ a variable name that is just the functor'​s own name, lowercased at the front, with a trailing number — for example ''​lookupTable0''​ for a ''​LookupTable''​ functor. This pattern is recognized as an **auto-generated name**: one the GUI assigned on its own because no alias was ever set, rather than a name a person chose. Such names are not reconstructed into an alias like ''​Lookup Table 0'';​ the functor is simply shown with no alias.
  
 ==== Model-level metadata ==== ==== Model-level metadata ====
Line 950: Line 1001:
 hectaresColumn := GetTableColumn areaTable 3; hectaresColumn := GetTableColumn areaTable 3;
 </​code>​ </​code>​
- 
-