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
calculate_python_expression [2026/08/31 16:51]
hermann
calculate_python_expression [2026/08/31 17:10] (current)
hermann
Line 3: Line 3:
 ===== Description ===== ===== Description =====
  
-This is a container functor that runs a Python instance with a user-defined expression. Like the other calculator functors, such as [[calculate_map|Calculate Map]] or [[calculate_lookup_table|Calculate Lookup Table]], data is connected through hook functors placed inside its block, rather than through regular input ports. See also [[calculate_r_expression|Calculate R Expression]] for the equivalent functor using R.+This is a container functor that runs a Python instance with a user-defined expression. Like the other calculator functors, such as [[Calculate Map]] or [[Calculate Lookup Table]], data is connected through hook functors placed inside its block, rather than through regular input ports. See also [[Calculate R Expression]] for the equivalent functor using R.
  
 ===== Inputs ===== ===== Inputs =====
  
-^ Name ^ Type ^ Description ^ +^ Name  ^ Type  ^ Description ​ 
-| Expression | [[code_type|Code Type]] | The expression to run on Python. Written directly as a Code constant using its own raw string syntax -- see [[#​writing_the_expression_in_ego_script|Writing the expression in EGO Script]] below. |+| Expression ​ | [[Code Type]] ​ | The expression to run on Python. Written directly as a Code constant using its own raw string syntax -- see [[#​writing_the_expression_in_ego_script|Writing the expression in EGO Script]] below. ​ |
  
 ===== Optional Inputs ===== ===== Optional Inputs =====
  
-^ Name ^ Type ^ Description ^ Default Value ^ +^ Name  ^ Type  ^ Description ​ ^ Default Value  
-| Packages | [[string_type|String Type]] | Packages to install with pip before the expression runs, one per line. Each package can be identified by name or by a filename or URL pointing to the corresponding wheel; a package already installed is skipped. This is an advanced port. | None |+| Packages ​ | [[String Type]] ​ | Packages to install with pip before the expression runs, one per line. Each package can be identified by name or by a filename or URL pointing to the corresponding wheel; a package already installed is skipped. This is an advanced port.  | None  |
  
 ===== Outputs ===== ===== Outputs =====
  
-^ Name ^ Type ^ Description ^ +^ Name  ^ Type  ^ Description ​ 
-| Result | [[struct_type|Struct Type]] | Struct containing the output values generated by the expression, one entry per key assigned into dinamica.outputs. |+| Result ​ | [[Struct Type]] ​ | Struct containing the output values generated by the expression, one entry per key assigned into dinamica.outputs. ​ |
  
 ===== Group ===== ===== Group =====
  
-[[functor_list#integration|Integration]]+[[Functor List#Integration ​| Integration]]
  
 ===== Notes ===== ===== Notes =====
Line 30: Line 30:
 Data is passed into the expression through hook functors placed inside the container'​s block -- the same verbose-form hook mechanism used by the calculator functors: Data is passed into the expression through hook functors placed inside the container'​s block -- the same verbose-form hook mechanism used by the calculator functors:
  
-  * Tables and lookup tables ​connect via a [[number_table|Number Table]] ​hook, available in the expression as dinamica.inputs["​t1"​],​ dinamica.inputs["​t2"​], ​..., dinamica.inputs["​t100"​] +  * Tables and lookup tables ​→ [[Number Table]] ​→ available in the expression as dinamica.inputs["​t1"​],​ dinamica.inputs["​t2"​], ​, dinamica.inputs["​t100"​] 
-  * Scalar values ​connect via a [[number_value|Number Value]] ​hook, available as dinamica.inputs["​v1"​],​ dinamica.inputs["​v2"​], ​..., dinamica.inputs["​v100"​] +  * Scalar values ​→ [[Number Value]] ​→ available as dinamica.inputs["​v1"​],​ dinamica.inputs["​v2"​], ​, dinamica.inputs["​v100"​] 
-  * Strings ​connect via a [[number_string|Number String]] ​hook, available as dinamica.inputs["​s1"​],​ dinamica.inputs["​s2"​], ​..., dinamica.inputs["​s100"​]+  * Strings ​→ [[Number String]] ​→ available as dinamica.inputs["​s1"​],​ dinamica.inputs["​s2"​], ​, dinamica.inputs["​s100"​]
  
-Maps cannot be connected -- this functor has no cell context. There is no shorthand notation. See [[calculate_functors|Calculate Functors -- Complete Operator Documentation]] for the general hook mechanism and syntax.+Maps cannot be connected -- this functor has no cell context. There is no shorthand notation. See [[Calculate Functors|Calculate Functors -- Complete Operator Documentation]] for the general hook mechanism and syntax.
  
-Every table or lookup table arriving through dinamica.inputs is represented in Python as a list of lists: the first inner list contains the column names (the header row) and every subsequent inner list is a row of data. The header carries plain column names only -- no asterisk marking key columns, no type annotation -- so which columns were keys in the original table is information Python doesn'​t receive and can't recover from the input alone. Code that needs that distinction has to be told it separately, for instance by also connecting the key count as its own [[number_value|Number Value]] hook.+Every table or lookup table arriving through dinamica.inputs is represented in Python as a list of lists: the first inner list contains the column names (the header row) and every subsequent inner list is a row of data. The header carries plain column names only -- no asterisk marking key columns, no type annotation -- so which columns were keys in the original table is information Python doesn'​t receive and can't recover from the input alone. Code that needs that distinction has to be told it separately, for instance by also connecting the key count as its own [[Number Value]] hook.
  
 ==== Expression outputs ==== ==== Expression outputs ====
Line 52: Line 52:
 ==== Retrieving outputs ==== ==== Retrieving outputs ====
  
-Calculate Python Expression returns a single [[struct_type|Struct Type]] value (via its Result output port) containing every entry assigned to dinamica.outputs. To retrieve individual values from that struct, use the following functors from the Integration group:+Calculate Python Expression returns a single [[Struct Type]] value (via its Result output port) containing every entry assigned to dinamica.outputs. To retrieve individual values from that struct, use the following functors from the Integration group:
  
-^ Functor ^ Retrieves ^ +^ Functor ​ ^ Retrieves ​ 
-| [[extract_struct_number|Extract Struct Number]] | A numeric value (int or float assigned to dinamica.outputs) | +| [[Extract Struct Number]] ​ | A numeric value (int or float assigned to dinamica.outputs) ​ 
-| [[extract_struct_string|Extract Struct String]] | A string value | +| [[Extract Struct String]] ​ | A string value  
-| [[extract_struct_table|Extract Struct Table]] | A table produced by dinamica.prepareTable() | +| [[Extract Struct Table]] ​ | A table produced by dinamica.prepareTable() ​ 
-| [[extract_struct_lookup_table|Extract Struct Lookup Table]] | A lookup table produced by dinamica.prepareLookupTable() | +| [[Extract Struct Lookup Table]] ​ | A lookup table produced by dinamica.prepareLookupTable() ​ 
-| [[extract_struct_tuple|Extract Struct Tuple]] | A tuple value |+| [[Extract Struct Tuple]] ​ | A tuple value  |
  
 Each functor takes two inputs: the Struct returned by Calculate Python Expression, and the name of the entry to extract as a string constant. For example, to retrieve a numeric output named patchCount and a table output named filteredPatches:​ Each functor takes two inputs: the Struct returned by Calculate Python Expression, and the name of the entry to extract as a string constant. For example, to retrieve a numeric output named patchCount and a table output named filteredPatches:​
Line 83: Line 83:
 dinamica.package(packageName,​ installPath=None,​ loadPath=None) installs (if needed, via pip) and imports the requested module. Because it runs together with the script, it may fail if a package is already loaded in an incompatible version. dinamica.package(packageName,​ installPath=None,​ loadPath=None) installs (if needed, via pip) and imports the requested module. Because it runs together with the script, it may fail if a package is already loaded in an incompatible version.
  
-^ Parameter ^ Type ^ Default ^ Description ^ +^ Parameter ​ ^ Type  ^ Default ​ ^ Description ​ 
-| packageName | str | -- | Identifies the package. Used as the default for both installPath and loadPath when those are omitted. | +| packageName ​ | str  | --  | Identifies the package. Used as the default for both installPath and loadPath when those are omitted. ​ 
-| installPath | str | packageName | What is passed to pip install. Can be a plain name, a version-pinned requirement,​ a wheel filename or URL, a git+ URL, or a name followed by extra pip flags. | +| installPath ​ | str  | packageName ​ | What is passed to pip install. Can be a plain name, a version-pinned requirement,​ a wheel filename or URL, a git+ URL, or a name followed by extra pip flags. ​ 
-| loadPath | str | packageName | The name used to import the module in Python. |+| loadPath ​ | str  | packageName ​ | The name used to import the module in Python. ​ |
  
 Simply install and load numpy: Simply install and load numpy:
Line 127: Line 127:
  
 <​code>​ <​code>​
-beautifulsoup4 +numpy 
-opencv-python +requests==2.31.0 
-PyYAML+torchvision==0.19.1 --index-url https://​download.pytorch.org/​whl/​cu121
 </​code>​ </​code>​
  
Line 135: Line 135:
  
 <code python> <code python>
-from bs4 import ​BeautifulSoup +import ​numpy as np 
-import ​cv2 as cv +from requests ​import ​Session 
-import ​yaml+from torchvision ​import ​transforms
 </​code>​ </​code>​
  
-==== dinamica.prepareTable() ​====+=== dinamica.prepareTable() ===
  
 Converts a list of lists into a table ready to be assigned to an output. The first inner list must be the header row. As with any table, each column'​s type is inferred from its own values: a column of int/float values produces a Real column, a column of str values produces a String column. Converts a list of lists into a table ready to be assigned to an output. The first inner list must be the header row. As with any table, each column'​s type is inferred from its own values: a column of int/float values produces a Real column, a column of str values produces a String column.
  
-^ Parameter ^ Type ^ Default ^ Description ^ +^ Parameter ​ ^ Type  ^ Default ​ ^ Description ​ 
-| inputTable | list of lists | -- | The table data. First inner list is the header row; subsequent inner lists are data rows. | +| inputTable ​ | list of lists  | --  | The table data. First inner list is the header row; subsequent inner lists are data rows.  
-| numKeys | int | -- | Number of key columns. Key column names will have an asterisk appended in the output. |+| numKeys ​ | int  | --  | Number of key columns. Key column names will have an asterisk appended in the output. ​ |
  
-==== dinamica.prepareLookupTable() ​====+=== dinamica.prepareLookupTable() ===
  
 Converts a list of lists into a lookup table ready to be assigned to an output. The first inner list must be the header row. Lookup tables are always Real-typed on both key and value sides -- there is no String option -- so every value in lut must be numeric. Converts a list of lists into a lookup table ready to be assigned to an output. The first inner list must be the header row. Lookup tables are always Real-typed on both key and value sides -- there is no String option -- so every value in lut must be numeric.
  
-^ Parameter ^ Type ^ Default ^ Description ^ +^ Parameter ​ ^ Type  ^ Default ​ ^ Description ​ 
-| lut | list of lists | -- | The lookup table data. First inner list is the header row; subsequent inner lists are data rows. |+| lut  | list of lists  | --  | The lookup table data. First inner list is the header row; subsequent inner lists are data rows.  |
  
-==== dinamica.toTable() ​====+=== dinamica.toTable() ===
  
 Converts several Python data shapes into a valid Dinamica table for output. Column types are inferred the same way as dinamica.prepareTable() -- except for a flat list, which always produces a Real-typed lookup table with sequential keys, matching the Real-only rule for lookup tables. Converts several Python data shapes into a valid Dinamica table for output. Column types are inferred the same way as dinamica.prepareTable() -- except for a flat list, which always produces a Real-typed lookup table with sequential keys, matching the Real-only rule for lookup tables.
  
-^ Parameter ^ Type ^ Default ^ Description ^ +^ Parameter ​ ^ Type  ^ Default ​ ^ Description ​ 
-| inputTable | list of lists; dict of lists; list of tuples; flat list; pandas.DataFrame;​ numpy.array | -- | The data to convert. A flat list produces a lookup table with sequential keys. A numpy.array must have its header as the first row. | +| inputTable ​ | list of lists; dict of lists; list of tuples; flat list; pandas.DataFrame;​ numpy.array ​ | --  | The data to convert. A flat list produces a lookup table with sequential keys. A numpy.array must have its header as the first row.  
-| numKeys | int | -- | Number of key columns. Key column names will have an asterisk appended in the output. Ignored for a flat list, which always produces a lookup table with sequential keys. |+| numKeys ​ | int  | --  | Number of key columns. Key column names will have an asterisk appended in the output. Ignored for a flat list, which always produces a lookup table with sequential keys.  |
  
 ==== Examples ==== ==== Examples ====
Line 228: Line 228:
 ==== Writing the expression in EGO Script ==== ==== Writing the expression in EGO Script ====
  
-Expression can be filled in directly as a text constant, using [[code_type|Code Type]]'​s own raw string syntax -- the same ''​$"<​delimiter>​( raw_characters )<​delimiter>"''​ form used by String constants. This is also the form the Dinamica EGO GUI's dedicated code editor generates when it writes the Expression port's value, so a hand-written script and one produced by the GUI take the same shape. See [[code_type|Code Type]] for the full grammar, including the base64 alternative form.+Expression can be filled in directly as a text constant, using [[Code Type]]'​s own raw string syntax -- the same ''​$"<​delimiter>​( raw_characters )<​delimiter>"''​ form used by String constants. This is also the form the Dinamica EGO GUI's dedicated code editor generates when it writes the Expression port's value, so a hand-written script and one produced by the GUI take the same shape. See [[Code Type]] for the full grammar, including the base64 alternative form.
  
 The following counts the patches in a land cover areas table whose area meets a minimum threshold: The following counts the patches in a land cover areas table whose area meets a minimum threshold:
Line 246: Line 246:
 </​code>​ </​code>​
  
-Here landCoverAreas is bound to t1 and minimumArea to v1, each through a [[number_table|Number Table]] or [[number_value|Number Value]] hook. Calculate Python Expression returns a Struct containing all values assigned to dinamica.outputs;​ the ExtractStructNumber functor then pulls the patchCount entry out of that struct by name. See "​Retrieving outputs"​ above for the full list of extraction functors.+Here landCoverAreas is bound to t1 and minimumArea to v1, each through a [[Number Table]] or [[Number Value]] hook. Calculate Python Expression returns a Struct containing all values assigned to dinamica.outputs;​ the ExtractStructNumber functor then pulls the patchCount entry out of that struct by name. See "​Retrieving outputs"​ above for the full list of extraction functors.
  
 A more involved example: installing numpy to compute area statistics for a land cover patches table and flag outlier patches, then retrieving both the scalar statistics and the resulting table: A more involved example: installing numpy to compute area statistics for a land cover patches table and flag outlier patches, then retrieving both the scalar statistics and the resulting table:
Line 277: Line 277:
 </​code>​ </​code>​
  
-Here landCoverPatches is bound to t1 through a single [[number_table|Number Table]] hook.+Here landCoverPatches is bound to t1 through a single [[Number Table]] hook.
  
 ===== Internal Name ===== ===== Internal Name =====
  
 CalculatePythonExpression CalculatePythonExpression