Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
python_coupling [2020/02/17 23:51] argemiro created |
python_coupling [2026/07/18 02:29] (current) hermann |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | {{ :logo_logo.png?400 |}} | ||
| + | |||
| ====== Dinamica EGO and Python Coupling ====== | ====== Dinamica EGO and Python Coupling ====== | ||
| - | O suporte ao Python (atualmente na versão 3.7) está presente no ramo "Python" nos repositórios (em cima do ramo "Tasks"). Para compilar o ramo, é necessário ter as dependências do Python no dff_dependencies_windows. A versão contendo as dependências pode ser baixada em [[http://csr.ufmg.br/~romulo/dff_dependencies_windows_python.7z]]. Para execução, é necessário ter a pasta "PyEnvironment" dentro da pasta do Dinamica, o PyEnvironment também pode ser obtido em [[http://csr.ufmg.br/~romulo/PyEnvironment.7z]]. | + | Dinamica EGO can run arbitrary Python code as part of a model through the [[Calculate Python Expression]] functor. This lesson walks through a complete example; for the full reference — including the ''dinamica.inputs''/''dinamica.outputs'' mechanism, all available utilities, and how to retrieve the results back into the model — see [[Calculate Python Expression]]. |
| - | === Exemplo: Calculate Python Expression === | + | ===== Example ===== |
| - | Uma expressão que pode ser usada: | + | The example below installs ''numpy'' and uses it to compute area statistics for a table of land cover patches, then returns both summary values and a table of outlier patches — something considerably more convenient with ''numpy'' than with plain Python loops. |
| - | <code> | + | |
| - | dinamica.package("numpy") | + | |
| - | a = numpy.arange(15).reshape(3, 5) | + | The input, ''t1'', is a table of land cover patches with columns ''PatchId*'' and ''Area''. Inside the ''CalculatePythonExpression'' container, ''t1'' must be provided by a [[Number Table]] hook connected to the actual table functor — this is what makes the table available to the expression as ''dinamica.inputs["t1"]''. See [[calculate_python_expression#expression_inputs|Expression inputs]] for the full hook mechanism. |
| - | print(a) | + | |
| - | print(dinamica.inputs) | + | Install ''numpy'' and load the ''Area'' column into an array, skipping the header row: |
| - | for row in dinamica.inputs["t1"]: | + | |
| - | print(row) | + | |
| - | for row in dinamica.inputs["t2"]: | + | <code> |
| - | print(row) | + | dinamica.package("numpy") |
| - | dinamica.outputs["teste"] = 2 | + | areas = numpy.array([row[1] for row in dinamica.inputs["t1"][1:]]) |
| - | dinamica.outputs["teste2"] = 2.5 | + | |
| - | dinamica.outputs["teste3"] = 'a' | + | |
| - | dinamica.outputs["outraSaida"] = "yoyo" | + | |
| - | dinamica.outputs["tabela"] = dinamica.prepareTable(dinamica.inputs["t1"], 3) | + | |
| - | dinamica.outputs["lut"] = dinamica.prepareLookupTable(dinamica.inputs["t2"]) | + | |
| </code> | </code> | ||
| - | onde: | + | Compute the mean and standard deviation of patch area: |
| <code> | <code> | ||
| - | dinamica.package("numpy") | + | meanArea = float(numpy.mean(areas)) |
| + | stdArea = float(numpy.std(areas)) | ||
| </code> | </code> | ||
| - | Pede ao PIP que instale o pacote numpy e faça o import. | + | |
| - | \\ | + | Flag patches whose area lies more than two standard deviations from the mean, using ''numpy'''s vectorized comparison instead of a manual loop: |
| <code> | <code> | ||
| - | print(dinamica.inputs) | + | isOutlier = numpy.abs(areas - meanArea) > 2 * stdArea |
| </code> | </code> | ||
| - | Imprime o vetor com todas as entradas passadas pelo Dinamica. | + | |
| - | \\ | + | Return the two summary statistics as scalar outputs: |
| <code> | <code> | ||
| - | dinamica.outputs["teste2"] = 2.5 | + | dinamica.outputs["meanArea"] = meanArea |
| + | dinamica.outputs["stdArea"] = stdArea | ||
| </code> | </code> | ||
| - | Coloca uma saída na struct com nome "teste2", contendo uma double com valor 2.5 | + | |
| - | \\ | + | Build and return a table containing only the outlier patches: |
| <code> | <code> | ||
| - | dinamica.outputs["tabela"] = dinamica.prepareTable(dinamica.inputs["t1"], 3) | + | header = dinamica.inputs["t1"][0] |
| + | outlierRows = [row for row, flagged in zip(dinamica.inputs["t1"][1:], isOutlier) if flagged] | ||
| + | outlierTable = [header] + outlierRows | ||
| + | |||
| + | dinamica.outputs["outlierPatches"] = dinamica.prepareTable(outlierTable, 1) | ||
| </code> | </code> | ||
| - | Coloca uma saída na struct com nome "tabela", contendo uma tabela com 3 colunas de chave. Essa função não é necessária se a tabela já estiver com os '*' nos nomes da coluna (portanto o usuário poderia fazer apenas dinamica.outputs["teste2"] = dinamica.inputs["t1"]). Toda tabela no Python é tratada como uma lista de listas, onde cada lista interna corresponde a uma **linha** da tabela. | + | |
| - | \\ | + | The complete expression: |
| <code> | <code> | ||
| - | dinamica.outputs["lut"] = dinamica.prepareLookupTable(dinamica.inputs["t2"]) | + | dinamica.package("numpy") |
| + | |||
| + | areas = numpy.array([row[1] for row in dinamica.inputs["t1"][1:]]) | ||
| + | |||
| + | meanArea = float(numpy.mean(areas)) | ||
| + | stdArea = float(numpy.std(areas)) | ||
| + | |||
| + | isOutlier = numpy.abs(areas - meanArea) > 2 * stdArea | ||
| + | |||
| + | dinamica.outputs["meanArea"] = meanArea | ||
| + | dinamica.outputs["stdArea"] = stdArea | ||
| + | |||
| + | header = dinamica.inputs["t1"][0] | ||
| + | outlierRows = [row for row, flagged in zip(dinamica.inputs["t1"][1:], isOutlier) if flagged] | ||
| + | outlierTable = [header] + outlierRows | ||
| + | |||
| + | dinamica.outputs["outlierPatches"] = dinamica.prepareTable(outlierTable, 1) | ||
| </code> | </code> | ||
| - | Coloca uma saída na struct com nome "lut", contendo uma LookupTable (Não existe outra forma de passar uma LookupTable de volta). | + | |
| + | Back in the model, ''meanArea'', ''stdArea'', and ''outlierPatches'' are retrieved from the returned ''Struct'' using the ''ExtractStruct*'' family of functors — see [[calculate_python_expression#retrieving_outputs|Retrieving outputs]] for details. | ||
| + | |||
| + | ===== Reference ===== | ||
| + | |||
| + | The full set of Python utilities available inside the expression — ''dinamica.package()'', ''dinamica.prepareTable()'', ''dinamica.prepareLookupTable()'', and ''dinamica.toTable()'' — along with their parameters and additional examples of installing packages with specific versions or from custom sources, is documented on the [[calculate_python_expression#utilities|Calculate Python Expression]] page. | ||
| ---- | ---- | ||
| - | === Calculate Python Utilities === | + | ===Congratulations, you have successfully completed this lesson!=== |
| + | |||
| + | ☞[[lesson_21|Next Lesson]] | ||
| + | |||
| + | ☞[[:guidebook_start| Back to Guidebook Start]] | ||
| - | ^ Utility Name ^ Description ^ Parameters ^ | ||
| - | | package | It imports the module requested. | str packageName, str installPath=None, str loadPath=None | | ||
| - | | prepareTable | It returns the table prepared to output. Input Table has to be in the form [[[header1...headerN][line1]...[lineM]]] where the first list contains the headers of the table and all the other lists are lines containing the data. | list(list) inputTable, int numKeys | | ||
| - | | prepareLookupTable | It returns the lookup table prepared to output. The lut has to be in the form [[[key,value][line1]...[lineM]]] where the first list contains the headers of the table and all the other lists are lines containing the data. | list(list) lut | | ||
| - | | toTable | It returns a valid representation of dinamica table to output. Input Table can be: [[[header1...headerN][line1]...[lineM]]] where the first list contains the headers of the table and all the other lists are lines containing the data; {header1: [valuesOfColumn1], header2: [valuesOfColumn2]...} where the valuesOfComlumn# are all values of that column in table; [[(header1...headerN)(line)...(lineM)]] where the first tuple contains the headers of the table and all the other tuples are lines containing the data; [value1, value2, ..., valueN], those are the values for a lookup table with sequential key; pandas.Dataframe is a commom structure table used to manipulate CSVs; numpy.array is a commom structure for matrix, that can be tables as well. The first line of matrix needs to be the table header. | list(list);dict(list);list(tuple);list;pandas.DataFrame;numpy.array inputTable | | ||