diff --git a/.editorconfig b/.editorconfig index 50f3a56..97f7334 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,17 +1,19 @@ # EditorConfig is awesome: https://EditorConfig.org -[*.{js,json,yml}] +[*] charset = utf-8 end_of_line = crlf -indent_style = tabs -indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true -[*.{yaml,yml}] -charset = utf-8 -end_of_line = crlf +[*.js] +indent_style = tabs +indent_size = 2 + +[*.{yaml,yml,json}] indent_style = spaces indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true \ No newline at end of file + +[src/processes/*.json] +indent_style = spaces +indent_size = 4 diff --git a/src/processes/absolute.json b/src/processes/absolute.json index 3b6e91d..793b010 100644 --- a/src/processes/absolute.json +++ b/src/processes/absolute.json @@ -1,7 +1,7 @@ { "id": "absolute", "summary": "Absolute value", - "description": "Computes the absolute value of a real number `x`, which is the \"unsigned\" portion of x and often denoted as *|x|*.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the absolute value of a real number `x`, which is the \"unsigned\" portion of `x` and often denoted as *|x|*.\n\nThe no-data value `null` is passed through and therefore gets propagated.", "categories": [ "math" ], diff --git a/src/processes/add.json b/src/processes/add.json index 58db5f2..ac65541 100644 --- a/src/processes/add.json +++ b/src/processes/add.json @@ -1,7 +1,7 @@ { "id": "add", "summary": "Addition of two numbers", - "description": "Sums up the two numbers `x` and `y` (*x + y*) and returns the computed sum.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", + "description": "Sums up the two numbers `x` and `y` (*`x + y`*) and returns the computed sum.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", "categories": [ "math" ], diff --git a/src/processes/add_dimension.json b/src/processes/add_dimension.json index 727456b..6b5f2c4 100644 --- a/src/processes/add_dimension.json +++ b/src/processes/add_dimension.json @@ -1,7 +1,7 @@ { "id": "add_dimension", "summary": "Add a new dimension", - "description": "Adds a new named dimension to the data cube.\n\nAfterwards, the dimension can be referenced with the specified `name`. If a dimension with the specified name exists, the process fails with a `DimensionExists` error. The dimension label of the dimension is set to the specified `label`.", + "description": "Adds a new named dimension to the data cube.\n\nAfterwards, the dimension can be referred to with the specified `name`. If a dimension with the specified name exists, the process fails with a `DimensionExists` exception. The dimension label of the dimension is set to the specified `label`.", "categories": [ "cubes" ], @@ -39,9 +39,10 @@ "schema": { "type": "string", "enum": [ + "bands", + "geometry", "spatial", "temporal", - "bands", "other" ] }, @@ -61,4 +62,4 @@ "message": "A dimension with the specified name already exists." } } -} \ No newline at end of file +} diff --git a/src/processes/aggregate_temporal_frequency.json b/src/processes/aggregate_temporal_frequency.json deleted file mode 100644 index 5436350..0000000 --- a/src/processes/aggregate_temporal_frequency.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "id": "aggregate_temporal_frequency", - "summary": "Temporal aggregations based on frequencies", - "description": "Computes a temporal aggregation based on calendar hierarchies such as year, month, week or seasons. For other calendar hierarchies ``aggregate_temporal()`` can be used.\n\nFor each interval, all data along the dimension will be passed through the reducer.\n\nIf the dimension is not set or is set to `null`, the data cube is expected to only have one temporal dimension.", - "categories": [ - "aggregate & resample", - "climatology", - "cubes" - ], - "parameters": [ - { - "name": "data", - "description": "A data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "frequency", - "description": "The time intervals to aggregate. The following pre-defined values are available:\n\n* `hourly`: Hour of the day\n* `daily`: Day of the year\n* `weekly`: Week of the year\n* `monthly`: Month of the year\n* `yearly`: Proleptic years\n* `seasons`: Refers to three month periods of the calendar seasons (December - February, March - May, June - August, September - November).\n* `tropical_seasons`: Refers to the six month periods of the tropical seasons (November - April, Mai - October).", - "schema": { - "type": "string", - "enum": [ - "hourly", - "daily", - "weekly", - "monthly", - "yearly", - "seasons", - "tropical_seasons" - ] - } - }, - { - "name": "reducer", - "description": "A reducer to be applied on all values along the specified dimension. A reducer is a single process such as ``mean()`` or a set of processes, which computes a single value for a list of values, see the category 'reducer' for such processes.", - "schema": { - "type": "object", - "subtype": "process-graph", - "parameters": [ - { - "name": "data", - "description": "A labeled array with elements of any type.", - "schema": { - "type": "array", - "subtype": "labeled-array", - "items": { - "description": "Any data type." - } - } - }, - { - "name": "context", - "description": "Additional data passed by the user.", - "schema": { - "description": "Any data type." - }, - "optional": true, - "default": null - } - ] - } - }, - { - "name": "dimension", - "description": "The name of the temporal dimension for aggregation. All data along the dimension will be passed through the specified reducer. If the dimension is not set or set to `null`, the data cube is expected to only have one temporal dimension. Fails with a `TooManyDimensions` error if it has more dimensions. Fails with a `DimensionNotAvailable` error if the specified dimension does not exist.\n\n**Note:** The default dimensions a data cube provides are described in the collection's metadata field `cube:dimensions`.", - "schema": { - "type": [ - "string", - "null" - ] - }, - "default": null, - "optional": true - }, - { - "name": "context", - "description": "Additional data to be passed to the reducer.", - "schema": { - "description": "Any data type." - }, - "optional": true, - "default": null - } - ], - "returns": { - "description": "A data cube with potentially lower resolution and cardinality, but the same number of dimensions as the original data cube. The specified temporal dimension has the following dimension labels (`YYYY` = four-digit year, `MM` = two-digit month, `DD` two-digit day of month):\n\n* `hourly`: `YYYY-MM-DD-0` - `YYYY-MM-DD-23`\n* `daily`: `YYYY-1` - `YYYY-365`\n* `weekly`: `YYYY-1` - `YYYY-52`\n* `monthly`: `YYYY-1` - `YYYY-12`\n* `yearly`: `YYYY`\n* `seasons`: `YYYY-djf` (December - February), `YYYY-mam` (March - May), `YYYY-jja` (June - August), `YYYY-son` (September - November).\n* `tropical_seasons`: `YYYY-ndjfma` (November - April), `YYYY-mjjaso` (May - October).", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - "exceptions": { - "TooManyDimensions": { - "message": "The data cube contains multiple temporal dimensions. The parameter `dimension` must be specified." - }, - "DimensionNotAvailable": { - "message": "A dimension with the specified name does not exist." - }, - "DistinctDimensionLabelsRequired": { - "message": "The dimension labels have duplicate values. Distinct labels must be specified." - } - }, - "links": [ - { - "href": "https://open-eo.github.io/openeo-api/glossary/#aggregation-and-resampling", - "rel": "about", - "title": "Aggregation explained in the openEO glossary" - } - ] -} \ No newline at end of file diff --git a/src/processes/aggregate_temporal_frequency.js b/src/processes/aggregate_temporal_period.js similarity index 93% rename from src/processes/aggregate_temporal_frequency.js rename to src/processes/aggregate_temporal_period.js index 76c6fe6..c8f00d2 100644 --- a/src/processes/aggregate_temporal_frequency.js +++ b/src/processes/aggregate_temporal_period.js @@ -1,7 +1,7 @@ import GeeProcess from '../processgraph/process.js'; import Commons from '../processgraph/commons.js'; -export default class aggregate_temporal_frequency extends GeeProcess { +export default class aggregate_temporal_period extends GeeProcess { reduce(node, imageCollection) { const callback = node.getCallback('reducer'); @@ -25,10 +25,10 @@ export default class aggregate_temporal_frequency extends GeeProcess { const ee = node.ee; // STEP 1: Get parameters and set some variables const dc = node.getDataCube('data'); - const frequency = node.getArgument('frequency'); + const period = node.getArgument('period'); // STEP 2: prepare image collection with aggregation label - const images = Commons.setAggregationLabels(node, dc.imageCollection(), frequency); + const images = Commons.setAggregationLabels(node, dc.imageCollection(), period); // STEP 3: aggregate based on aggregation label diff --git a/src/processes/aggregate_temporal_period.json b/src/processes/aggregate_temporal_period.json new file mode 100644 index 0000000..176fc29 --- /dev/null +++ b/src/processes/aggregate_temporal_period.json @@ -0,0 +1,115 @@ +{ + "id": "aggregate_temporal_period", + "summary": "Temporal aggregations based on calendar hierarchies", + "description": "Computes a temporal aggregation based on calendar hierarchies such as years, months or seasons. For other calendar hierarchies ``aggregate_temporal()`` can be used.\n\nFor each interval, all data along the dimension will be passed through the reducer.\n\nIf the dimension is not set or is set to `null`, the data cube is expected to only have one temporal dimension.", + "categories": [ + "aggregate", + "climatology", + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "The source data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "period", + "description": "The time intervals to aggregate. The following pre-defined values are available:\n\n* `hour`: Hour of the day\n* `day`: Day of the year\n* `week`: Week of the year\n* `dekad`: Ten day periods, counted per year with three periods per month (day 1 - 10, 11 - 20 and 21 - end of month). The third dekad of the month can range from 8 to 11 days. For example, the third dekad of a year spans from January 21 till January 31 (11 days), the fourth dekad spans from February 1 till February 10 (10 days) and the sixth dekad spans from February 21 till February 28 or February 29 in a leap year (8 or 9 days respectively).\n* `month`: Month of the year\n* `season`: Three month periods of the calendar seasons (December - February, March - May, June - August, September - November).\n* `tropical-season`: Six month periods of the tropical seasons (November - April, May - October).\n* `year`: Proleptic years\n* `decade`: Ten year periods ([0-to-9 decade](https://en.wikipedia.org/wiki/Decade#0-to-9_decade)), from a year ending in a 0 to the next year ending in a 9.\n* `decade-ad`: Ten year periods ([1-to-0 decade](https://en.wikipedia.org/wiki/Decade#1-to-0_decade)) better aligned with the anno Domini (AD) calendar era, from a year ending in a 1 to the next year ending in a 0.", + "schema": { + "type": "string", + "enum": [ + "hour", + "day", + "week", + "month", + "season", + "tropical-season", + "year" + ] + } + }, + { + "name": "reducer", + "description": "A reducer to be applied for the values contained in each period. A reducer is a single process such as ``mean()`` or a set of processes, which computes a single value for a list of values, see the category 'reducer' for such processes. Periods may not contain any values, which for most reducers leads to no-data (`null`) values by default.", + "schema": { + "type": "object", + "subtype": "process-graph", + "parameters": [ + { + "name": "data", + "description": "A labeled array with elements of any type. If there's no data for the period, the array is empty.", + "schema": { + "type": "array", + "subtype": "labeled-array", + "items": { + "description": "Any data type." + } + } + }, + { + "name": "context", + "description": "Additional data passed by the user.", + "schema": { + "description": "Any data type." + }, + "optional": true, + "default": null + } + ], + "returns": { + "description": "The value to be set in the new data cube.", + "schema": { + "description": "Any data type." + } + } + } + }, + { + "name": "dimension", + "description": "The name of the temporal dimension for aggregation. All data along the dimension is passed through the specified reducer. If the dimension is not set or set to `null`, the source data cube is expected to only have one temporal dimension. Fails with a `TooManyDimensions` exception if it has more dimensions. Fails with a `DimensionNotAvailable` exception if the specified dimension does not exist.", + "schema": { + "type": [ + "string", + "null" + ] + }, + "optional": true, + "default": null + }, + { + "name": "context", + "description": "Additional data to be passed to the reducer.", + "schema": { + "description": "Any data type." + }, + "optional": true, + "default": null + } + ], + "returns": { + "description": "A new data cube with the same dimensions. The dimension properties (name, type, labels, reference system and resolution) remain unchanged, except for the resolution and dimension labels of the given temporal dimension. The specified temporal dimension has the following dimension labels (`YYYY` = four-digit year, `MM` = two-digit month, `DD` two-digit day of month):\n\n* `hour`: `YYYY-MM-DD-00` - `YYYY-MM-DD-23`\n* `day`: `YYYY-001` - `YYYY-365`\n* `week`: `YYYY-01` - `YYYY-52`\n* `dekad`: `YYYY-00` - `YYYY-36`\n* `month`: `YYYY-01` - `YYYY-12`\n* `season`: `YYYY-djf` (December - February), `YYYY-mam` (March - May), `YYYY-jja` (June - August), `YYYY-son` (September - November).\n* `tropical-season`: `YYYY-ndjfma` (November - April), `YYYY-mjjaso` (May - October).\n* `year`: `YYYY`\n* `decade`: `YYY0`\n* `decade-ad`: `YYY1`\n\nThe dimension labels in the new data cube are complete for the whole extent of the source data cube. For example, if `period` is set to `day` and the source data cube has two dimension labels at the beginning of the year (`2020-01-01`) and the end of a year (`2020-12-31`), the process returns a data cube with 365 dimension labels (`2020-001`, `2020-002`, ..., `2020-365`). In contrast, if `period` is set to `day` and the source data cube has just one dimension label `2020-01-05`, the process returns a data cube with just a single dimension label (`2020-005`).", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + "exceptions": { + "TooManyDimensions": { + "message": "The data cube contains multiple temporal dimensions. The parameter `dimension` must be specified." + }, + "DimensionNotAvailable": { + "message": "A dimension with the specified name does not exist or no temporal dimension is available." + } + }, + "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html#aggregate", + "rel": "about", + "title": "Aggregation explained in the openEO documentation" + } + ] +} diff --git a/src/processes/anomaly.js b/src/processes/anomaly.js index 1856d92..3c4a3cf 100644 --- a/src/processes/anomaly.js +++ b/src/processes/anomaly.js @@ -9,9 +9,9 @@ export default class anomaly extends GeeProcess { const normalsLabels = node.ee.List(normalsDataCube.dimT().getValues()); const normalsCollection = normalsDataCube.imageCollection(); const normals = normalsCollection.toList(normalsCollection.size()); - const frequency = node.getArgument('frequency'); + const period = node.getArgument('period'); - let images = Commons.setAggregationLabels(node, dc.imageCollection(), frequency); + let images = Commons.setAggregationLabels(node, dc.imageCollection(), period); images = images.map(image => { const label = image.get('label'); const normal = normals.get(normalsLabels.indexOf(label)); diff --git a/src/processes/anomaly.json b/src/processes/anomaly.json index 0a161df..306fe48 100644 --- a/src/processes/anomaly.json +++ b/src/processes/anomaly.json @@ -1,7 +1,7 @@ { "id": "anomaly", - "summary": "Computes anomalies", - "description": "Computes anomalies based on normals for a specific temporal frequency.", + "summary": "Compute anomalies", + "description": "Computes anomalies based on normals for temporal periods. It compares the data for each label in the temporal dimension with the corresponding data in the normals data cube by subtracting the normal from the data.", "categories": [ "climatology", "cubes", @@ -10,7 +10,7 @@ "parameters": [ { "name": "data", - "description": "A data cube with exactly one temporal dimension and the following dimension labels for the given frequency (`YYYY` = four-digit year, `MM` = two-digit month, `DD` two-digit day of month):\n\n* `hourly`: `YYYY-MM-DD-0` - `YYYY-MM-DD-23`\n* `daily`: `YYYY-1` - `YYYY-365`\n* `weekly`: `YYYY-1` - `YYYY-52`\n* `monthly`: `YYYY-1` - `YYYY-12`\n* `yearly`: `YYYY`\n* `single_period` / `climatology_period`: A single dimension label with any name is expected.\n* `seasons`: `YYYY-djf` (December - February), `YYYY-mam` (March - May), `YYYY-jja` (June - August), `YYYY-son` (September - November)\n* `tropical_seasons`: `YYYY-ndjfma` (November - April), `YYYY-mjjaso` (May - October)\n\n``aggregate_temporal_frequency()`` can compute such a data cube.", + "description": "A data cube with exactly one temporal dimension and the following dimension labels for the given period (`YYYY` = four-digit year, `MM` = two-digit month, `DD` two-digit day of month):\n\n* `hour`: `YYYY-MM-DD-00` - `YYYY-MM-DD-23`\n* `day`: `YYYY-001` - `YYYY-365`\n* `week`: `YYYY-01` - `YYYY-52`\n* `dekad`: `YYYY-00` - `YYYY-36`\n* `month`: `YYYY-01` - `YYYY-12`\n* `season`: `YYYY-djf` (December - February), `YYYY-mam` (March - May), `YYYY-jja` (June - August), `YYYY-son` (September - November).\n* `tropical-season`: `YYYY-ndjfma` (November - April), `YYYY-mjjaso` (May - October).\n* `year`: `YYYY`\n* `decade`: `YYY0`\n* `decade-ad`: `YYY1`\n* `single-period` / `climatology-period`: Any\n\n``aggregate_temporal_period()`` can compute such a data cube.", "schema": { "type": "object", "subtype": "raster-cube" @@ -18,36 +18,34 @@ }, { "name": "normals", - "description": "A data cube with normals, e.g. daily, monthly or yearly values computed from a process such as ``climatological_normal()``. Must contain exactly one temporal dimension with the following dimension labels for the given frequency:\n\n* `hourly`: `0` - `23`\n* `daily`: `1` - `365`\n* `weekly`: `1` - `52`\n* `monthly`: `1` - `12`\n* `yearly`: Four-digit year numbers\n* `single_period` / `climatology_period`: A single dimension label with any name is expected.\n* `seasons`: `djf` (December - February), `mam` (March - May), `jja` (June - August), `son` (September - November)\n* `tropical_seasons`: `ndjfma` (November - April), `mjjaso` (May - October)", + "description": "A data cube with normals, e.g. daily, monthly or yearly values computed from a process such as ``climatological_normal()``. Must contain exactly one temporal dimension with the following dimension labels for the given period:\n\n* `hour`: `00` - `23`\n* `day`: `001` - `365`\n* `week`: `01` - `52`\n* `dekad`: `00` - `36`\n* `month`: `01` - `12`\n* `season`: `djf` (December - February), `mam` (March - May), `jja` (June - August), `son` (September - November)\n* `tropical-season`: `ndjfma` (November - April), `mjjaso` (May - October)\n* `year`: Four-digit year numbers\n* `decade`: Four-digit year numbers, the last digit being a `0`\n* `decade-ad`: Four-digit year numbers, the last digit being a `1`\n* `single-period` / `climatology-period`: A single dimension label with any name is expected.", "schema": { "type": "object", "subtype": "raster-cube" } }, { - "name": "frequency", - "description": "Specifies the time intervals available in the data cubes. The following options are available:\n\n* `hourly`: Hour of the day\n* `daily`: Day of the year\n* `weekly`: Week of the year\n* `monthly`: Month of the year\n* `yearly`: Proleptic years\n* `seasons`: Refers to three month periods of the calendar seasons (December - February, March - May, June - August, September - November).\n* `tropical_seasons`: Refers to the six month periods of the tropical seasons (November - April, Mai - October).", + "name": "period", + "description": "Specifies the time intervals available in the normals data cube. The following options are available:\n\n* `hour`: Hour of the day\n* `day`: Day of the year\n* `week`: Week of the year\n* `dekad`: Ten day periods, counted per year with three periods per month (day 1 - 10, 11 - 20 and 21 - end of month). The third dekad of the month can range from 8 to 11 days. For example, the fourth dekad is Feb, 1 - Feb, 10 each year.\n* `month`: Month of the year\n* `season`: Three month periods of the calendar seasons (December - February, March - May, June - August, September - November).\n* `tropical-season`: Six month periods of the tropical seasons (November - April, May - October).\n* `year`: Proleptic years\n* `decade`: Ten year periods ([0-to-9 decade](https://en.wikipedia.org/wiki/Decade#0-to-9_decade)), from a year ending in a 0 to the next year ending in a 9.\n* `decade-ad`: Ten year periods ([1-to-0 decade](https://en.wikipedia.org/wiki/Decade#1-to-0_decade)) better aligned with the anno Domini (AD) calendar era, from a year ending in a 1 to the next year ending in a 0.\n* `single-period` / `climatology-period`: A single period of arbitrary length", "schema": { "type": "string", "enum": [ - "hourly", - "daily", - "weekly", - "monthly", - "yearly", - "single_period", - "climatology_period", - "seasons", - "tropical_seasons" + "hour", + "day", + "week", + "month", + "season", + "tropical-season", + "year" ] } } ], "returns": { - "description": "A data cube. The cardinality, resolution, the number of dimensions and the dimension labels are the same as for the original data cube.", + "description": "A data cube with the same dimensions. The dimension properties (name, type, labels, reference system and resolution) remain unchanged.", "schema": { "type": "object", "subtype": "raster-cube" } } -} \ No newline at end of file +} diff --git a/src/processes/apply.json b/src/processes/apply.json index 3150066..b330686 100644 --- a/src/processes/apply.json +++ b/src/processes/apply.json @@ -1,60 +1,73 @@ { - "id": "apply", - "summary": "Apply a process to each pixel", - "description": "Applies a *unary* process to each pixel value in the data cube (i.e. a local operation). A unary process takes a single value and returns a single value, for example ``abs()`` or ``linear_scale_range()``. In contrast, the process ``apply_dimension()`` applies a process to all pixel values along a particular dimension.", - "categories": [ - "cubes" - ], - "parameters": [ - { - "name": "data", - "description": "A data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "process", - "description": "A unary process to be applied on each value, may consist of multiple sub-processes.", - "schema": { - "type": "object", - "subtype": "process-graph", - "parameters": [ - { - "name": "x", - "description": "The value to process.", + "id": "apply", + "summary": "Apply a process to each value", + "description": "Applies a process to each value in the data cube (i.e. a local operation). In contrast, the process ``apply_dimension()`` applies a process to all values along a particular dimension.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "A data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "process", + "description": "A process that accepts and returns a single value and is applied on each individual value in the data cube. The process may consist of multiple sub-processes and could, for example, consist of processes such as ``absolute()`` or ``linear_scale_range()``.", "schema": { - "description": "Any data type." + "type": "object", + "subtype": "process-graph", + "parameters": [ + { + "name": "x", + "description": "The value to process.", + "schema": { + "description": "Any data type." + } + }, + { + "name": "context", + "description": "Additional data passed by the user.", + "schema": { + "description": "Any data type." + }, + "optional": true, + "default": null + } + ], + "returns": { + "description": "The value to be set in the new data cube.", + "schema": { + "description": "Any data type." + } + } } - }, - { + }, + { "name": "context", - "description": "Additional data passed by the user.", + "description": "Additional data to be passed to the process.", "schema": { - "description": "Any data type." + "description": "Any data type." }, "optional": true, "default": null - } - ] - } - }, - { - "name": "context", - "description": "Additional data to be passed to the process.", - "schema": { - "description": "Any data type." - }, - "optional": true, - "default": null - } - ], - "returns": { + } + ], + "returns": { "description": "A data cube with the newly computed values and the same dimensions. The dimension properties (name, type, labels, reference system and resolution) remain unchanged.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - } -} \ No newline at end of file + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html#apply", + "rel": "about", + "title": "Apply explained in the openEO documentation" + } + ] +} diff --git a/src/processes/arccos.json b/src/processes/arccos.json index a75c730..4cd498a 100644 --- a/src/processes/arccos.json +++ b/src/processes/arccos.json @@ -1,29 +1,32 @@ { "id": "arccos", "summary": "Inverse cosine", - "description": "Computes the arc cosine of `x`. The arc cosine is the inverse function of the cosine so that *arccos(cos(x)) = x*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the arc cosine of `x`. The arc cosine is the inverse function of the cosine so that *`arccos(cos(x)) = x`*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated. `NaN` is returned for values outside of the allowed range.", "categories": [ "math > trigonometric" ], "parameters": [ { "name": "x", - "description": "A number.", + "description": "A number in the range *[-1, 1]*.", "schema": { "type": [ "number", "null" - ] + ], + "minimum": -1, + "maximum": 1 } } ], "returns": { - "description": "The computed angle in radians.", + "description": "The computed angle in radians in the range *[0, Ï€]*.", "schema": { "type": [ "number", "null" - ] + ], + "minimum": 0 } }, "examples": [ @@ -41,4 +44,4 @@ "title": "Inverse cosine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/arcosh.json b/src/processes/arcosh.json index 6b5dc94..820b8cd 100644 --- a/src/processes/arcosh.json +++ b/src/processes/arcosh.json @@ -1,29 +1,31 @@ { "id": "arcosh", "summary": "Inverse hyperbolic cosine", - "description": "Computes the inverse hyperbolic cosine of `x`. It is the inverse function of the hyperbolic cosine so that *arcosh(cosh(x)) = x*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the inverse hyperbolic cosine of `x`. It is the inverse function of the hyperbolic cosine so that *`arcosh(cosh(x)) = x`*.\n\nThe no-data value `null` is passed through and therefore gets propagated. `NaN` is returned for values outside of the allowed range.", "categories": [ "math > trigonometric" ], "parameters": [ { "name": "x", - "description": "A number.", + "description": "A number in the range *[1, +∞)*.", "schema": { "type": [ "number", "null" ] - } + }, + "minimum": 1 } ], "returns": { - "description": "The computed angle in radians.", + "description": "The computed hyperbolic angle in radians in the range *[0, +∞)*.", "schema": { "type": [ "number", "null" - ] + ], + "minimum": 0 } }, "examples": [ @@ -41,4 +43,4 @@ "title": "Inverse hyperbolic cosine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/arcsin.json b/src/processes/arcsin.json index b85e0ea..2c772a0 100644 --- a/src/processes/arcsin.json +++ b/src/processes/arcsin.json @@ -1,24 +1,26 @@ { "id": "arcsin", "summary": "Inverse sine", - "description": "Computes the arc sine of `x`. The arc sine is the inverse function of the sine so that *arcsin(sin(x)) = x*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the arc sine of `x`. The arc sine is the inverse function of the sine so that *`arcsin(sin(x)) = x`*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated. `NaN` is returned for values < -1 and > 1.", "categories": [ "math > trigonometric" ], "parameters": [ { "name": "x", - "description": "A number.", + "description": "A number in the range *[-1, 1]*.", "schema": { "type": [ "number", "null" - ] + ], + "minimum": -1, + "maximum": 1 } } ], "returns": { - "description": "The computed angle in radians.", + "description": "The computed angle in radians in the range *[-Ï€/2, Ï€/2]*.", "schema": { "type": [ "number", @@ -41,4 +43,4 @@ "title": "Inverse sine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/arctan.json b/src/processes/arctan.json index 6c9e2be..9461eba 100644 --- a/src/processes/arctan.json +++ b/src/processes/arctan.json @@ -1,7 +1,7 @@ { "id": "arctan", "summary": "Inverse tangent", - "description": "Computes the arc tangent of `x`. The arc tangent is the inverse function of the tangent so that *arctan(tan(x)) = x*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the arc tangent of `x`. The arc tangent is the inverse function of the tangent so that *`arctan(tan(x)) = x`*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", "categories": [ "math > trigonometric" ], @@ -18,7 +18,7 @@ } ], "returns": { - "description": "The computed angle in radians.", + "description": "The computed angle in radians in the range *(−π/2, Ï€/2)*.", "schema": { "type": [ "number", @@ -41,4 +41,4 @@ "title": "Inverse tangent explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/array_element.json b/src/processes/array_element.json index 389030b..8b70a2e 100644 --- a/src/processes/array_element.json +++ b/src/processes/array_element.json @@ -1,7 +1,7 @@ { "id": "array_element", "summary": "Get an element from an array", - "description": "Returns the element with the specified index or label from the array.\n\nEither the parameter `index` or `label` must be specified, otherwise the `ArrayElementParameterMissing` exception is thrown. If both parameters are set the `ArrayElementParameterConflict` exception is thrown.", + "description": "Gives the element with the specified index or label from the array.\n\nEither the parameter `index` or `label` must be specified, otherwise the `ArrayElementParameterMissing` exception is thrown. If both parameters are set the `ArrayElementParameterConflict` exception is thrown.", "categories": [ "arrays", "reducer" @@ -21,13 +21,14 @@ "name": "index", "description": "The zero-based index of the element to retrieve.", "schema": { - "type": "integer" + "type": "integer", + "minimum": 0 }, "optional": true }, { "name": "label", - "description": "The label of the element to retrieve.", + "description": "The label of the element to retrieve. Throws an `ArrayNotLabeled` exception, if the given array is not a labeled array and this parameter is set.", "schema": [ { "type": "number" @@ -59,10 +60,13 @@ "message": "The array has no element with the specified index or label." }, "ArrayElementParameterMissing": { - "message": "The process 'array_element' requires either the 'index' or 'labels' parameter to be set." + "message": "The process `array_element` requires either the `index` or `labels` parameter to be set." }, "ArrayElementParameterConflict": { - "message": "The process 'array_element' only allows that either the 'index' or the 'labels' parameter is set." + "message": "The process `array_element` only allows that either the `index` or the `labels` parameter is set." + }, + "ArrayNotLabeled": { + "message": "The array is not a labeled array, but the `label` parameter is set. Use the `index` instead." } }, "examples": [ diff --git a/src/processes/arsinh.json b/src/processes/arsinh.json index 1475772..2b7942d 100644 --- a/src/processes/arsinh.json +++ b/src/processes/arsinh.json @@ -1,7 +1,7 @@ { "id": "arsinh", "summary": "Inverse hyperbolic sine", - "description": "Computes the inverse hyperbolic sine of `x`. It is the inverse function of the hyperbolic sine so that *arsinh(sinh(x)) = x*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the inverse hyperbolic sine of `x`. It is the inverse function of the hyperbolic sine so that *`arsinh(sinh(x)) = x`*.\n\nThe no-data value `null` is passed through and therefore gets propagated.", "categories": [ "math > trigonometric" ], @@ -18,7 +18,7 @@ } ], "returns": { - "description": "The computed angle in radians.", + "description": "The computed hyperbolic angle in radians.", "schema": { "type": [ "number", @@ -41,4 +41,4 @@ "title": "Inverse hyperbolic sine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/artanh.json b/src/processes/artanh.json index add380b..6308290 100644 --- a/src/processes/artanh.json +++ b/src/processes/artanh.json @@ -1,24 +1,26 @@ { "id": "artanh", "summary": "Inverse hyperbolic tangent", - "description": "Computes the inverse hyperbolic tangent of `x`. It is the inverse function of the hyperbolic tangent so that *artanh(tanh(x)) = x*.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the inverse hyperbolic tangent of `x`. It is the inverse function of the hyperbolic tangent so that *`artanh(tanh(x)) = x`*.\n\nThe no-data value `null` is passed through and therefore gets propagated. `NaN` is returned for values outside of the allowed range. The computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. Therefore, `x` = 1 results in +infinity and `x` = 0 results in -infinity. Otherwise, an exception is thrown.", "categories": [ "math > trigonometric" ], "parameters": [ { "name": "x", - "description": "A number.", + "description": "A number in the range *(-1, 1)*.", "schema": { "type": [ "number", "null" - ] + ], + "minimumExclusive": -1, + "maximumExclusive": 1 } } ], "returns": { - "description": "The computed angle in radians.", + "description": "The computed hyperbolic angle in radians.", "schema": { "type": [ "number", @@ -39,6 +41,11 @@ "rel": "about", "href": "http://mathworld.wolfram.com/InverseHyperbolicTangent.html", "title": "Inverse hyperbolic tangent explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/4610935", + "title": "IEEE Standard 754-2008 for Floating-Point Arithmetic" } ] -} \ No newline at end of file +} diff --git a/src/processes/ceil.json b/src/processes/ceil.json index 18bf21a..7c01cf4 100644 --- a/src/processes/ceil.json +++ b/src/processes/ceil.json @@ -1,62 +1,62 @@ { - "id": "ceil", - "summary": "Round fractions up", - "description": "The least integer greater than or equal to the number `x`.\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math > rounding" - ], - "parameters": [ - { - "name": "x", - "description": "A number to round up.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The number rounded up.", - "schema": { - "type": [ - "integer", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 0 - }, - "returns": 0 + "id": "ceil", + "summary": "Round fractions up", + "description": "The least integer greater than or equal to the number `x`.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math > rounding" + ], + "parameters": [ + { + "name": "x", + "description": "A number to round up.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The number rounded up.", + "schema": { + "type": [ + "integer", + "null" + ] + } }, - { - "arguments": { - "x": 3.5 - }, - "returns": 4 - }, - { - "arguments": { - "x": -0.4 - }, - "returns": 0 - }, - { - "arguments": { - "x": -3.5 - }, - "returns": -3 - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/CeilingFunction.html", - "title": "Ceiling explained by Wolfram MathWorld" - } - ] + "examples": [ + { + "arguments": { + "x": 0 + }, + "returns": 0 + }, + { + "arguments": { + "x": 3.5 + }, + "returns": 4 + }, + { + "arguments": { + "x": -0.4 + }, + "returns": 0 + }, + { + "arguments": { + "x": -3.5 + }, + "returns": -3 + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/CeilingFunction.html", + "title": "Ceiling explained by Wolfram MathWorld" + } + ] } \ No newline at end of file diff --git a/src/processes/climatological_normal.js b/src/processes/climatological_normal.js index e557093..07097ee 100644 --- a/src/processes/climatological_normal.js +++ b/src/processes/climatological_normal.js @@ -8,7 +8,7 @@ export default class climatological_normal extends GeeProcess { executeSync(node) { const ee = node.ee; const dc = node.getDataCube('data'); - const frequency = node.getArgument('frequency'); + const period = node.getArgument('period'); // Get a data cube restricted to the climatological period (default: from 1981 to 2010) const climatologyPeriod = node.getArgument('climatology_period', ["1981", "2010"]).map(x => parseInt(x, 10)); @@ -16,16 +16,16 @@ export default class climatological_normal extends GeeProcess { let end = ee.Date(climatologyPeriod[1] + "-12-31"); let labels, range, geeFrequencyName, seasons, geeSeasons, earlyStart; - switch (frequency) { - case 'daily': + switch (period) { + case 'day': labels = range = Utils.sequence(1, 365); geeFrequencyName = "day_of_year"; break; - case 'monthly': + case 'month': labels = range = Utils.sequence(1, 12); geeFrequencyName = "month"; break; - case 'seasons': + case 'season': // Define seasons + labels seasons = GeeUtils.seasons(node); geeSeasons = ee.Dictionary(seasons); @@ -41,7 +41,7 @@ export default class climatological_normal extends GeeProcess { ); end = end.advance(-2, 'month'); break; - case 'tropical_seasons': + case 'tropical-season': // Define seasons + labels seasons = GeeUtils.tropicalSeasons(node); geeSeasons = ee.Dictionary(seasons); @@ -57,11 +57,11 @@ export default class climatological_normal extends GeeProcess { ); end = end.advance(-4, 'month'); break; - case 'climatology_period': - case 'yearly': // alias for climatology_period + case 'climatology-period': + case 'year': // alias for climatology-period range = [ee.List(climatologyPeriod)]; geeFrequencyName = "year"; - labels = ["climatology_period"]; + labels = ["climatology-period"]; break; } @@ -69,18 +69,18 @@ export default class climatological_normal extends GeeProcess { const normals = ee.List(range).map(x => { let calFilter = null; - switch (frequency) { - case 'climatology_period': - case 'yearly': // alias for climatology_period - case 'seasons': - case 'tropical_seasons': + switch (period) { + case 'climatology-period': + case 'year': // alias for climatology-period + case 'season': + case 'tropical-season': x = ee.List(x); calFilter = ee.Filter.calendarRange(x.get(0), x.get(-1), geeFrequencyName); break; } - switch (frequency) { - case 'seasons': - case 'tropical_seasons': + switch (period) { + case 'season': + case 'tropical-season': calFilter = ee.Filter(ee.Algorithms.If( ee.Number(x.reduce('min')).lt(1), ee.Filter.or(ee.Filter.calendarRange(ee.Number(x.get(0)).add(12), 12, 'month'), ee.Filter.calendarRange(1, x.get(-1), 'month')), diff --git a/src/processes/climatological_normal.json b/src/processes/climatological_normal.json index 51ea369..a7d0950 100644 --- a/src/processes/climatological_normal.json +++ b/src/processes/climatological_normal.json @@ -1,58 +1,56 @@ { "id": "climatological_normal", - "summary": "Computes climatology normals", - "description": "Climatological normal period is a usually 30-year average of a weather variable. Climatological normals are used as an average or baseline to evaluate climate events and provide context for yearly, monthly, daily or seasonal variability. The default climatology period is from 1981 until 2010 (both inclusive).", + "summary": "Compute climatology normals", + "description": "Climatological normal period is a usually 30 year average of a weather variable. Climatological normals are used as an average or baseline to evaluate climate events and provide context for yearly, monthly, daily or seasonal variability.", "categories": [ + "cubes", "climatology" ], "parameters": [ { "name": "data", - "description": "A data cube with exactly one temporal dimension. The datacube must span at least the temporal interval specified in the parameter `climatology_period`.\n\nSeasonal periods may span two consecutive years, e.g. temporal winter that includes months December, January and February. If the required months before the actual climate period are available, the season is taken into account. If not available, the first season is not taken into account and the seasonal mean is based on one year less than the other seasonal normals. The incomplete season at the end of the last year is never taken into account.", + "description": "A data cube with exactly one temporal dimension. The data cube must span at least the temporal interval specified in the parameter `climatology-period`.\n\nSeasonal periods may span two consecutive years, e.g. temporal winter that includes months December, January and February. If the required months before the actual climate period are available, the season is taken into account. If not available, the first season is not taken into account and the seasonal mean is based on one year less than the other seasonal normals. The incomplete season at the end of the last year is never taken into account.", "schema": { "type": "object", "subtype": "raster-cube" } }, { - "name": "frequency", - "description": "The time intervals to aggregate the average value for. The following pre-defined frequencies are supported:\n\n* `daily`: Day of the year\n* `monthly`: Month of the year\n* `climatology_period`: The period specified in the `climatology_period`.\n* `seasons`: Refers to three month periods of the calendar seasons (December - February, March - May, June - August, September - November).\n* `tropical_seasons`: Refers to the six month periods of the tropical seasons (November - April, Mai - October).", + "name": "period", + "description": "The time intervals to aggregate the average value for. The following pre-defined frequencies are supported:\n\n* `day`: Day of the year\n* `month`: Month of the year\n* `climatology-period`: The period specified in the `climatology-period`.\n* `season`: Three month periods of the calendar seasons (December - February, March - May, June - August, September - November).\n* `tropical-season`: Six month periods of the tropical seasons (November - April, May - October).", "schema": { "type": "string", "enum": [ - "daily", - "monthly", - "seasons", - "tropical_seasons", - "climatology_period" + "day", + "month", + "season", + "tropical-season", + "climatology-period" ] } }, { "name": "climatology_period", - "description": "Closed temporal interval. The first element of the array is the first year to be fully included in the temporal interval. The second element is the last year to be fully included in the temporal interval. The default period is from 1981 until 2010 (both inclusive).", + "description": "The climatology period as a closed temporal interval. The first element of the array is the first year to be fully included in the temporal interval. The second element is the last year to be fully included in the temporal interval.\n\nThe default climatology period is from 1981 until 2010 (both inclusive) right now, but this might be updated over time to what is commonly used in climatology. If you don't want to keep your research to be reproducible, please explicitly specify a period.", "schema": { "type": "array", - "subtype": "temporal-interval", + "uniqueItems": true, "minItems": 2, "maxItems": 2, "items": { - "type": "string", - "subtype": "year", - "minLength": 4, - "maxLength": 4, - "pattern": "^\\d{4}$" + "type": "integer", + "subtype": "year" } }, "default": [ - "1981", - "2010" + 1981, + 2010 ], "optional": true } ], "returns": { - "description": "A data cube with potentially cardinality, but the same resolution and number of dimensions as the original data cube. The temporal dimension has the following dimension labels:\n\n* `daily`: `1` - `365`\n* `monthly`: `1` - `12`\n* `climatology_period`: `climatology_period`\n* `seasons`: `djf` (December - February), `mam` (March - May), `jja` (June - August), `son` (September - November)\n* `tropical_seasons`: `ndjfma` (November - April), `mjjaso` (May - October)", + "description": "A data cube with the same dimensions. The dimension properties (name, type, labels, reference system and resolution) remain unchanged, except for the resolution and dimension labels of the temporal dimension. The temporal dimension has the following dimension labels:\n\n* `day`: `001` - `365`\n* `month`: `01` - `12`\n* `climatology-period`: `climatology-period`\n* `season`: `djf` (December - February), `mam` (March - May), `jja` (June - August), `son` (September - November)\n* `tropical-season`: `ndjfma` (November - April), `mjjaso` (May - October)", "schema": { "type": "object", "subtype": "raster-cube" @@ -65,4 +63,4 @@ "title": "Background information on climatology normal by Wikipedia" } ] -} \ No newline at end of file +} diff --git a/src/processes/clip.json b/src/processes/clip.json index 8d43055..de2a4d1 100644 --- a/src/processes/clip.json +++ b/src/processes/clip.json @@ -1,106 +1,82 @@ { - "id": "clip", - "summary": "Clip a value between a minimum and a maximum", - "description": "Clips a number between specified minimum and maximum values. A value larger than the maximal value will have the maximal value, a value lower than minimal value will have the minimal value.\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math" - ], - "parameters": [ - { - "name": "x", - "description": "A number.", - "schema": { - "type": [ - "number", - "null" - ] - } + "id": "clip", + "summary": "Clip a value between a minimum and a maximum", + "description": "Clips a number between specified minimum and maximum values. A value larger than the maximum value is set to the maximum value, a value lower than the minimum value is set to the minimum value. If the maximum value is smaller than the minimum number, the process throws a `MinMaxSwapped` exception.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math" + ], + "parameters": [ + { + "name": "x", + "description": "A number.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "min", + "description": "Minimum value. If the value is lower than this value, the process will return the value of this parameter.", + "schema": { + "type": "number" + } + }, + { + "name": "max", + "description": "Maximum value. If the value is greater than this value, the process will return the value of this parameter.", + "schema": { + "type": "number" + } + } + ], + "returns": { + "description": "The value clipped to the specified range.", + "schema": { + "type": [ + "number", + "null" + ] + } }, - { - "name": "min", - "description": "Minimum value. If the value is lower than this value, the process will return the value of this parameter.", - "schema": { - "type": "number" - } + "exceptions": { + "MinMaxSwapped": { + "message": "The minimum value should be lower than or equal to the maximum value." + } }, - { - "name": "max", - "description": "Maximum value. If the value is greater than this value, the process will return the value of this parameter.", - "schema": { - "type": "number" - } - } - ], - "returns": { - "description": "The value clipped to the specified range.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": -5, - "min": -1, - "max": 1 - }, - "returns": -1 - }, - { - "arguments": { - "x": 10.001, - "min": 1, - "max": 10 - }, - "returns": 10 - }, - { - "arguments": { - "x": 0.000001, - "min": 0, - "max": 0.02 - }, - "returns": 0.000001 - }, - { - "arguments": { - "x": null, - "min": 0, - "max": 1 - }, - "returns": null - } - ], - "process_graph": { - "min": { - "process_id": "min", - "arguments": { - "data": [ - { - "from_parameter": "max" - }, - { - "from_parameter": "x" - } - ] - } - }, - "max": { - "process_id": "max", - "arguments": { - "data": [ - { - "from_parameter": "min" - }, - { - "from_node": "min" - } - ] - }, - "result": true - } - } -} \ No newline at end of file + "examples": [ + { + "arguments": { + "x": -5, + "min": -1, + "max": 1 + }, + "returns": -1 + }, + { + "arguments": { + "x": 10.001, + "min": 1, + "max": 10 + }, + "returns": 10 + }, + { + "arguments": { + "x": 0.000001, + "min": 0, + "max": 0.02 + }, + "returns": 0.000001 + }, + { + "arguments": { + "x": null, + "min": 0, + "max": 1 + }, + "returns": null + } + ] +} diff --git a/src/processes/cos.json b/src/processes/cos.json index 6e6e414..0d6229a 100644 --- a/src/processes/cos.json +++ b/src/processes/cos.json @@ -18,12 +18,14 @@ } ], "returns": { - "description": "The computed cosine of `x`.", + "description": "The computed cosine in the range *[-1, 1]*.", "schema": { "type": [ "number", "null" - ] + ], + "minimum": -1, + "maximum": 1 } }, "examples": [ @@ -41,4 +43,4 @@ "title": "Cosine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/cosh.json b/src/processes/cosh.json index 975958a..8b56a22 100644 --- a/src/processes/cosh.json +++ b/src/processes/cosh.json @@ -1,14 +1,14 @@ { "id": "cosh", "summary": "Hyperbolic cosine", - "description": "Computes the hyperbolic cosine of `x`.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the hyperbolic cosine of `x`.\n\nThe no-data value `null` is passed through and therefore gets propagated.", "categories": [ "math > trigonometric" ], "parameters": [ { "name": "x", - "description": "An angle in radians.", + "description": "An hyperbolic angle in radians.", "schema": { "type": [ "number", @@ -18,12 +18,13 @@ } ], "returns": { - "description": "The computed hyperbolic cosine of `x`.", + "description": "The computed hyperbolic cosine in the range *[1, +∞)*.", "schema": { "type": [ "number", "null" - ] + ], + "minimum": 1 } }, "examples": [ @@ -41,4 +42,4 @@ "title": "Hyperbolic cosine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/create_raster_cube.js b/src/processes/create_cube.js similarity index 78% rename from src/processes/create_raster_cube.js rename to src/processes/create_cube.js index eb5fb7f..574afb1 100644 --- a/src/processes/create_raster_cube.js +++ b/src/processes/create_cube.js @@ -1,7 +1,7 @@ import GeeProcess from '../processgraph/process.js'; import DataCube from '../processgraph/datacube.js'; -export default class create_raster_cube extends GeeProcess { +export default class create_cube extends GeeProcess { executeSync(node) { const dc = new DataCube(node.ee); diff --git a/src/processes/create_cube.json b/src/processes/create_cube.json new file mode 100644 index 0000000..035e969 --- /dev/null +++ b/src/processes/create_cube.json @@ -0,0 +1,23 @@ +{ + "id": "create_cube", + "summary": "Create an empty data cube", + "description": "Creates a new data cube without dimensions. Dimensions can be added with ``add_dimension()``.", + "categories": [ + "cubes" + ], + "parameters": [], + "returns": { + "description": "An empty data cube with no dimensions.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html", + "rel": "about", + "title": "Data Cubes explained in the openEO documentation" + } + ] +} diff --git a/src/processes/create_raster_cube.json b/src/processes/create_raster_cube.json deleted file mode 100644 index 19d7279..0000000 --- a/src/processes/create_raster_cube.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "id": "create_raster_cube", - "summary": "Create an empty raster data cube", - "description": "Creates a new raster data cube without dimensions. Dimensions can be added with ``add_dimension()``.", - "categories": [ - "cubes" - ], - "parameters": [], - "returns": { - "description": "An empty raster data cube with zero dimensions.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - } -} \ No newline at end of file diff --git a/src/processes/debug.js b/src/processes/debug.js deleted file mode 100644 index 5d3bd3a..0000000 --- a/src/processes/debug.js +++ /dev/null @@ -1,20 +0,0 @@ -import GeeProcess from '../processgraph/process.js'; - -export default class debug extends GeeProcess { - - executeSync(node) { - const data = node.getArgument('data'); - const code = node.getArgument('data'); - const level = node.getArgument('data', 'info'); - const message = node.getArgument('data'); - - const logger = node.getLogger(); - logger[level](message, data, code); - - // ToDo 1.2: rename to inspect #81 - // ToDo processes: Implement that if GEE objects are passed into data, it requests gee.getInfo on them and logs the result. #81 - - return data; - } - -} diff --git a/src/processes/debug.json b/src/processes/debug.json deleted file mode 100644 index eedafa4..0000000 --- a/src/processes/debug.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "id": "debug", - "summary": "Publish debugging information", - "description": "Sends debugging information about the data to the log output. Passes the data through.", - "categories": [ - "development" - ], - "experimental": true, - "parameters": [ - { - "name": "data", - "description": "Data to publish.", - "schema": { - "description": "Any data type is allowed." - } - }, - { - "name": "code", - "description": "An identifier to help identify the log entry in a bunch of other log entries.", - "schema": { - "type": "string" - }, - "default": "", - "optional": true - }, - { - "name": "level", - "description": "The severity level of this message, defaults to `info`. Note that the level `error` forces the computation to be stopped!", - "schema": { - "type": "string", - "enum": [ - "error", - "warning", - "info", - "debug" - ] - }, - "default": "info", - "optional": true - }, - { - "name": "message", - "description": "A message to send in addition to the data.", - "schema": { - "type": "string" - }, - "default": "", - "optional": true - } - ], - "returns": { - "description": "The data as passed to the `data` parameter without any modification.", - "schema": { - "description": "Any data type is allowed." - } - } -} \ No newline at end of file diff --git a/src/processes/dimension_labels.json b/src/processes/dimension_labels.json index 938f392..b1bc529 100644 --- a/src/processes/dimension_labels.json +++ b/src/processes/dimension_labels.json @@ -1,41 +1,42 @@ { - "id": "dimension_labels", - "summary": "Get the dimension labels", - "description": "Returns all labels for a dimension in the data cube. The labels have the same order as in the data cube.", - "categories": [ - "cubes" - ], - "parameters": [ - { - "name": "data", - "description": "The data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } + "id": "dimension_labels", + "summary": "Get the dimension labels", + "description": "Gives all labels for a dimension in the data cube. The labels have the same order as in the data cube.\n\nIf a dimension with the specified name does not exist, the process fails with a `DimensionNotAvailable` exception.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "The data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "dimension", + "description": "The name of the dimension to get the labels for.", + "schema": { + "type": "string" + } + } + ], + "returns": { + "description": "The labels as an array.", + "schema": { + "type": "array", + "items": { + "type": [ + "number", + "string" + ] + } + } }, - { - "name": "dimension", - "description": "The name of the dimension to get the labels for.", - "schema": { - "type": "string" - } + "exceptions": { + "DimensionNotAvailable": { + "message": "A dimension with the specified name does not exist." + } } - ], - "returns": { - "description": "The labels as array.", - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] - } - } - } -} \ No newline at end of file +} diff --git a/src/processes/divide.json b/src/processes/divide.json index 74d0f11..2244c84 100644 --- a/src/processes/divide.json +++ b/src/processes/divide.json @@ -1,79 +1,79 @@ { - "id": "divide", - "summary": "Division of two numbers", - "description": "Divides argument `x` by the argument `y` (*x / y*) and returns the computed result.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. Therefore, a division by zero results in ±infinity if the processing environment supports it. Otherwise a `DivisionByZero` error must the thrown.", - "categories": [ - "math" - ], - "parameters": [ - { - "name": "x", - "description": "The dividend.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - { - "name": "y", - "description": "The divisor.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed result.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "exceptions": { - "DivisionByZero": { - "message": "Division by zero is not supported." - } - }, - "examples": [ - { - "arguments": { - "x": 5, - "y": 2.5 - }, - "returns": 2 - }, - { - "arguments": { - "x": -2, - "y": 4 - }, - "returns": -0.5 - }, - { - "arguments": { - "x": 1, - "y": null - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/Division.html", - "title": "Division explained by Wolfram MathWorld" - }, - { - "rel": "about", - "href": "https://ieeexplore.ieee.org/document/8766229", - "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" - } - ] + "id": "divide", + "summary": "Division of two numbers", + "description": "Divides argument `x` by the argument `y` (*`x / y`*) and returns the computed result.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. A division by zero results in:\n\n- +infinity for `x` > 0,\n- -infinity for `x` < 0,\n- `NaN` for `x` = 0,\n- or otherwise, throws a `DivisionByZero` exception if the other options are not supported by the processing environment.", + "categories": [ + "math" + ], + "parameters": [ + { + "name": "x", + "description": "The dividend.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "y", + "description": "The divisor.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed result.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + "exceptions": { + "DivisionByZero": { + "message": "Division by zero is not supported." + } + }, + "examples": [ + { + "arguments": { + "x": 5, + "y": 2.5 + }, + "returns": 2 + }, + { + "arguments": { + "x": -2, + "y": 4 + }, + "returns": -0.5 + }, + { + "arguments": { + "x": 1, + "y": null + }, + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Division.html", + "title": "Division explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ] } \ No newline at end of file diff --git a/src/processes/drop_dimension.json b/src/processes/drop_dimension.json index 28709d5..64b3aed 100644 --- a/src/processes/drop_dimension.json +++ b/src/processes/drop_dimension.json @@ -1,40 +1,40 @@ { - "id": "drop_dimension", - "summary": "Remove a dimension", - "description": "Drops a dimension from the data cube.\n\nDropping a dimension only works on dimensions with a single dimension label left, otherwise the process fails with a `DimensionLabelCountMismatch` error. Dimension values can be reduced to a single value with a filter such as ``filter_bands()`` or the ``reduce_dimension()`` process. If a dimension with the specified name does not exist, the process fails with a `DimensionNotAvailable` error.", - "categories": [ - "cubes" - ], - "parameters": [ - { - "name": "data", - "description": "The data cube to drop a dimension from.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "name", - "description": "Name of the dimension to drop.", - "schema": { - "type": "string" - } - } - ], - "returns": { + "id": "drop_dimension", + "summary": "Remove a dimension", + "description": "Drops a dimension from the data cube.\n\nDropping a dimension only works on dimensions with a single dimension label left, otherwise the process fails with a `DimensionLabelCountMismatch` exception. Dimension values can be reduced to a single value with a filter such as ``filter_bands()`` or the ``reduce_dimension()`` process. If a dimension with the specified name does not exist, the process fails with a `DimensionNotAvailable` exception.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "The data cube to drop a dimension from.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "name", + "description": "Name of the dimension to drop.", + "schema": { + "type": "string" + } + } + ], + "returns": { "description": "A data cube without the specified dimension. The number of dimensions decreases by one, but the dimension properties (name, type, labels, reference system and resolution) for all other dimensions remain unchanged.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - "exceptions": { - "DimensionLabelCountMismatch": { - "message": "The number of dimension labels exceeds one, which requires a reducer." + "schema": { + "type": "object", + "subtype": "raster-cube" + } }, - "DimensionNotAvailable": { - "message": "A dimension with the specified name does not exist." + "exceptions": { + "DimensionLabelCountMismatch": { + "message": "The number of dimension labels exceeds one, which requires a reducer." + }, + "DimensionNotAvailable": { + "message": "A dimension with the specified name does not exist." + } } - } -} \ No newline at end of file +} diff --git a/src/processes/e.js b/src/processes/e.js index 97bef96..88900cc 100644 --- a/src/processes/e.js +++ b/src/processes/e.js @@ -3,8 +3,6 @@ import GeeProcess from '../processgraph/process.js'; export default class e extends GeeProcess { executeSync(node) { - const dc = node.getDataCube('data'); - dc.setData(Math.E); - return dc; + return node.ee.Number(Math.E); } } diff --git a/src/processes/e.json b/src/processes/e.json index cb083f1..7950686 100644 --- a/src/processes/e.json +++ b/src/processes/e.json @@ -1,23 +1,23 @@ { - "id": "e", - "summary": "Euler's number (e)", - "description": "The real number *e* is a mathematical constant that is the base of the natural logarithm such that *ln(e) = 1*. The numerical value is approximately *2.71828*.", - "categories": [ - "math > constants", - "math > exponential & logarithmic" - ], - "parameters": [], - "returns": { - "description": "The numerical value of Euler's number.", - "schema": { - "type": "number" - } - }, - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/e.html", - "title": "Mathematical constant e explained by Wolfram MathWorld" - } - ] + "id": "e", + "summary": "Euler's number (e)", + "description": "The real number *e* is a mathematical constant that is the base of the natural logarithm such that *`ln(e) = 1`*. The numerical value is approximately *2.71828*.", + "categories": [ + "math > constants", + "math > exponential & logarithmic" + ], + "parameters": [], + "returns": { + "description": "The numerical value of Euler's number.", + "schema": { + "type": "number" + } + }, + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/e.html", + "title": "Mathematical constant e explained by Wolfram MathWorld" + } + ] } \ No newline at end of file diff --git a/src/processes/exp.json b/src/processes/exp.json index c28e0aa..c9df86f 100644 --- a/src/processes/exp.json +++ b/src/processes/exp.json @@ -1,68 +1,69 @@ { - "id": "exp", - "summary": "Exponentiation to the base e", - "description": "Exponential function to the base *e* raised to the power of `p`.\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math > exponential & logarithmic" - ], - "parameters": [ - { - "name": "p", - "description": "The numerical exponent.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed value for *e* raised to the power of `p`.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "p": 0 - }, - "returns": 1 - }, - { - "arguments": { - "p": null - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/ExponentialFunction.html", - "title": "Exponential function explained by Wolfram MathWorld" - } - ], - "process_graph": { - "e": { - "process_id": "e", - "arguments": {} + "id": "exp", + "summary": "Exponentiation to the base e", + "description": "Exponential function to the base *e* raised to the power of `p`.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math > exponential & logarithmic" + ], + "parameters": [ + { + "name": "p", + "description": "The numerical exponent.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed value for *e* raised to the power of `p`. Value is in the range of *(0, +8)*", + "schema": { + "type": [ + "number", + "null" + ], + "minimumExclusive": 0 + } }, - "power": { - "process_id": "power", - "arguments": { - "base": { - "from_node": "e" + "examples": [ + { + "arguments": { + "p": 0 + }, + "returns": 1 + }, + { + "arguments": { + "p": null + }, + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/ExponentialFunction.html", + "title": "Exponential function explained by Wolfram MathWorld" + } + ], + "process_graph": { + "e": { + "process_id": "e", + "arguments": {} }, - "p": { - "from_parameter": "p" + "power": { + "process_id": "power", + "arguments": { + "base": { + "from_node": "e" + }, + "p": { + "from_parameter": "p" + } + }, + "result": true } - }, - "result": true } - } } \ No newline at end of file diff --git a/src/processes/filter_bands.json b/src/processes/filter_bands.json index 0bc553b..3d0e0ee 100644 --- a/src/processes/filter_bands.json +++ b/src/processes/filter_bands.json @@ -1,12 +1,11 @@ { "id": "filter_bands", - "summary": "Filter the bands by name", - "description": "Filters the bands in the data cube so that bands that don't match any of the criteria are dropped from the data cube. The data cube is expected to have only one dimension of type `bands`. Fails with a `DimensionMissing` error if no such dimension exists.\n\nThe following criteria can be used to select bands:\n\n* `bands`: band name or common band name (e.g. `B01`, `B8A`, `red` or `nir`)\n* `wavelengths`: ranges of wavelengths in micrometres (μm) (e.g. 0.5 - 0.6)\n\nAll these information are exposed in the band metadata of the collection. To keep algorithms interoperable it is recommended to prefer the common bands names or the wavelengths over collection and/or back-end specific band names.\n\nIf multiple criteria are specified, any of them must match and not all of them, i.e. they are combined with an OR-operation. If no criteria is specified, the `BandFilterParameterMissing` exception must be thrown.\n\n**Important:** The order of the specified array defines the order of the bands in the data cube, which can be important for subsequent processes. If multiple bands are matched by a single criterion (e.g. a range of wavelengths), they stay in the original order.", + "summary": "Filter the bands by names", + "description": "Filters the bands in the data cube so that bands that don't match any of the criteria are dropped from the data cube. The data cube is expected to have only one dimension of type `bands`. Fails with a `DimensionMissing` exception if no such dimension exists.\n\nThe following criteria can be used to select bands:\n\n* `bands`: band name or common band name (e.g. `B01`, `B8A`, `red` or `nir`)\n* `wavelengths`: ranges of wavelengths in micrometers (μm) (e.g. 0.5 - 0.6)\n\nAll these information are exposed in the band metadata of the collection. To keep algorithms interoperable it is recommended to prefer the common band names or the wavelengths over band names that are specific to the collection and/or back-end.\n\nIf multiple criteria are specified, any of them must match and not all of them, i.e. they are combined with an OR-operation. If no criteria are specified, the `BandFilterParameterMissing` exception must be thrown.\n\n**Important:** The order of the specified array defines the order of the bands in the data cube, which can be important for subsequent processes. If multiple bands are matched by a single criterion (e.g. a range of wavelengths), they stay in the original order.", "categories": [ "cubes", "filter" ], - "gee:custom": true, "parameters": [ { "name": "data", @@ -18,7 +17,7 @@ }, { "name": "bands", - "description": "A list of band names. Either the unique band name (metadata field `name` in bands) or one of the common band names (metadata field `common_name` in bands). If unique band name and common name conflict, the unique band name has higher priority.\n\nThe order of the specified array defines the order of the bands in the data cube. If multiple bands match a common name, all matched bands are included in the original order.", + "description": "A list of band names. Either the unique band name (metadata field `name` in bands) or one of the common band names (metadata field `common_name` in bands). If the unique band name and the common name conflict, the unique band name has a higher priority.\n\nThe order of the specified array defines the order of the bands in the data cube. If multiple bands match a common name, all matched bands are included in the original order.", "schema": { "type": "array", "items": { @@ -39,7 +38,7 @@ }, "exceptions": { "BandFilterParameterMissing": { - "message": "The process 'filter_bands' requires any of the parameters 'bands', 'common_names' or 'wavelengths' to be set." + "message": "The process `filter_bands` requires any of the parameters `bands`, `common_names` or `wavelengths` to be set." }, "DimensionMissing": { "message": "A band dimension is missing." @@ -50,6 +49,11 @@ "rel": "about", "href": "https://github.com/radiantearth/stac-spec/tree/master/extensions/eo#common-band-names", "title": "List of common band names as specified by the STAC specification" + }, + { + "href": "https://openeo.org/documentation/1.0/datacubes.html#filter", + "rel": "about", + "title": "Filters explained in the openEO documentation" } ] -} \ No newline at end of file +} diff --git a/src/processes/filter_bbox.json b/src/processes/filter_bbox.json index 2794135..b6f25f5 100644 --- a/src/processes/filter_bbox.json +++ b/src/processes/filter_bbox.json @@ -1,12 +1,11 @@ { "id": "filter_bbox", "summary": "Spatial filter using a bounding box", - "description": "Limits the data cube to the specified bounding box.\n\nThe filter retains a pixel in the data cube if the point at the pixel center intersects with the bounding box (as defined in the Simple Features standard by the OGC).", + "description": "Limits the data cube to the specified bounding box.\n\n* For raster data cubes, the filter retains a pixel in the data cube if the point at the pixel center intersects with the bounding box (as defined in the Simple Features standard by the OGC). Alternatively, ``filter_spatial()`` can be used to filter by geometry.\n* For vector data cubes, the filter retains the geometry in the data cube if the geometry is fully within the bounding box (as defined in the Simple Features standard by the OGC). All geometries that were empty or not contained fully within the bounding box will be removed from the data cube.\n\nAlternatively, filter spatially with geometries using ``filter_spatial()`` (on a raster data cube) or ``filter_vector()`` (on a vector data cube).", "categories": [ "cubes", "filter" ], - "gee:custom": true, "parameters": [ { "name": "data", @@ -18,7 +17,7 @@ }, { "name": "extent", - "description": "A bounding box, which may include a vertical axis (see `base` and `height`).", + "description": "A bounding box, which may include a vertical axis (see `base` and `height`).\n\nIf the bounding box is not provided in the coordinate reference system (CRS) of the data cube, the bounding box is reprojected to the CRS of the spatial data cube dimensions.", "schema": { "type": "object", "subtype": "bounding-box", @@ -62,7 +61,7 @@ "default": null }, "crs": { - "description": "Coordinate reference system of the extent, specified as as [EPSG code](http://www.epsg-registry.org/), [WKT2 (ISO 19162) string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html) or [PROJ definition (deprecated)](https://proj.org/usage/quickstart.html). Defaults to `4326` (EPSG code 4326) unless the client explicitly requests a different coordinate reference system.", + "description": "Coordinate reference system of the extent, specified as as [EPSG code](http://www.epsg-registry.org/) or [WKT2 CRS string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html). Defaults to `4326` (EPSG code 4326) unless the client explicitly requests a different coordinate reference system.", "anyOf": [ { "title": "EPSG Code", @@ -72,6 +71,11 @@ "examples": [ 3857 ] + }, + { + "title": "WKT2", + "type": "string", + "subtype": "wkt2-definition" } ], "default": 4326 @@ -88,6 +92,11 @@ } }, "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html#filter", + "rel": "about", + "title": "Filters explained in the openEO documentation" + }, { "rel": "about", "href": "https://proj.org/usage/projections.html", @@ -109,4 +118,4 @@ "title": "Simple Features standard by the OGC" } ] -} \ No newline at end of file +} diff --git a/src/processes/filter_spatial.json b/src/processes/filter_spatial.json index b08c06d..db740d0 100644 --- a/src/processes/filter_spatial.json +++ b/src/processes/filter_spatial.json @@ -1,41 +1,47 @@ { - "id": "filter_spatial", - "summary": "Spatial filter using geometries", - "description": "Limits the data cube over the spatial dimensions to the specified geometries.\n\n- For **polygons**, the filter retains a pixel in the data cube if the point at the pixel center intersects with at least one of the polygons (as defined in the Simple Features standard by the OGC).\n- For **points**, the process considers the closest pixel center.\n- For **lines** (line strings), the process considers all the pixels whose centers are closest to at least one point on the line.\n\nMore specifically, pixels outside of the bounding box of the given geometry will not be available after filtering. All pixels inside the bounding box that are not retained will be set to `null` (no data).", - "categories": [ + "id": "filter_spatial", + "summary": "Spatial filter raster data cubes using geometries", + "description": "Limits the raster data cube over the spatial dimensions to the specified geometries.\n\n- For **polygons**, the filter retains a pixel in the data cube if the point at the pixel center intersects with at least one of the polygons (as defined in the Simple Features standard by the OGC).\n- For **points**, the process considers the closest pixel center.\n- For **lines** (line strings), the process considers all the pixels whose centers are closest to at least one point on the line.\n\nMore specifically, pixels outside of the bounding box of the given geometries will not be available after filtering. All pixels inside the bounding box that are not retained will be set to `null` (no data).\n\n Alternatively, use ``filter_bbox()`` to filter with a bounding box or ``filter_vector()`` to filter a vector data cube based on geometries. Use ``mask_polygon()`` to mask without changing the spatial extent of your data cube.", + "categories": [ "cubes", - "filter" - ], - "parameters": [ - { - "name": "data", - "description": "A data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } + "filter" + ], + "parameters": [ + { + "name": "data", + "description": "A raster data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "geometries", + "description": "One or more geometries used for filtering, given as GeoJSON or vector data cube. If multiple geometries are provided, the union of them is used. Empty geometries are ignored.\n\nLimits the data cube to the bounding box of the given geometries. No implicit masking gets applied. To mask the pixels of the data cube use ``mask_polygon()``.", + "schema": { + "title": "GeoJSON", + "type": "object", + "subtype": "geojson" + } + } + ], + "returns": { + "description": "A raster data cube restricted to the specified geometries. The dimensions and dimension properties (name, type, labels, reference system and resolution) remain unchanged, except that the spatial dimensions have less (or the same) dimension labels.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } }, - { - "name": "geometries", - "description": "One or more geometries used for filtering, specified as GeoJSON.", - "schema": { - "type": "object", - "subtype": "geojson" - } - } - ], - "returns": { - "description": "A data cube restricted to the specified geometries. The dimensions and dimension properties (name, type, labels, reference system and resolution) remain unchanged, except that the spatial dimensions have less (or the same) dimension labels.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - "links": [ - { - "href": "http://www.opengeospatial.org/standards/sfa", - "rel": "about", - "title": "Simple Features standard by the OGC" - } - ] -} \ No newline at end of file + "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html#filter", + "rel": "about", + "title": "Filters explained in the openEO documentation" + }, + { + "href": "http://www.opengeospatial.org/standards/sfa", + "rel": "about", + "title": "Simple Features standard by the OGC" + } + ] +} diff --git a/src/processes/filter_temporal.json b/src/processes/filter_temporal.json index dbb3f20..6be89fb 100644 --- a/src/processes/filter_temporal.json +++ b/src/processes/filter_temporal.json @@ -1,7 +1,7 @@ { "id": "filter_temporal", - "summary": "Temporal filter for a temporal intervals", - "description": "Limits the data cube to the specified interval of dates and/or times.\n\nMore precisely, the filter checks whether the temporal dimension label is greater than or equal to the lower boundary (start date/time) and the temporal dimension label is less than the value of the upper boundary (end date/time). This corresponds to a left-closed interval, which contains the lower boundary but not the upper boundary.\n\nIf the dimension is set to `null` (it's the default value), the data cube is expected to only have one temporal dimension.", + "summary": "Temporal filter based on temporal intervals", + "description": "Limits the data cube to the specified interval of dates and/or times.\n\nMore precisely, the filter checks whether each of the temporal dimension labels is greater than or equal to the lower boundary (start date/time) and less than the value of the upper boundary (end date/time). This corresponds to a left-closed interval, which contains the lower boundary but not the upper boundary.", "categories": [ "cubes", "filter" @@ -17,7 +17,7 @@ }, { "name": "extent", - "description": "Left-closed temporal interval, i.e. an array with exactly two elements:\n\n1. The first element is the start of the temporal interval. The specified instance in time is **included** in the interval.\n2. The second element is the end of the temporal interval. The specified instance in time is **excluded** from the interval.\n\nThe specified temporal strings follow [RFC 3339](https://tools.ietf.org/html/rfc3339). Also supports open intervals by setting one of the boundaries to `null`, but never both.", + "description": "Left-closed temporal interval, i.e. an array with exactly two elements:\n\n1. The first element is the start of the temporal interval. The specified time instant is **included** in the interval.\n2. The second element is the end of the temporal interval. The specified time instant is **excluded** from the interval.\n\nThe second element must always be greater/later than the first element. Otherwise, a `TemporalExtentEmpty` exception is thrown.\n\nAlso supports unbounded intervals by setting one of the boundaries to `null`, but never both.", "schema": { "type": "array", "subtype": "temporal-interval", @@ -28,19 +28,14 @@ { "type": "string", "format": "date-time", - "subtype": "date-time" + "subtype": "date-time", + "description": "Date and time with a time zone." }, { "type": "string", "format": "date", - "subtype": "date" - }, - { - "type": "string", - "subtype": "year", - "minLength": 4, - "maxLength": 4, - "pattern": "^\\d{4}$" + "subtype": "date", + "description": "Date only, formatted as `YYYY-MM-DD`. The time zone is UTC. Missing time components are all 0." }, { "type": "null" @@ -61,7 +56,7 @@ }, { "name": "dimension", - "description": "The name of the temporal dimension to filter on. If the dimension is not set or is set to `null`, the filter applies to all temporal dimensions. Fails with a `DimensionNotAvailable` error if the specified dimension does not exist.", + "description": "The name of the temporal dimension to filter on. If no specific dimension is specified, the filter applies to all temporal dimensions. Fails with a `DimensionNotAvailable` exception if the specified dimension does not exist.", "schema": { "type": [ "string", @@ -73,7 +68,7 @@ } ], "returns": { - "description": "A data cube restricted to the specified temporal extent. The dimensions and dimension properties (name, type, labels, reference system and resolution) remain unchanged, except that the given temporal dimension(s) have less (or the same) dimension labels.", + "description": "A data cube restricted to the specified temporal extent. The dimensions and dimension properties (name, type, labels, reference system and resolution) remain unchanged, except that the temporal dimensions (determined by `dimensions` parameter) may have less dimension labels.", "schema": { "type": "object", "subtype": "raster-cube" @@ -82,6 +77,21 @@ "exceptions": { "DimensionNotAvailable": { "message": "A dimension with the specified name does not exist." + }, + "TemporalExtentEmpty": { + "message": "The temporal extent is empty. The second instant in time must always be greater/later than the first instant in time." + } + }, + "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html#filter", + "rel": "about", + "title": "Filters explained in the openEO documentation" + }, + { + "href": "https://www.rfc-editor.org/rfc/rfc3339.html", + "rel": "about", + "title": "RFC3339: Details about formatting temporal strings" } - } -} \ No newline at end of file + ] +} diff --git a/src/processes/first.json b/src/processes/first.json index ec8a357..1afa962 100644 --- a/src/processes/first.json +++ b/src/processes/first.json @@ -1,77 +1,77 @@ { - "id": "first", - "summary": "First element", + "id": "first", + "summary": "First element", "description": "Gives the first element of an array.\n\nAn array without non-`null` elements resolves always with `null`.", - "categories": [ - "arrays", - "reducer" - ], - "parameters": [ - { - "name": "data", + "categories": [ + "arrays", + "reducer" + ], + "parameters": [ + { + "name": "data", "description": "An array with elements of any data type.", - "schema": { - "type": "array", - "items": { - "description": "Any data type is allowed." + "schema": { + "type": "array", + "items": { + "description": "Any data type is allowed." + } + } + }, + { + "name": "ignore_nodata", + "description": "Indicates whether no-data values are ignored or not. Ignores them by default. Setting this flag to `false` considers no-data values so that `null` is returned if the first value is such a value.", + "schema": { + "type": "boolean" + }, + "default": true, + "optional": true + } + ], + "returns": { + "description": "The first element of the input array.", + "schema": { + "description": "Any data type is allowed." } - } - }, - { - "name": "ignore_nodata", - "description": "Indicates whether no-data values are ignored or not. Ignores them by default. Setting this flag to `false` considers no-data values so that `null` is returned if the first value is such a value.", - "schema": { - "type": "boolean" - }, - "default": true, - "optional": true - } - ], - "returns": { - "description": "The first element of the input array.", - "schema": { - "description": "Any data type is allowed." - } - }, - "examples": [ - { - "arguments": { - "data": [ - 1, - 0, - 3, - 2 - ] - }, - "returns": 1 - }, - { - "arguments": { - "data": [ - null, - "A", - "B" - ] - }, - "returns": "A" - }, - { - "arguments": { - "data": [ - null, - 2, - 3 - ], - "ignore_nodata": false - }, - "returns": null }, - { - "description": "The input array is empty: return `null`.", - "arguments": { - "data": [] - }, - "returns": null - } - ] + "examples": [ + { + "arguments": { + "data": [ + 1, + 0, + 3, + 2 + ] + }, + "returns": 1 + }, + { + "arguments": { + "data": [ + null, + "A", + "B" + ] + }, + "returns": "A" + }, + { + "arguments": { + "data": [ + null, + 2, + 3 + ], + "ignore_nodata": false + }, + "returns": null + }, + { + "description": "The input array is empty: return `null`.", + "arguments": { + "data": [] + }, + "returns": null + } + ] } \ No newline at end of file diff --git a/src/processes/floor.json b/src/processes/floor.json index a454310..d0eb5a9 100644 --- a/src/processes/floor.json +++ b/src/processes/floor.json @@ -1,62 +1,62 @@ { - "id": "floor", - "summary": "Round fractions down", - "description": "The greatest integer less than or equal to the number `x`.\n\nThis process is *not* an alias for the ``int()`` process as defined by some mathematicians, see the examples for negative numbers in both processes for differences.\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math > rounding" - ], - "parameters": [ - { - "name": "x", - "description": "A number to round down.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The number rounded down.", - "schema": { - "type": [ - "integer", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 0 - }, - "returns": 0 + "id": "floor", + "summary": "Round fractions down", + "description": "The greatest integer less than or equal to the number `x`.\n\nThis process is *not* an alias for the ``int()`` process as defined by some mathematicians, see the examples for negative numbers in both processes for differences.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math > rounding" + ], + "parameters": [ + { + "name": "x", + "description": "A number to round down.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The number rounded down.", + "schema": { + "type": [ + "integer", + "null" + ] + } }, - { - "arguments": { - "x": 3.5 - }, - "returns": 3 - }, - { - "arguments": { - "x": -0.4 - }, - "returns": -1 - }, - { - "arguments": { - "x": -3.5 - }, - "returns": -4 - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/FloorFunction.html", - "title": "Floor explained by Wolfram MathWorld" - } - ] + "examples": [ + { + "arguments": { + "x": 0 + }, + "returns": 0 + }, + { + "arguments": { + "x": 3.5 + }, + "returns": 3 + }, + { + "arguments": { + "x": -0.4 + }, + "returns": -1 + }, + { + "arguments": { + "x": -3.5 + }, + "returns": -4 + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/FloorFunction.html", + "title": "Floor explained by Wolfram MathWorld" + } + ] } \ No newline at end of file diff --git a/src/processes/if.json b/src/processes/if.json index 76db35a..43e6fcd 100644 --- a/src/processes/if.json +++ b/src/processes/if.json @@ -1,96 +1,96 @@ { - "id": "if", - "summary": "If-Then-Else conditional", - "description": "If the value passed is `true`, returns the value of the `accept` parameter, otherwise returns the value of the `reject` parameter.\n\nThis is basically an if-then-else construct as in other programming languages.", - "categories": [ - "logic", - "comparison", - "masks" - ], - "parameters": [ - { - "name": "value", - "description": "A boolean value.", - "schema": { - "type": [ - "boolean", - "null" - ] - } + "id": "if", + "summary": "If-Then-Else conditional", + "description": "If the value passed is `true`, returns the value of the `accept` parameter, otherwise returns the value of the `reject` parameter.\n\nThis is basically an if-then-else construct as in other programming languages.", + "categories": [ + "logic", + "comparison", + "masks" + ], + "parameters": [ + { + "name": "value", + "description": "A boolean value.", + "schema": { + "type": [ + "boolean", + "null" + ] + } + }, + { + "name": "accept", + "description": "A value that is returned if the boolean value is `true`.", + "schema": { + "description": "Any data type is allowed." + } + }, + { + "name": "reject", + "description": "A value that is returned if the boolean value is **not** `true`. Defaults to `null`.", + "schema": { + "description": "Any data type is allowed." + }, + "default": null, + "optional": true + } + ], + "returns": { + "description": "Either the `accept` or `reject` argument depending on the given boolean value.", + "schema": { + "description": "Any data type is allowed." + } }, - { - "name": "accept", - "description": "A value that is returned if the boolean value is `true`.", - "schema": { - "description": "Any data type is allowed." - } - }, - { - "name": "reject", - "description": "A value that is returned if the boolean value is **not** `true`. Defaults to `null`.", - "schema": { - "description": "Any data type is allowed." - }, - "default": null, - "optional": true - } - ], - "returns": { - "description": "Either the `accept` or `reject` argument depending on the given boolean value.", - "schema": { - "description": "Any data type is allowed." - } - }, - "examples": [ - { - "arguments": { - "value": true, - "accept": "A", - "reject": "B" - }, - "returns": "A" - }, - { - "arguments": { - "value": null, - "accept": "A", - "reject": "B" - }, - "returns": "B" - }, - { - "arguments": { - "value": false, - "accept": [ - 1, - 2, - 3 - ], - "reject": [ - 4, - 5, - 6 - ] - }, - "returns": [ - 4, - 5, - 6 - ] - }, - { - "arguments": { - "value": true, - "accept": 123 - }, - "returns": 123 - }, - { - "arguments": { - "value": false, - "accept": 1 - }, - "returns": null - } - ] + "examples": [ + { + "arguments": { + "value": true, + "accept": "A", + "reject": "B" + }, + "returns": "A" + }, + { + "arguments": { + "value": null, + "accept": "A", + "reject": "B" + }, + "returns": "B" + }, + { + "arguments": { + "value": false, + "accept": [ + 1, + 2, + 3 + ], + "reject": [ + 4, + 5, + 6 + ] + }, + "returns": [ + 4, + 5, + 6 + ] + }, + { + "arguments": { + "value": true, + "accept": 123 + }, + "returns": 123 + }, + { + "arguments": { + "value": false, + "accept": 1 + }, + "returns": null + } + ] } \ No newline at end of file diff --git a/src/processes/inspect.js b/src/processes/inspect.js new file mode 100644 index 0000000..5971dce --- /dev/null +++ b/src/processes/inspect.js @@ -0,0 +1,37 @@ +import GeeProcess from '../processgraph/process.js'; +import DataCube from '../processgraph/datacube.js'; + +export default class inspect extends GeeProcess { + + executeSync(node) { + let data = node.getArgument('data'); + const message = node.getArgument('message', ''); + const code = node.getArgument('code', 'User'); + const level = node.getArgument('level', 'info'); + + const ee = node.ee; + if (data instanceof DataCube) { + data = data.toJSON(); + } + else if ( + data instanceof ee.Image || + data instanceof ee.ImageCollection || + data instanceof ee.Array || + data instanceof ee.List || + data instanceof ee.Number || + data instanceof ee.String || + data instanceof ee.Feature || + data instanceof ee.FeatureCollection || + data instanceof ee.Geometry || + data instanceof ee.GeometryCollection || + data instanceof ee.ComputedObject) { + data = data.getInfo(); + } + + const logger = node.getLogger(); + logger.add(message, level, data, undefined, code) + + return data; + } + +} diff --git a/src/processes/inspect.json b/src/processes/inspect.json new file mode 100644 index 0000000..9d7f219 --- /dev/null +++ b/src/processes/inspect.json @@ -0,0 +1,57 @@ +{ + "id": "inspect", + "summary": "Add information to the logs", + "description": "This process can be used to add runtime information to the logs, e.g. for debugging purposes. This process should be used with caution and it is recommended to remove the process in production workflows. For example, logging each value or array individually in a process such as ``apply()`` or ``reduce_dimension()`` could lead to a (too) large number of log entries. Several data structures (e.g. data cubes) are too large to log and will only return summaries of their contents.\n\nThe data provided in the parameter `data` is returned without changes.", + "categories": [ + "development" + ], + "experimental": true, + "parameters": [ + { + "name": "data", + "description": "Data to log.", + "schema": { + "description": "Any data type is allowed." + } + }, + { + "name": "message", + "description": "A message to send in addition to the data.", + "schema": { + "type": "string" + }, + "default": "", + "optional": true + }, + { + "name": "code", + "description": "A label to help identify one or more log entries originating from this process in the list of all log entries. It can help to group or filter log entries and is usually not unique.", + "schema": { + "type": "string" + }, + "default": "User", + "optional": true + }, + { + "name": "level", + "description": "The severity level of this message, defaults to `info`.", + "schema": { + "type": "string", + "enum": [ + "error", + "warning", + "info", + "debug" + ] + }, + "default": "info", + "optional": true + } + ], + "returns": { + "description": "The data as passed to the `data` parameter without any modification.", + "schema": { + "description": "Any data type is allowed." + } + } +} diff --git a/src/processes/int.json b/src/processes/int.json index dfa29a0..8fca165 100644 --- a/src/processes/int.json +++ b/src/processes/int.json @@ -1,63 +1,63 @@ { - "id": "int", - "summary": "Integer part of a number", - "description": "The integer part of the real number `x`.\n\nThis process is *not* an alias for the ``floor()`` process as defined by some mathematicians, see the examples for negative numbers in both processes for differences.\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math", - "math > rounding" - ], - "parameters": [ - { - "name": "x", - "description": "A number.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "Integer part of the number.", - "schema": { - "type": [ - "integer", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 0 - }, - "returns": 0 + "id": "int", + "summary": "Integer part of a number", + "description": "The integer part of the real number `x`.\n\nThis process is *not* an alias for the ``floor()`` process as defined by some mathematicians, see the examples for negative numbers in both processes for differences.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math", + "math > rounding" + ], + "parameters": [ + { + "name": "x", + "description": "A number.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "Integer part of the number.", + "schema": { + "type": [ + "integer", + "null" + ] + } }, - { - "arguments": { - "x": 3.5 - }, - "returns": 3 - }, - { - "arguments": { - "x": -0.4 - }, - "returns": 0 - }, - { - "arguments": { - "x": -3.5 - }, - "returns": -3 - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/IntegerPart.html", - "title": "Integer Part explained by Wolfram MathWorld" - } - ] + "examples": [ + { + "arguments": { + "x": 0 + }, + "returns": 0 + }, + { + "arguments": { + "x": 3.5 + }, + "returns": 3 + }, + { + "arguments": { + "x": -0.4 + }, + "returns": 0 + }, + { + "arguments": { + "x": -3.5 + }, + "returns": -3 + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/IntegerPart.html", + "title": "Integer Part explained by Wolfram MathWorld" + } + ] } \ No newline at end of file diff --git a/src/processes/last.json b/src/processes/last.json index 10fa05b..1a35e6a 100644 --- a/src/processes/last.json +++ b/src/processes/last.json @@ -1,77 +1,77 @@ { - "id": "last", - "summary": "Last element", + "id": "last", + "summary": "Last element", "description": "Gives the last element of an array.\n\nAn array without non-`null` elements resolves always with `null`.", - "categories": [ - "arrays", - "reducer" - ], - "parameters": [ - { - "name": "data", + "categories": [ + "arrays", + "reducer" + ], + "parameters": [ + { + "name": "data", "description": "An array with elements of any data type.", - "schema": { - "type": "array", - "items": { - "description": "Any data type is allowed." + "schema": { + "type": "array", + "items": { + "description": "Any data type is allowed." + } + } + }, + { + "name": "ignore_nodata", + "description": "Indicates whether no-data values are ignored or not. Ignores them by default. Setting this flag to `false` considers no-data values so that `null` is returned if the last value is such a value.", + "schema": { + "type": "boolean" + }, + "default": true, + "optional": true + } + ], + "returns": { + "description": "The last element of the input array.", + "schema": { + "description": "Any data type is allowed." } - } - }, - { - "name": "ignore_nodata", - "description": "Indicates whether no-data values are ignored or not. Ignores them by default. Setting this flag to `false` considers no-data values so that `null` is returned if the last value is such a value.", - "schema": { - "type": "boolean" - }, - "default": true, - "optional": true - } - ], - "returns": { - "description": "The last element of the input array.", - "schema": { - "description": "Any data type is allowed." - } - }, - "examples": [ - { - "arguments": { - "data": [ - 1, - 0, - 3, - 2 - ] - }, - "returns": 2 - }, - { - "arguments": { - "data": [ - "A", - "B", - null - ] - }, - "returns": "B" - }, - { - "arguments": { - "data": [ - 0, - 1, - null - ], - "ignore_nodata": false - }, - "returns": null }, - { - "description": "The input array is empty: return `null`.", - "arguments": { - "data": [] - }, - "returns": null - } - ] + "examples": [ + { + "arguments": { + "data": [ + 1, + 0, + 3, + 2 + ] + }, + "returns": 2 + }, + { + "arguments": { + "data": [ + "A", + "B", + null + ] + }, + "returns": "B" + }, + { + "arguments": { + "data": [ + 0, + 1, + null + ], + "ignore_nodata": false + }, + "returns": null + }, + { + "description": "The input array is empty: return `null`.", + "arguments": { + "data": [] + }, + "returns": null + } + ] } \ No newline at end of file diff --git a/src/processes/linear_scale_range.json b/src/processes/linear_scale_range.json index c02a303..8919687 100644 --- a/src/processes/linear_scale_range.json +++ b/src/processes/linear_scale_range.json @@ -1,89 +1,89 @@ { - "id": "linear_scale_range", - "summary": "Linear transformation between two ranges", - "description": "Performs a linear transformation between the input and output range.\n\nThe given number in `x` is clipped to the bounds specified in `inputMin` and `inputMax` so that the underlying formula *((x - inputMin) / (inputMax - inputMin)) * (outputMax - outputMin) + outputMin* never returns any value lower than `outputMin` or greater than `outputMax`.\n\nPotential use case include\n\n* scaling values to the 8-bit range (0 - 255) often used for numeric representation of values in one of the channels of the [RGB colour model](https://en.wikipedia.org/wiki/RGB_color_model#Numeric_representations) or\n* calculating percentages (0 - 100).\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math" - ], - "parameters": [ - { - "name": "x", + "id": "linear_scale_range", + "summary": "Linear transformation between two ranges", + "description": "Performs a linear transformation between the input and output range.\n\nThe given number in `x` is clipped to the bounds specified in `inputMin` and `inputMax` so that the underlying formula *`((x - inputMin) / (inputMax - inputMin)) * (outputMax - outputMin) + outputMin`* never returns a value outside of the range defined by `outputMin` and `outputMax`.\n\nPotential use case include\n\n* scaling values to the 8-bit range (0 - 255) often used for numeric representation of values in one of the channels of the [RGB colour model](https://en.wikipedia.org/wiki/RGB_color_model#Numeric_representations) or\n* calculating percentages (0 - 100).\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math" + ], + "parameters": [ + { + "name": "x", "description": "A number to transform. The number gets clipped to the bounds specified in `inputMin` and `inputMax`.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - { - "name": "inputMin", - "description": "Minimum value the input can obtain.", - "schema": { - "type": "number" - } - }, - { - "name": "inputMax", - "description": "Maximum value the input can obtain.", - "schema": { - "type": "number" - } - }, - { - "name": "outputMin", - "description": "Minimum value of the desired output range.", - "schema": { - "type": "number" - }, - "default": 0, - "optional": true - }, - { - "name": "outputMax", - "description": "Maximum value of the desired output range.", - "schema": { - "type": "number" - }, - "default": 1, - "optional": true - } - ], - "returns": { - "description": "The transformed number.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 0.3, - "inputMin": -1, - "inputMax": 1, - "outputMin": 0, - "outputMax": 255 - }, - "returns": 165.75 - }, - { - "arguments": { - "x": 25.5, - "inputMin": 0, - "inputMax": 255 - }, - "returns": 0.1 + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "inputMin", + "description": "Minimum value the input can obtain.", + "schema": { + "type": "number" + } + }, + { + "name": "inputMax", + "description": "Maximum value the input can obtain.", + "schema": { + "type": "number" + } + }, + { + "name": "outputMin", + "description": "Minimum value of the desired output range.", + "schema": { + "type": "number" + }, + "default": 0, + "optional": true + }, + { + "name": "outputMax", + "description": "Maximum value of the desired output range.", + "schema": { + "type": "number" + }, + "default": 1, + "optional": true + } + ], + "returns": { + "description": "The transformed number.", + "schema": { + "type": [ + "number", + "null" + ] + } }, - { - "arguments": { - "x": null, - "inputMin": 0, - "inputMax": 100 - }, - "returns": null + "examples": [ + { + "arguments": { + "x": 0.3, + "inputMin": -1, + "inputMax": 1, + "outputMin": 0, + "outputMax": 255 + }, + "returns": 165.75 + }, + { + "arguments": { + "x": 25.5, + "inputMin": 0, + "inputMax": 255 + }, + "returns": 0.1 + }, + { + "arguments": { + "x": null, + "inputMin": 0, + "inputMax": 100 + }, + "returns": null }, { "description": "Shows that the input data is clipped.", @@ -95,75 +95,75 @@ "outputMax": 255 }, "returns": 255 - } - ], - "process_graph": { - "subtract1": { - "process_id": "subtract", - "arguments": { - "x": { - "from_parameter": "x" - }, - "y": { - "from_parameter": "inputMin" } - } - }, - "subtract2": { - "process_id": "subtract", - "arguments": { - "x": { - "from_parameter": "inputMax" + ], + "process_graph": { + "subtract1": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "x" + }, + "y": { + "from_parameter": "inputMin" + } + } }, - "y": { - "from_parameter": "inputMin" - } - } - }, - "subtract3": { - "process_id": "subtract", - "arguments": { - "x": { - "from_parameter": "outputMax" + "subtract2": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "inputMax" + }, + "y": { + "from_parameter": "inputMin" + } + } }, - "y": { - "from_parameter": "outputMin" - } - } - }, - "divide": { - "process_id": "divide", - "arguments": { - "x": { - "from_node": "subtract1" + "subtract3": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "outputMax" + }, + "y": { + "from_parameter": "outputMin" + } + } }, - "y": { - "from_node": "subtract2" - } - } - }, - "multiply": { - "process_id": "multiply", - "arguments": { - "x": { - "from_node": "divide" + "divide": { + "process_id": "divide", + "arguments": { + "x": { + "from_node": "subtract1" + }, + "y": { + "from_node": "subtract2" + } + } }, - "y": { - "from_node": "subtract3" - } - } - }, - "add": { - "process_id": "add", - "arguments": { - "x": { - "from_node": "multiply" + "multiply": { + "process_id": "multiply", + "arguments": { + "x": { + "from_node": "divide" + }, + "y": { + "from_node": "subtract3" + } + } }, - "y": { - "from_parameter": "outputMin" + "add": { + "process_id": "add", + "arguments": { + "x": { + "from_node": "multiply" + }, + "y": { + "from_parameter": "outputMin" + } + }, + "result": true } - }, - "result": true } - } } \ No newline at end of file diff --git a/src/processes/ln.json b/src/processes/ln.json index d824a17..b654492 100644 --- a/src/processes/ln.json +++ b/src/processes/ln.json @@ -1,67 +1,68 @@ { - "id": "ln", - "summary": "Natural logarithm", - "description": "The natural logarithm is the logarithm to the base *e* of the number `x`, which equals to using the *log* process with the base set to *e*. The natural logarithm is the inverse function of taking *e* to the power x.\n\nThe no-data value `null` is passed through.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. Therefore, `ln(0)` results in ±infinity if the processing environment supports it or otherwise an error is thrown.", - "categories": [ - "math > exponential & logarithmic" - ], - "parameters": [ - { - "name": "x", - "description": "A number to compute the natural logarithm for.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed natural logarithm.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 1 - }, - "returns": 0 - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/NaturalLogarithm.html", - "title": "Natural logarithm explained by Wolfram MathWorld" - }, - { - "rel": "about", - "href": "https://ieeexplore.ieee.org/document/8766229", - "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" - } - ], - "process_graph": { - "e": { - "process_id": "e", - "arguments": {} + "id": "ln", + "summary": "Natural logarithm", + "description": "The natural logarithm is the logarithm to the base *e* of the number `x`, which equals to using the *log* process with the base set to *e*. The natural logarithm is the inverse function of taking *e* to the power x.\n\nThe no-data value `null` is passed through.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. Therefore, *`ln(0)`* results in -infinity if the processing environment supports it or otherwise an exception is thrown. `NaN` is returned for values outside of the allowed range.", + "categories": [ + "math > exponential & logarithmic" + ], + "parameters": [ + { + "name": "x", + "description": "A number to compute the natural logarithm for in the range *[0, +∞)*.", + "schema": { + "type": [ + "number", + "null" + ], + "minimum": 0 + } + } + ], + "returns": { + "description": "The computed natural logarithm.", + "schema": { + "type": [ + "number", + "null" + ] + } }, - "log": { - "process_id": "log", - "arguments": { - "x": { - "from_parameter": "x" + "examples": [ + { + "arguments": { + "x": 1 + }, + "returns": 0 + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/NaturalLogarithm.html", + "title": "Natural logarithm explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ], + "process_graph": { + "e": { + "process_id": "e", + "arguments": {} }, - "base": { - "from_node": "e" + "log": { + "process_id": "log", + "arguments": { + "x": { + "from_parameter": "x" + }, + "base": { + "from_node": "e" + } + }, + "result": true } - }, - "result": true } - } } \ No newline at end of file diff --git a/src/processes/load_collection.json b/src/processes/load_collection.json index 603eb04..3eae90f 100644 --- a/src/processes/load_collection.json +++ b/src/processes/load_collection.json @@ -1,12 +1,11 @@ { "id": "load_collection", "summary": "Load a collection", - "description": "Loads a collection from the current back-end by its id and returns it as processable data cube. The data that is added to the data cube can be restricted with the additional `spatial_extent`, `temporal_extent`, `bands` and `properties`.\n\n**Remarks:**\n\n* The bands (and all dimensions that specify nominal dimension labels) are expected to be ordered as specified in the metadata if the `bands` parameter is set to `null`.\n* If no additional parameter is specified this would imply that the whole data set is expected to be loaded. Due to the large size of many data sets this is not recommended and may be optimized by back-ends to only load the data that is actually required after evaluating subsequent processes such as filters. This means that the pixel values should be processed only after the data has been limited to the required extents and as a consequence also to a manageable size.", + "description": "Loads a collection from the current back-end by its id and returns it as a processable data cube. The data that is added to the data cube can be restricted with the parameters `spatial_extent`, `temporal_extent`, `bands` and `properties`. If no data is available for the given extents, a `NoDataAvailable` exception is thrown.\n\n**Remarks:**\n\n* The bands (and all dimensions that specify nominal dimension labels) are expected to be ordered as specified in the metadata if the `bands` parameter is set to `null`.\n* If no additional parameter is specified this would imply that the whole data set is expected to be loaded. Due to the large size of many data sets, this is not recommended and may be optimized by back-ends to only load the data that is actually required after evaluating subsequent processes such as filters. This means that the values in the data cube should be processed only after the data has been limited to the required extent and as a consequence also to a manageable size.", "categories": [ "cubes", "import" ], - "gee:custom": true, "parameters": [ { "name": "id", @@ -19,7 +18,7 @@ }, { "name": "spatial_extent", - "description": "Limits the data to load from the collection to the specified bounding box or polygons.\n\nThe process puts a pixel into the data cube if the point at the pixel center intersects with the bounding box or any of the polygons (as defined in the Simple Features standard by the OGC).\n\nThe GeoJSON can be one of the following GeoJSON types:\n\n* A `Polygon` geometry,\n* a `GeometryCollection` containing Polygons,\n* a `Feature` with a `Polygon` geometry or\n* a `FeatureCollection` containing `Feature`s with a `Polygon` geometry.\n\nSet this parameter to `null` to set no limit for the spatial extent. Be careful with this when loading large datasets!", + "description": "Limits the data to load from the collection to the specified bounding box or polygons.\n\n* For raster data, the process loads the pixel into the data cube if the point at the pixel center intersects with the bounding box or any of the polygons (as defined in the Simple Features standard by the OGC).\n* For vector data, the process loads the geometry into the data cube if the geometry is fully *within* the bounding box or any of the polygons (as defined in the Simple Features standard by the OGC). Empty geometries may only be in the data cube if no spatial extent has been provided.\n\nThe GeoJSON can be one of the following feature types:\n\n* A `Polygon` or `MultiPolygon` geometry,\n* a `Feature` with a `Polygon` or `MultiPolygon` geometry, or\n* a `FeatureCollection` containing at least one `Feature` with `Polygon` or `MultiPolygon` geometries.\n* Empty geometries are ignored.\n\nSet this parameter to `null` to set no limit for the spatial extent. Be careful with this when loading large datasets! It is recommended to use this parameter instead of using ``filter_bbox()`` or ``filter_spatial()`` directly after loading unbounded data.", "schema": [ { "title": "Bounding Box", @@ -65,7 +64,7 @@ "default": null }, "crs": { - "description": "Coordinate reference system of the extent, specified as as [EPSG code](http://www.epsg-registry.org/), [WKT2 (ISO 19162) string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html) or [PROJ definition (deprecated)](https://proj.org/usage/quickstart.html). Defaults to `4326` (EPSG code 4326) unless the client explicitly requests a different coordinate reference system.", + "description": "Coordinate reference system of the extent, specified as as [EPSG code](http://www.epsg-registry.org/) or [WKT2 CRS string](http://docs.opengeospatial.org/is/18-010r7/18-010r7.html). Defaults to `4326` (EPSG code 4326) unless the client explicitly requests a different coordinate reference system. If the bounding box is not provided in the coordinate reference system (CRS) of the data cube, the bounding box is reprojected to the CRS of the spatial data cube dimensions.", "anyOf": [ { "title": "EPSG Code", @@ -95,11 +94,12 @@ }, { "name": "temporal_extent", - "description": "Limits the data to load from the collection to the specified left-closed temporal interval. Applies to all temporal dimensions. The interval has to be specified as an array with exactly two elements:\n\n1. The first element is the start of the temporal interval. The specified instance in time is **included** in the interval.\n2. The second element is the end of the temporal interval. The specified instance in time is **excluded** from the interval.\n\nThe specified temporal strings follow [RFC 3339](https://tools.ietf.org/html/rfc3339). Also supports open intervals by setting one of the boundaries to `null`, but never both.\n\nSet this parameter to `null` to set no limit for the spatial extent. Be careful with this when loading large datasets!", + "description": "Limits the data to load from the collection to the specified left-closed temporal interval. Applies to all temporal dimensions. The interval has to be specified as an array with exactly two elements:\n\n1. The first element is the start of the temporal interval. The specified time instant is **included** in the interval.\n2. The second element is the end of the temporal interval. The specified time instant is **excluded** from the interval.\n\nThe second element must always be greater/later than the first element. Otherwise, a `TemporalExtentEmpty` exception is thrown.\n\nAlso supports unbounded intervals by setting one of the boundaries to `null`, but never both.\n\nSet this parameter to `null` to set no limit for the temporal extent. Be careful with this when loading large datasets! It is recommended to use this parameter instead of using ``filter_temporal()`` directly after loading unbounded data.", "schema": [ { "type": "array", "subtype": "temporal-interval", + "uniqueItems": true, "minItems": 2, "maxItems": 2, "items": { @@ -107,19 +107,14 @@ { "type": "string", "format": "date-time", - "subtype": "date-time" + "subtype": "date-time", + "description": "Date and time with a time zone." }, { "type": "string", "format": "date", - "subtype": "date" - }, - { - "type": "string", - "subtype": "year", - "minLength": 4, - "maxLength": 4, - "pattern": "^\\d{4}$" + "subtype": "date", + "description": "Date only, formatted as `YYYY-MM-DD`. The time zone is UTC. Missing time components are all 0." }, { "type": "null" @@ -146,10 +141,11 @@ }, { "name": "bands", - "description": "Only adds the specified bands into the data cube so that bands that don't match the list of band names are not available. Applies to all dimensions of type `bands`.\n\nEither the unique band name (metadata field `name` in bands) or one of the common band names (metadata field `common_name` in bands) can be specified. If unique band name and common name conflict, the unique band name has higher priority.\n\nThe order of the specified array defines the order of the bands in the data cube. f multiple bands match a common name, all matched bands are included in the original order.", + "description": "Only adds the specified bands into the data cube so that bands that don't match the list of band names are not available. Applies to all dimensions of type `bands`.\n\nEither the unique band name (metadata field `name` in bands) or one of the common band names (metadata field `common_name` in bands) can be specified. If the unique band name and the common name conflict, the unique band name has a higher priority.\n\nThe order of the specified array defines the order of the bands in the data cube. If multiple bands match a common name, all matched bands are included in the original order.\n\nIt is recommended to use this parameter instead of using ``filter_bands()`` directly after loading unbounded data.", "schema": [ { "type": "array", + "minItems": 1, "items": { "type": "string", "subtype": "band-name" @@ -172,20 +168,28 @@ "subtype": "raster-cube" } }, + "exceptions": { + "NoDataAvailable": { + "message": "There is no data available for the given extents." + }, + "TemporalExtentEmpty": { + "message": "The temporal extent is empty. The second instant in time must always be greater/later than the first instant in time." + } + }, "examples": [ { "description": "Loading `Sentinel-2B` data from a `Sentinel-2` collection for 2018, but only with cloud cover between 0 and 50%.", - "arguments": { - "id": "COPERNICUS/S2", - "spatial_extent": { - "west": 16.1, - "east": 16.6, - "north": 48.6, - "south": 47.2 - }, - "temporal_extent": [ - "2018-01-01", - "2019-01-01" + "arguments": { + "id": "COPERNICUS/S2", + "spatial_extent": { + "west": 16.1, + "east": 16.6, + "north": 48.6, + "south": 47.2 + }, + "temporal_extent": [ + "2018-01-01", + "2019-01-01" ], "properties": { "eo:cloud_cover": { @@ -214,7 +218,7 @@ "y": "Sentinel-2B", "case_sensitive": false }, - "result": true + "result": true } } } @@ -223,6 +227,11 @@ } ], "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html", + "rel": "about", + "title": "Data Cubes explained in the openEO documentation" + }, { "rel": "about", "href": "https://proj.org/usage/projections.html", @@ -247,6 +256,11 @@ "rel": "about", "href": "https://github.com/radiantearth/stac-spec/tree/master/extensions/eo#common-band-names", "title": "List of common band names as specified by the STAC specification" + }, + { + "href": "https://www.rfc-editor.org/rfc/rfc3339.html", + "rel": "about", + "title": "RFC3339: Details about formatting temporal strings" } ] -} \ No newline at end of file +} diff --git a/src/processes/log.json b/src/processes/log.json index 08f1d30..fa31a29 100644 --- a/src/processes/log.json +++ b/src/processes/log.json @@ -1,81 +1,82 @@ { - "id": "log", - "summary": "Logarithm to a base", - "description": "Logarithm to the base `base` of the number `x` is defined to be the inverse function of taking b to the power of x.\n\nThe no-data value `null` is passed through and therefore gets propagated if any of the arguments is `null`.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. Therefore, `log(0, 2)` results in ±infinity if the processing environment supports it or otherwise an error is thrown.", - "categories": [ - "math > exponential & logarithmic" - ], - "parameters": [ - { - "name": "x", - "description": "A number to compute the logarithm for.", - "schema": { - "type": [ - "number", - "null" - ] - } + "id": "log", + "summary": "Logarithm to a base", + "description": "Logarithm to the base `base` of the number `x` is defined to be the inverse function of taking b to the power of x.\n\nThe no-data value `null` is passed through and therefore gets propagated if any of the arguments is `null`.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. Therefore, having `x` set to `0` with any base results in -infinity if the processing environment supports it or otherwise an exception is thrown. `NaN` is returned for values outside of the allowed range.", + "categories": [ + "math > exponential & logarithmic" + ], + "parameters": [ + { + "name": "x", + "description": "A number to compute the logarithm for in the range *[0, +∞)*.", + "schema": { + "type": [ + "number", + "null" + ], + "minimum": 0 + } + }, + { + "name": "base", + "description": "The numerical base.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed logarithm.", + "schema": { + "type": [ + "number", + "null" + ] + } }, - { - "name": "base", - "description": "The numerical base.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed logarithm.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 10, - "base": 10 - }, - "returns": 1 - }, - { - "arguments": { - "x": 2, - "base": 2 - }, - "returns": 1 - }, - { - "arguments": { - "x": 4, - "base": 2 - }, - "returns": 2 - }, - { - "arguments": { - "x": 1, - "base": 16 - }, - "returns": 0 - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/Logarithm.html", - "title": "Logarithm explained by Wolfram MathWorld" - }, - { - "rel": "about", - "href": "https://ieeexplore.ieee.org/document/8766229", - "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" - } - ] + "examples": [ + { + "arguments": { + "x": 10, + "base": 10 + }, + "returns": 1 + }, + { + "arguments": { + "x": 2, + "base": 2 + }, + "returns": 1 + }, + { + "arguments": { + "x": 4, + "base": 2 + }, + "returns": 2 + }, + { + "arguments": { + "x": 1, + "base": 16 + }, + "returns": 0 + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Logarithm.html", + "title": "Logarithm explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ] } \ No newline at end of file diff --git a/src/processes/mask.json b/src/processes/mask.json index cd7afad..852d210 100644 --- a/src/processes/mask.json +++ b/src/processes/mask.json @@ -1,47 +1,48 @@ { - "id": "mask", - "summary": "Apply a raster mask", - "description": "Applies a mask to a raster data cube. To apply a vector mask use ``mask_polygon()``.\n\nA mask is a raster data cube for which corresponding pixels among `data` and `mask` are compared and those pixels in `data` are replaced whose pixels in `mask` are non-zero (for numbers) or `true` (for boolean values). The pixel values are replaced with the value specified for `replacement`, which defaults to `null` (no data).\n\nThe data cubes have to be compatible so that each dimension in mask must also be available in the raster data cube with the same name, type, reference system, resolution and labels. Dimensions can be missing in the mask with the result that the mask is applied for each label of the missing dimension in the data cube. The process fails if there's an incompatibility found between the raster data cube and the mask.", - "categories": [ - "masks" - ], - "parameters": [ - { - "name": "data", - "description": "A raster data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "mask", - "description": "A mask as raster data cube. Every pixel in `data` must have a corresponding element in `mask`.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "replacement", - "description": "The value used to replace masked values with.", - "schema": { - "type": [ - "number", - "boolean", - "string", - "null" - ] - }, - "default": null, - "optional": true + "id": "mask", + "summary": "Apply a raster mask", + "description": "Applies a mask to a raster data cube. To apply a polygon as a mask, use ``mask_polygon()``.\n\nA mask is a raster data cube for which corresponding pixels among `data` and `mask` are compared and those pixels in `data` are replaced whose pixels in `mask` are non-zero (for numbers) or `true` (for boolean values). The pixel values are replaced with the value specified for `replacement`, which defaults to `null` (no data).\n\nThe data cubes have to be compatible except that the horizontal spatial dimensions (axes `x` and `y`) will be aligned implicitly by ``resample_cube_spatial()``. `data` is the target data cube for resampling and the default parameters of ``resample_cube_spatial()`` apply. All other dimensions in the mask must also be available in the raster data cube with the same name, type, reference system, resolution and labels. Dimensions can be missing in the mask with the result that the mask is applied to each label of the dimension in `data` that is missing in the data cube of the mask. The process fails if there's an incompatibility found between the raster data cube and the mask.", + "categories": [ + "cubes", + "masks" + ], + "parameters": [ + { + "name": "data", + "description": "A raster data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "mask", + "description": "A mask as a raster data cube. Every pixel in `data` must have a corresponding element in `mask`.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "replacement", + "description": "The value used to replace masked values with.", + "schema": { + "type": [ + "number", + "boolean", + "string", + "null" + ] + }, + "default": null, + "optional": true + } + ], + "returns": { + "description": "A masked raster data cube with the same dimensions. The dimension properties (name, type, labels, reference system and resolution) remain unchanged.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } } - ], - "returns": { - "description": "A masked raster data cube with the same dimensions. The dimension properties (name, type, labels, reference system and resolution) remain unchanged.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - } -} \ No newline at end of file +} diff --git a/src/processes/max.json b/src/processes/max.json index c730305..95b0e53 100644 --- a/src/processes/max.json +++ b/src/processes/max.json @@ -1,12 +1,12 @@ { "id": "max", "summary": "Maximum value", - "description": "Computes the largest value of an array of numbers, which is is equal to the first element of a sorted (i.e., ordered) version the array.\n\nAn array without non-`null` elements resolves always with `null`.", + "description": "Computes the largest value of an array of numbers, which is equal to the first element of a sorted (i.e., ordered) version of the array.\n\nAn array without non-`null` elements resolves always with `null`.", "categories": [ "math", + "math > statistics", "reducer" ], - "gee:custom": true, "parameters": [ { "name": "data", diff --git a/src/processes/mean.json b/src/processes/mean.json index f3ddfa3..f4f6ec8 100644 --- a/src/processes/mean.json +++ b/src/processes/mean.json @@ -3,10 +3,9 @@ "summary": "Arithmetic mean (average)", "description": "The arithmetic mean of an array of numbers is the quantity commonly called the average. It is defined as the sum of all elements divided by the number of elements.\n\nAn array without non-`null` elements resolves always with `null`.", "categories": [ - "math", + "math > statistics", "reducer" ], - "gee:custom": true, "parameters": [ { "name": "data", @@ -145,4 +144,4 @@ "result": true } } -} \ No newline at end of file +} diff --git a/src/processes/median.json b/src/processes/median.json index 9d4029b..ab884fd 100644 --- a/src/processes/median.json +++ b/src/processes/median.json @@ -1,12 +1,11 @@ { "id": "median", "summary": "Statistical median", - "description": "The statistical median of an array of numbers is the value separating the higher half from the lower half of the data.\n\nAn array without non-`null` elements resolves always with `null`.\n\n**Remarks:**\n\n* For a symmetric arrays, the result is equal to the ``mean()``.\n* The median can also be calculated by computing the ``quantiles()`` with a probability of *0.5*.", + "description": "The statistical median of an array of numbers is the value separating the higher half from the lower half of the data.\n\nAn array without non-`null` elements resolves always with `null`.\n\n**Remarks:**\n\n* For symmetric arrays, the result is equal to the ``mean()``.\n* The median can also be calculated by computing the ``quantiles()`` with a probability of *0.5*.", "categories": [ - "math", + "math > statistics", "reducer" ], - "gee:custom": true, "parameters": [ { "name": "data", @@ -124,4 +123,4 @@ "result": true } } -} \ No newline at end of file +} diff --git a/src/processes/merge_cubes.json b/src/processes/merge_cubes.json index 9b8f10b..3f6fb22 100644 --- a/src/processes/merge_cubes.json +++ b/src/processes/merge_cubes.json @@ -1,45 +1,53 @@ { - "id": "merge_cubes", - "summary": "Merging two data cubes", - "description": "The data cubes have to be compatible. A merge operation without overlap should be reversible with (a set of) filter operations for each of the two cubes. The process performs the join on overlapping dimensions, with the same name and type.\n\nAn overlapping dimension has the same name, type, reference system and resolution in both dimensions, but can have different labels. One of the dimensions can have different labels, for all other dimensions the labels must be equal. If data overlaps, the parameter `overlap_resolver` must be specified to resolve the overlap.\n\n**Examples for merging two data cubes:**\n\n1. Data cubes with the dimensions `x`, `y`, `t` and `bands` have the same dimension labels in `x`,`y` and `t`, but the labels for the dimension `bands` are `B1` and `B2` for the first cube and `B3` and `B4`. An overlap resolver is *not needed*. The merged data cube has the dimensions `x`, `y`, `t` and `bands` and the dimension `bands` has four dimension labels: `B1`, `B2`, `B3`, `B4`.\n2. Data cubes with the dimensions `x`, `y`, `t` and `bands` have the same dimension labels in `x`,`y` and `t`, but the labels for the dimension `bands` are `B1` and `B2` for the first data cube and `B2` and `B3` for the second. An overlap resolver is *required* to resolve overlap in band `B2`. The merged data cube has the dimensions `x`, `y`, `t` and `bands` and the dimension `bands` has three dimension labels: `B1`, `B2`, `B3`.\n3. Data cubes with the dimensions `x`, `y` and `t` have the same dimension labels in `x`,`y` and `t`. There are two options:\n 1. Keep the overlapping values separately in the merged data cube: An overlap resolver is *not needed*, but for each data cube you need to add a new dimension using ``add_dimension()``. The new dimensions must be equal, except that the labels for the new dimensions must differ by name. The merged data cube has the same dimensions and labels as the original data cubes, plus the dimension added with ``add_dimension()``, which has the two dimension labels after the merge.\n 2. Combine the overlapping values into a single value: An overlap resolver is *required* to resolve the overlap for all pixels. The merged data cube has the same dimensions and labels as the original data cubes, but all pixel values have been processed by the overlap resolver.\n4. Merging a data cube with dimensions `x`, `y`, `t` with another cube with dimensions `x`, `y` will join on the `x`, `y` dimension, so the lower dimension cube is merged with each time step in the higher dimensional cube. This can for instance be used to apply a digital elevation model to a spatiotemporal data cube.", - "categories": [ - "cubes" - ], - "gee:custom": true, - "parameters": [ - { - "name": "cube1", - "description": "The first data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "cube2", - "description": "The second data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }], - "returns": { + "id": "merge_cubes", + "summary": "Merge two data cubes", + "description": "The process merges two 'compatible' data cubes.\n\nThe data cubes have to be compatible, which means that they must share a common subset of equal dimensions. To conveniently get to such a subset of equal dimensions, the process tries to align the horizontal spatial dimensions (axes `x` and `y`) implicitly with ``resample_cube_spatial()`` if required. `cube1` is the target data cube for resampling and the default parameters of ``resample_cube_spatial()`` apply. The equality for geometries follows the definition in the Simple Features standard by the OGC.\n\nAll dimensions share the same properties, such as name, type, reference system, and resolution. Dimensions can have disjoint or overlapping labels. If there is any overlap between the dimension labels, the parameter `overlap_resolver` must be specified to combine the two values for these overlapping labels. A merge operation without overlap should be reversible with (a set of) filter operations for each of the two cubes, if no implicit resampling was applied.\n\nIt is not possible to merge a vector and a raster data cube. Merging vector data cubes with different base geometry types (points, lines/line strings, polygons) is not possible and throws the `IncompatibleGeometryTypes` exception. The base geometry types can be merged with their corresponding multi geometry types.\n\nAfter the merge, the dimensions with a natural/inherent label order (with a reference system this is each spatial and temporal dimensions) still have all dimension labels sorted. For other dimensions without inherent order, including bands, the dimension labels keep the order in which they are present in the original data cubes, and the dimension labels of `cube2` get appended to the dimension labels of `cube1`.\n\n**Examples for merging two data cubes:**\n\n1. Data cubes with the dimensions (`x`, `y`, `t`, `bands`) have the same dimension labels in `x`, `y` and `t`, but the labels for the dimension `bands` are `B1` and `B2` for the base data cube and `B3` and `B4` for the other. An overlap resolver is *not needed*. The merged data cube has the dimensions `x`, `y`, `t`, `bands`, and the dimension `bands` has four dimension labels: `B1`, `B2`, `B3`, `B4`.\n2. Data cubes with the dimensions (`x`, `y`, `t`, `bands`) have the same dimension labels in `x`, `y` and `t`, but the labels for the dimension `bands` are `B1` and `B2` for the base data cube and `B2` and `B3` for the other. An overlap resolver is *required* to resolve overlap in band `B2`. The merged data cube has the dimensions `x`, `y`, `t` and `bands` and the dimension `bands` has three dimension labels: `B1`, `B2`, `B3`.\n3. Data cubes with the dimensions (`x`, `y`, `t`) have the same dimension labels in `x`, `y` and `t`. There are two options:\n 1. Keep the overlapping values separately in the merged data cube: An overlap resolver is *not needed*, but for each data cube you need to add a new dimension using ``add_dimension()``. The new dimensions must be equal, except that the labels for the new dimensions must differ. The merged data cube has the same dimensions and labels as the original data cubes, plus the dimension added with ``add_dimension()``, which has the two dimension labels after the merge.\n 2. Combine the overlapping values into a single value: An overlap resolver is *required* to resolve the overlap for all values. The merged data cube has the same dimensions and labels as the original data cubes, but all values have been processed by the overlap resolver.\n4. A data cube with dimensions (`x`, `y`, `t` / `bands`) or (`x`, `y`, `t`, `bands`) and another data cube with dimensions (`x`, `y`) have the same dimension labels in `x` and `y`. Merging them will join dimensions `x` and `y`, so the lower dimension cube is merged with each time step and band available in the higher dimensional cube. A use case for this is applying a digital elevation model to a spatio-temporal data cube. An overlap resolver is *required* to resolve the overlap for all pixels.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "cube1", + "description": "The base data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "cube2", + "description": "The other data cube to be merged with the base data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + } + ], + "returns": { "description": "The merged data cube. See the process description for details regarding the dimensions and dimension properties (name, type, labels, reference system and resolution).", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - "exceptions": { - "OverlapResolverMissing": { - "message": "Overlapping data cubes, but no overlap resolver has been specified." - } - }, - "links": [ - { - "rel": "about", - "href": "https://en.wikipedia.org/wiki/Reduction_Operator", - "title": "Background information on reduction operators (binary reducers) by Wikipedia" - } - ] -} \ No newline at end of file + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + "exceptions": { + "OverlapResolverMissing": { + "message": "Overlapping data cubes, but no overlap resolver has been specified." + }, + "IncompatibleGeometryTypes": { + "message": "The geometry types are not compatible and can't be merged." + } + }, + "links": [ + { + "rel": "about", + "href": "https://en.wikipedia.org/wiki/Reduction_Operator", + "title": "Background information on reduction operators (binary reducers) by Wikipedia" + }, + { + "href": "http://www.opengeospatial.org/standards/sfa", + "rel": "about", + "title": "Simple Features standard by the OGC" + } + ] +} diff --git a/src/processes/min.json b/src/processes/min.json index f9536b0..8716b5a 100644 --- a/src/processes/min.json +++ b/src/processes/min.json @@ -1,9 +1,10 @@ { "id": "min", "summary": "Minimum value", - "description": "Computes the smallest value of an array of numbers, which is is equal to the last element of a sorted (i.e., ordered) version the array.\n\nAn array without non-`null` elements resolves always with `null`.", + "description": "Computes the smallest value of an array of numbers, which is equal to the last element of a sorted (i.e., ordered) version of the array.\n\nAn array without non-`null` elements resolves always with `null`.", "categories": [ "math", + "math > statistics", "reducer" ], "parameters": [ @@ -67,4 +68,4 @@ "title": "Minimum explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/multiply.json b/src/processes/multiply.json index ef0d5cb..8d0647c 100644 --- a/src/processes/multiply.json +++ b/src/processes/multiply.json @@ -1,7 +1,7 @@ { "id": "multiply", "summary": "Multiplication of two numbers", - "description": "Multiplies the two numbers `x` and `y` (*x * y*) and returns the computed product.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", + "description": "Multiplies the two numbers `x` and `y` (*`x * y`*) and returns the computed product.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", "categories": [ "math" ], @@ -93,4 +93,4 @@ "result": true } } -} \ No newline at end of file +} diff --git a/src/processes/nan.js b/src/processes/nan.js new file mode 100644 index 0000000..651d508 --- /dev/null +++ b/src/processes/nan.js @@ -0,0 +1,8 @@ +import GeeProcess from '../processgraph/process.js'; + +export default class nan extends GeeProcess { + + executeSync(node) { + return node.ee.Number(NaN); + } +} diff --git a/src/processes/nan.json b/src/processes/nan.json new file mode 100644 index 0000000..ae19dd6 --- /dev/null +++ b/src/processes/nan.json @@ -0,0 +1,28 @@ +{ + "id": "nan", + "summary": "Not a Number (NaN)", + "description": "`NaN` (not a number) is a symbolic floating-point representation which is neither a signed infinity nor a finite number.", + "categories": [ + "math > constants" + ], + "experimental": true, + "parameters": [], + "returns": { + "description": "Returns `NaN`.", + "schema": { + "description": "JSON Schema can't represent `NaN` and thus a schema can't be specified." + } + }, + "links": [ + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/4610935", + "title": "IEEE Standard 754-2008 for Floating-Point Arithmetic" + }, + { + "rel": "about", + "href": "http://mathworld.wolfram.com/NaN.html", + "title": "NaN explained by Wolfram MathWorld" + } + ] +} \ No newline at end of file diff --git a/src/processes/normalized_difference.json b/src/processes/normalized_difference.json index 9d766d9..9e99a72 100644 --- a/src/processes/normalized_difference.json +++ b/src/processes/normalized_difference.json @@ -1,7 +1,7 @@ { "id": "normalized_difference", "summary": "Normalized difference", - "description": "Computes the normalized difference for two bands. The normalized difference is computed as *(x - y) / (x + y)*.\n\nThis process could be used for a number of remote sensing indices such as:\n\n* [NDVI](https://eos.com/ndvi/): `x` = NIR band, `y` = red band\n* [NDWI](https://eos.com/ndwi/): `x` = NIR band, `y` = SWIR band\n* [NDSI](https://eos.com/ndsi/): `x` = green band, `y` = SWIR band\n\nSome back-ends may have native processes such as ``ndvi()`` available for convenience.", + "description": "Computes the normalized difference for two bands. The normalized difference is computed as *`(x - y) / (x + y)`*.\n\nThis process could be used for a number of remote sensing indices such as:\n\n* [NDVI](https://eos.com/ndvi/): `x` = NIR band, `y` = red band\n* [NDWI](https://eos.com/ndwi/): `x` = NIR band, `y` = SWIR band\n* [NDSI](https://eos.com/ndsi/): `x` = green band, `y` = SWIR band\n\nSome back-ends may have native processes such as ``ndvi()`` available for convenience.", "categories": [ "math > indices", "vegetation indices" @@ -83,4 +83,4 @@ "result": true } } -} \ No newline at end of file +} diff --git a/src/processes/pi.js b/src/processes/pi.js index 2fa0b46..599d5c5 100644 --- a/src/processes/pi.js +++ b/src/processes/pi.js @@ -3,8 +3,6 @@ import GeeProcess from '../processgraph/process.js'; export default class pi extends GeeProcess { executeSync(node) { - let dc = node.getDataCube('data'); - dc.setData(Math.PI); - return dc; + return node.ee.Number(Math.PI); } } diff --git a/src/processes/pi.json b/src/processes/pi.json index 136d93b..ea26089 100644 --- a/src/processes/pi.json +++ b/src/processes/pi.json @@ -1,23 +1,23 @@ { - "id": "pi", - "summary": "Pi (Ï€)", - "description": "The real number Pi (Ï€) is a mathematical constant that is the ratio of the circumference of a circle to its diameter. The numerical value is approximately *3.14159*.", - "categories": [ - "math > constants", - "math > trigonometric" - ], - "parameters": [], - "returns": { - "description": "The numerical value of Pi.", - "schema": { - "type": "number" - } - }, - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/Pi.html", - "title": "Mathematical constant Pi explained by Wolfram MathWorld" - } - ] + "id": "pi", + "summary": "Pi (Ï€)", + "description": "The real number Pi (Ï€) is a mathematical constant that is the ratio of the circumference of a circle to its diameter. The numerical value is approximately *3.14159*.", + "categories": [ + "math > constants", + "math > trigonometric" + ], + "parameters": [], + "returns": { + "description": "The numerical value of Pi.", + "schema": { + "type": "number" + } + }, + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Pi.html", + "title": "Mathematical constant Pi explained by Wolfram MathWorld" + } + ] } \ No newline at end of file diff --git a/src/processes/power.json b/src/processes/power.json index c7c3deb..d01912a 100644 --- a/src/processes/power.json +++ b/src/processes/power.json @@ -1,98 +1,98 @@ { - "id": "power", - "summary": "Exponentiation", - "description": "Computes the exponentiation for the base `base` raised to the power of `p`.\n\nThe no-data value `null` is passed through and therefore gets propagated if any of the arguments is `null`.", - "categories": [ - "math", - "math > exponential & logarithmic" - ], - "parameters": [ - { - "name": "base", - "description": "The numerical base.", - "schema": { - "type": [ - "number", - "null" - ] - } + "id": "power", + "summary": "Exponentiation", + "description": "Computes the exponentiation for the base `base` raised to the power of `p`.\n\nThe no-data value `null` is passed through and therefore gets propagated if any of the arguments is `null`.", + "categories": [ + "math", + "math > exponential & logarithmic" + ], + "parameters": [ + { + "name": "base", + "description": "The numerical base.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "p", + "description": "The numerical exponent.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed value for `base` raised to the power of `p`.", + "schema": { + "type": [ + "number", + "null" + ] + } }, - { - "name": "p", - "description": "The numerical exponent.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed value for `base` raised to the power of `p`.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "base": 0, - "p": 2 - }, - "returns": 0 - }, - { - "arguments": { - "base": 2.5, - "p": 0 - }, - "returns": 1 - }, - { - "arguments": { - "base": 3, - "p": 3 - }, - "returns": 27 - }, - { - "arguments": { - "base": 5, - "p": -1 - }, - "returns": 0.2 - }, - { - "arguments": { - "base": 1, - "p": 0.5 - }, - "returns": 1 - }, - { - "arguments": { - "base": 1, - "p": null - }, - "returns": null - }, - { - "arguments": { - "base": null, - "p": 2 - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/Power.html", - "title": "Power explained by Wolfram MathWorld" - } - ] + "examples": [ + { + "arguments": { + "base": 0, + "p": 2 + }, + "returns": 0 + }, + { + "arguments": { + "base": 2.5, + "p": 0 + }, + "returns": 1 + }, + { + "arguments": { + "base": 3, + "p": 3 + }, + "returns": 27 + }, + { + "arguments": { + "base": 5, + "p": -1 + }, + "returns": 0.2 + }, + { + "arguments": { + "base": 1, + "p": 0.5 + }, + "returns": 1 + }, + { + "arguments": { + "base": 1, + "p": null + }, + "returns": null + }, + { + "arguments": { + "base": null, + "p": 2 + }, + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Power.html", + "title": "Power explained by Wolfram MathWorld" + } + ] } \ No newline at end of file diff --git a/src/processes/product.json b/src/processes/product.json index 4ad69dc..ee5161e 100644 --- a/src/processes/product.json +++ b/src/processes/product.json @@ -6,7 +6,6 @@ "math", "reducer" ], - "gee:custom": true, "parameters": [ { "name": "data", @@ -78,4 +77,4 @@ "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" } ] -} \ No newline at end of file +} diff --git a/src/processes/reduce_dimension.json b/src/processes/reduce_dimension.json index 135834e..08237b9 100644 --- a/src/processes/reduce_dimension.json +++ b/src/processes/reduce_dimension.json @@ -1,77 +1,90 @@ { "id": "reduce_dimension", "summary": "Reduce dimensions", - "description": "Applies a unary reducer to a data cube dimension by collapsing all the pixel values along the specified dimension into an output value computed by the reducer. This process passes a list of values to the reducer. In contrast, ``reduce_dimension_binary()`` passes two values, which may be better suited especially for UDFs in case the number of values gets too large to be processed at once.\n\nThe dimension is dropped. To avoid this, use ``apply_dimension()`` instead.", + "description": "Applies a reducer to a data cube dimension by collapsing all the values along the specified dimension into an output value computed by the reducer.\n\nThe dimension is dropped. To avoid this, use ``apply_dimension()`` instead.", "categories": [ - "cubes", - "reducer" + "cubes", + "reducer" ], "parameters": [ - { - "name": "data", - "description": "A data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "reducer", - "description": "A reducer to apply on the specified dimension. A reducer is a single process such as ``mean()`` or a set of processes, which computes a single value for a list of values, see the category 'reducer' for such processes.", - "schema": { - "type": "object", - "subtype": "process-graph", - "parameters": [ - { - "name": "data", - "description": "A labeled array with elements of any type.", - "schema": { - "type": "array", - "subtype": "labeled-array", - "items": { - "description": "Any data type." + { + "name": "data", + "description": "A data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" + } + }, + { + "name": "reducer", + "description": "A reducer to apply on the specified dimension. A reducer is a single process such as ``mean()`` or a set of processes, which computes a single value for a list of values, see the category 'reducer' for such processes.", + "schema": { + "type": "object", + "subtype": "process-graph", + "parameters": [ + { + "name": "data", + "description": "A labeled array with elements of any type.", + "schema": { + "type": "array", + "subtype": "labeled-array", + "items": { + "description": "Any data type." + } + } + }, + { + "name": "context", + "description": "Additional data passed by the user.", + "schema": { + "description": "Any data type." + }, + "optional": true, + "default": null + } + ], + "returns": { + "description": "The value to be set in the new data cube.", + "schema": { + "description": "Any data type." + } } - } - }, - { - "name": "context", - "description": "Additional data passed by the user.", - "schema": { - "description": "Any data type." - }, - "optional": true, - "default": null } - ] - } - }, - { - "name": "dimension", - "description": "The name of the dimension over which to reduce. Fails with a `DimensionNotAvailable` error if the specified dimension does not exist.", - "schema": { - "type": "string" - } - }, - { - "name": "context", - "description": "Additional data to be passed to the reducer.", - "schema": { - "description": "Any data type." }, - "optional": true, - "default": null - } + { + "name": "dimension", + "description": "The name of the dimension over which to reduce. Fails with a `DimensionNotAvailable` exception if the specified dimension does not exist.", + "schema": { + "type": "string" + } + }, + { + "name": "context", + "description": "Additional data to be passed to the reducer.", + "schema": { + "description": "Any data type." + }, + "optional": true, + "default": null + } ], "returns": { "description": "A data cube with the newly computed values. It is missing the given dimension, the number of dimensions decreases by one. The dimension properties (name, type, labels, reference system and resolution) for all other dimensions remain unchanged.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } + "schema": { + "type": "object", + "subtype": "raster-cube" + } }, "exceptions": { - "DimensionNotAvailable": { - "message": "A dimension with the specified name does not exist." - } - } - } \ No newline at end of file + "DimensionNotAvailable": { + "message": "A dimension with the specified name does not exist." + } + }, + "links": [ + { + "href": "https://openeo.org/documentation/1.0/datacubes.html#reduce", + "rel": "about", + "title": "Reducers explained in the openEO documentation" + } + ] +} diff --git a/src/processes/rename_dimension.json b/src/processes/rename_dimension.json index 6de0e3c..b5dcdd5 100644 --- a/src/processes/rename_dimension.json +++ b/src/processes/rename_dimension.json @@ -16,14 +16,14 @@ }, { "name": "source", - "description": "The current name of the dimension. Fails with a `DimensionNotAvailable` error if the specified dimension does not exist.", + "description": "The current name of the dimension. Fails with a `DimensionNotAvailable` exception if the specified dimension does not exist.", "schema": { "type": "string" } }, { "name": "target", - "description": "A new Name for the dimension. Fails with a `DimensionExists` error if a dimension with the specified name exists.", + "description": "A new Name for the dimension. Fails with a `DimensionExists` exception if a dimension with the specified name exists.", "schema": { "type": "string" } @@ -44,4 +44,4 @@ "message": "A dimension with the specified name already exists." } } -} \ No newline at end of file +} diff --git a/src/processes/rename_labels.json b/src/processes/rename_labels.json index 8681a82..00b1c5f 100644 --- a/src/processes/rename_labels.json +++ b/src/processes/rename_labels.json @@ -1,112 +1,98 @@ { - "id": "rename_labels", - "summary": "Rename dimension labels", - "description": "Renames the labels of the specified dimension in the data cube from `source` to `target`.\n\nIf the array for the source labels is empty (the default), the dimension labels are expected to be enumerated with zero-based numbering (0,1,2,3,...) so that the dimension labels directly map to the indices of the array specified for the parameter `target`. If the dimension labels are not enumerated and the `target` parameter is not specified, a `LabelsNotEnumerated` is thrown. The number of source and target labels must be equal, otherwise the error `LabelMismatch` is thrown.\n\nThis process doesn't change the order of the labels and their corresponding data.", - "categories": [ - "cubes" - ], - "parameters": [ - { - "name": "data", - "description": "The data cube.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - { - "name": "dimension", - "description": "The name of the dimension to rename the labels for.", - "schema": { - "type": "string" - } - }, - { - "name": "target", - "description": "The new names for the labels. The dimension labels in the data cube are expected to be enumerated, if the parameter `target` is not specified. If a target dimension label already exists in the data cube, a `LabelExists` error is thrown.", - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" + "id": "rename_labels", + "summary": "Rename dimension labels", + "description": "Renames the labels of the specified dimension in the data cube from `source` to `target`.\n\nIf the array for the source labels is empty (the default), the dimension labels are expected to be enumerated with zero-based numbering (0,1,2,3,...) so that the dimension labels directly map to the indices of the array specified for the parameter `target`. Otherwise, the number of the source and target labels must be equal. If none of these requirements is fulfilled, the `LabelMismatch` exception is thrown.\n\nThis process doesn't change the order of the labels and their corresponding data.", + "categories": [ + "cubes" + ], + "parameters": [ + { + "name": "data", + "description": "The data cube.", + "schema": { + "type": "object", + "subtype": "raster-cube" } - ] - } - } - }, - { - "name": "source", - "description": "The names of the labels as they are currently in the data cube. The array defines an unsorted and potentially incomplete list of labels that should be renamed to the names available in the corresponding array elements in the parameter `target`. If one of the source dimension labels doesn't exist, a `LabelNotAvailable` error is thrown. By default, the array is empty so that the dimension labels in the data cube are expected to be enumerated.", - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" + }, + { + "name": "dimension", + "description": "The name of the dimension to rename the labels for.", + "schema": { + "type": "string" + } + }, + { + "name": "target", + "description": "The new names for the labels.\n\nIf a target dimension label already exists in the data cube, a `LabelExists` exception is thrown.", + "schema": { + "type": "array", + "uniqueItems": true, + "items": { + "type": [ + "number", + "string" + ] + } } - ] + }, + { + "name": "source", + "description": "The original names of the labels to be renamed to corresponding array elements in the parameter `target`. It is allowed to only specify a subset of labels to rename, as long as the `target` and `source` parameter have the same length. The order of the labels doesn't need to match the order of the dimension labels in the data cube. By default, the array is empty so that the dimension labels in the data cube are expected to be enumerated.\n\nIf the dimension labels are not enumerated and the given array is empty, the `LabelsNotEnumerated` exception is thrown. If one of the source dimension labels doesn't exist, the `LabelNotAvailable` exception is thrown.", + "schema": { + "type": "array", + "uniqueItems": true, + "items": { + "type": [ + "number", + "string" + ] + } + }, + "default": [], + "optional": true } - }, - "default": [], - "optional": true - } - ], - "returns": { + ], + "returns": { "description": "The data cube with the same dimensions. The dimension properties (name, type, labels, reference system and resolution) remain unchanged, except that for the given dimension the labels change. The old labels can not be referred to any longer. The number of labels remains the same.", - "schema": { - "type": "object", - "subtype": "raster-cube" - } - }, - "exceptions": { - "LabelsNotEnumerated": { - "message": "The dimension labels are not enumerated." - }, - "LabelMismatch": { - "message": "The number of labels in the parameters `source` and `target` don't match." + "schema": { + "type": "object", + "subtype": "raster-cube" + } }, - "LabelNotAvailable": { - "message": "A label with the specified name does not exist." + "exceptions": { + "LabelsNotEnumerated": { + "message": "The dimension labels are not enumerated." + }, + "LabelMismatch": { + "message": "The number of labels in the parameters `source` and `target` don't match." + }, + "LabelNotAvailable": { + "message": "A label with the specified name does not exist." + }, + "LabelExists": { + "message": "A label with the specified name exists." + } }, - "LabelExists": { - "message": "A label with the specified name exists." - } - }, - "examples": [ - { - "title": "Rename named labels", + "examples": [ + { + "title": "Rename named labels", "description": "Renaming the bands from `B1` to `red`, from `B2` to `green` and from `B3` to `blue`.", - "arguments": { - "data": { + "arguments": { + "data": { "from_parameter": "data" - }, - "dimension": "bands", - "source": [ - "B1", - "B2", - "B3" - ], - "target": [ - "red", - "green", - "blue" - ] - } - } + }, + "dimension": "bands", + "source": [ + "B1", + "B2", + "B3" ], - "links": [ - { - "rel": "example", - "type": "application/json", - "href": "https://processes.openeo.org/1.0.0/examples/rename-enumerated-labels.json", - "title": "Rename enumerated labels" + "target": [ + "red", + "green", + "blue" + ] + } } - ] -} \ No newline at end of file + ] +} diff --git a/src/processes/round.json b/src/processes/round.json index 7ffb9af..cb1ff9e 100644 --- a/src/processes/round.json +++ b/src/processes/round.json @@ -1,91 +1,105 @@ { - "id": "round", - "summary": "Round to a specified precision", - "description": "Rounds a real number `x` to specified precision `p`.\n\nIf the fractional part of `x` is halfway between two integers, one of which is even and the other odd, then the even number is returned.\nThis behaviour follows [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229). This kind of rounding is also called \"round to nearest (even)\" or \"banker's rounding\". It minimizes rounding errors that result from consistently rounding a midpoint value in a single direction.\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math > rounding" - ], - "parameters": [ - { - "name": "x", - "description": "A number to round.", - "schema": { - "type": [ - "number", - "null" - ] - } + "id": "round", + "summary": "Round to a specified precision", + "description": "Rounds a real number `x` to specified precision `p`.\n\nIf `x` is halfway between closest numbers of precision `p`, it is rounded to the closest even number of precision `p`.\nThis behavior follows [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) and is often called \"round to nearest (even)\" or \"banker's rounding\". It minimizes rounding errors that result from consistently rounding a midpoint value in a single direction.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math > rounding" + ], + "parameters": [ + { + "name": "x", + "description": "A number to round.", + "schema": { + "type": [ + "number", + "null" + ] + } + }, + { + "name": "p", + "description": "A positive number specifies the number of digits after the decimal point to round to. A negative number means rounding to a power of ten, so for example *-2* rounds to the nearest hundred. Defaults to *0*.", + "schema": { + "type": "integer" + }, + "default": 0, + "optional": true + } + ], + "returns": { + "description": "The rounded number.", + "schema": { + "type": [ + "number", + "null" + ] + } }, - { - "name": "p", - "description": "A positive number specifies the number of digits after the decimal point to round to. A negative number means rounding to a power of ten, so for example *-2* rounds to the nearest hundred. Defaults to *0*.", - "schema": { - "type": "integer" - }, - "default": 0, - "optional": true - } - ], - "returns": { - "description": "The rounded number.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 0 - }, - "returns": 0 - }, - { - "arguments": { - "x": 3.56, - "p": 1 - }, - "returns": 3.6 - }, - { - "arguments": { - "x": -0.4444444, - "p": 2 - }, - "returns": -0.44 - }, - { - "arguments": { - "x": -2.5 - }, - "returns": -2 - }, - { - "arguments": { - "x": -3.5 - }, - "returns": -4 - }, - { - "arguments": { - "x": 1234.5, - "p": -2 - }, - "returns": 1200 - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/AbsoluteValue.html", - "title": "Absolute value explained by Wolfram MathWorld" - }, - { - "rel": "about", - "href": "https://ieeexplore.ieee.org/document/8766229", - "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" - } - ] -} \ No newline at end of file + "examples": [ + { + "arguments": { + "x": 0 + }, + "returns": 0 + }, + { + "arguments": { + "x": 3.56, + "p": 1 + }, + "returns": 3.6 + }, + { + "arguments": { + "x": -0.4444444, + "p": 2 + }, + "returns": -0.44 + }, + { + "arguments": { + "x": -2.5 + }, + "returns": -2 + }, + { + "arguments": { + "x": -3.5 + }, + "returns": -4 + }, + { + "arguments": { + "x": 0.25, + "p": 1 + }, + "returns": 0.2 + }, + { + "arguments": { + "x": 0.35, + "p": 1 + }, + "returns": 0.4 + }, + { + "arguments": { + "x": 1234.5, + "p": -2 + }, + "returns": 1200 + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/AbsoluteValue.html", + "title": "Absolute value explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ] +} diff --git a/src/processes/save_result.json b/src/processes/save_result.json index dcc7757..0aa7f13 100644 --- a/src/processes/save_result.json +++ b/src/processes/save_result.json @@ -1,7 +1,7 @@ { "id": "save_result", - "summary": "Save processed data to storage", - "description": "Saves processed data to the local user workspace / data store of the authenticated user. This process aims to be compatible to GDAL/OGR formats and options. STAC-compatible metadata should be stored with the processed data.\n\nCalling this process may be rejected by back-ends in the context of secondary web services.", + "summary": "Save processed data", + "description": "Makes the processed data available in the given file format to the corresponding medium that is relevant for the context this processes is applied in:\n\n* For **batch jobs** the data is stored on the back-end. STAC-compatible metadata is usually made available with the processed data.\n* For **synchronous processing** the data is sent to the client as a direct response to the request.\n* **Secondary web services** are provided with the processed data so that it can make use of it (e.g., visualize it). Web service may require the data in a certain format. Please refer to the documentation of the individual service types for details.", "categories": [ "cubes", "export" @@ -9,12 +9,12 @@ "parameters": [ { "name": "data", - "description": "The data to save.", + "description": "The data to deliver in the given file format.", "schema": {} }, { "name": "format", - "description": "The file format to save to. It must be one of the values that the server reports as supported output file formats, which usually correspond to the short GDAL/OGR codes. If the format is not suitable for storing the underlying data structure, a `FormatUnsuitable` exception will be thrown. This parameter is *case insensitive*.", + "description": "The file format to use. It must be one of the values that the server reports as supported output file formats, which usually correspond to the short GDAL/OGR codes. This parameter is *case insensitive*.\n\n* If the data cube is empty and the file format can't store empty data cubes, a `DataCubeEmpty` exception is thrown.\n* If the file format is otherwise not suitable for storing the underlying data structure, a `FormatUnsuitable` exception is thrown.", "schema": { "type": "string", "subtype": "output-format" @@ -32,25 +32,29 @@ } ], "returns": { - "description": "`false` if saving failed, `true` otherwise.", + "description": "Always returns `true` as in case of an error an exception is thrown which aborts the execution of the process.", "schema": { - "type": "boolean" + "type": "boolean", + "const": true } }, "exceptions": { "FormatUnsuitable": { "message": "Data can't be transformed into the requested output format." + }, + "DataCubeEmpty": { + "message": "The file format doesn't support storing empty data cubes." } }, "links": [ { "rel": "about", - "href": "https://www.gdal.org/formats_list.html", + "href": "https://gdal.org/drivers/raster/index.html", "title": "GDAL Raster Formats" }, { "rel": "about", - "href": "https://www.gdal.org/ogr_formats.html", + "href": "https://gdal.org/drivers/vector/index.html", "title": "OGR Vector Formats" } ] diff --git a/src/processes/sd.json b/src/processes/sd.json index 88125cb..cf9c6c7 100644 --- a/src/processes/sd.json +++ b/src/processes/sd.json @@ -1,84 +1,83 @@ { - "id": "sd", - "summary": "Standard deviation", + "id": "sd", + "summary": "Standard deviation", "description": "Computes the sample standard deviation, which quantifies the amount of variation of an array of numbers. It is defined to be the square root of the corresponding variance (see ``variance()``).\n\nA low standard deviation indicates that the values tend to be close to the expected value, while a high standard deviation indicates that the values are spread out over a wider range.\n\nAn array without non-`null` elements resolves always with `null`.", - "categories": [ - "math", - "reducer" - ], - "gee:custom": true, - "parameters": [ - { - "name": "data", + "categories": [ + "math > statistics", + "reducer" + ], + "parameters": [ + { + "name": "data", "description": "An array of numbers.", - "schema": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ] + "schema": { + "type": "array", + "items": { + "type": [ + "number", + "null" + ] + } + } + } + ], + "returns": { + "description": "The computed sample standard deviation.", + "schema": { + "type": [ + "number", + "null" + ] } - } - } - ], - "returns": { - "description": "The computed sample standard deviation.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "data": [ - -1, - 1, - 3, - null - ] - }, - "returns": 2 }, - { - "description": "The input array is empty: return `null`.", - "arguments": { - "data": [] - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/StandardDeviation.html", - "title": "Standard deviation explained by Wolfram MathWorld" - } - ], - "process_graph": { - "variance": { - "process_id": "variance", - "arguments": { - "data": { - "from_parameter": "data" + "examples": [ + { + "arguments": { + "data": [ + -1, + 1, + 3, + null + ] + }, + "returns": 2 }, - "ignore_nodata": { - "from_parameter": "ignore_nodata" + { + "description": "The input array is empty: return `null`.", + "arguments": { + "data": [] + }, + "returns": null } - } - }, - "power": { - "process_id": "power", - "arguments": { - "base": { - "from_node": "variance" + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/StandardDeviation.html", + "title": "Standard deviation explained by Wolfram MathWorld" + } + ], + "process_graph": { + "variance": { + "process_id": "variance", + "arguments": { + "data": { + "from_parameter": "data" + }, + "ignore_nodata": { + "from_parameter": "ignore_nodata" + } + } }, - "p": 0.5 - }, - "result": true + "power": { + "process_id": "power", + "arguments": { + "base": { + "from_node": "variance" + }, + "p": 0.5 + }, + "result": true + } } - } -} \ No newline at end of file +} diff --git a/src/processes/sin.json b/src/processes/sin.json index 06c45cc..1528597 100644 --- a/src/processes/sin.json +++ b/src/processes/sin.json @@ -18,12 +18,14 @@ } ], "returns": { - "description": "The computed sine of `x`.", + "description": "The computed sine in the range *[-1, 1]*.", "schema": { "type": [ "number", "null" - ] + ], + "minimum": -1, + "maximum": 1 } }, "examples": [ @@ -41,4 +43,4 @@ "title": "Sine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/sinh.json b/src/processes/sinh.json index c505b3a..6eced19 100644 --- a/src/processes/sinh.json +++ b/src/processes/sinh.json @@ -1,14 +1,14 @@ { "id": "sinh", "summary": "Hyperbolic sine", - "description": "Computes the hyperbolic sine of `x`.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the hyperbolic sine of `x`.\n\nThe no-data value `null` is passed through and therefore gets propagated.", "categories": [ "math > trigonometric" ], "parameters": [ { "name": "x", - "description": "An angle in radians.", + "description": "An hyperbolic angle in radians.", "schema": { "type": [ "number", @@ -18,7 +18,7 @@ } ], "returns": { - "description": "The computed hyperbolic sine of `x`.", + "description": "The computed hyperbolic sine.", "schema": { "type": [ "number", @@ -41,4 +41,4 @@ "title": "Hyperbolic sine explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/sqrt.json b/src/processes/sqrt.json index 1d3abc3..0203c40 100644 --- a/src/processes/sqrt.json +++ b/src/processes/sqrt.json @@ -1,75 +1,80 @@ { - "id": "sqrt", - "summary": "Square root", - "description": "Computes the square root of a real number `x`, which is equal to calculating `x` to the power of *0.5*.\n\nA square root of x is a number a such that *a^2^ = x*. Therefore, the square root is the inverse function of a to the power of 2, but only for *a >= 0*.\n\nThe no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "math", - "math > exponential & logarithmic" - ], - "parameters": [ - { - "name": "x", - "description": "A number.", - "schema": { - "type": [ - "number", - "null" - ] - } - } - ], - "returns": { - "description": "The computed square root.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "x": 0 - }, - "returns": 0 - }, - { - "arguments": { - "x": 1 - }, - "returns": 1 + "id": "sqrt", + "summary": "Square root", + "description": "Computes the square root of a real number `x`, which is equal to calculating `x` to the power of *0.5*. For negative `x`, the process returns `NaN`.\n\nA square root of x is a number a such that *`a² = x`*. Therefore, the square root is the inverse function of a to the power of 2, but only for *a >= 0*.\n\nThe no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "math", + "math > exponential & logarithmic" + ], + "parameters": [ + { + "name": "x", + "description": "A number.", + "schema": { + "type": [ + "number", + "null" + ] + } + } + ], + "returns": { + "description": "The computed square root.", + "schema": { + "type": [ + "number", + "null" + ] + } }, - { - "arguments": { - "x": 9 - }, - "returns": 3 - }, - { - "arguments": { - "x": null - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/SquareRoot.html", - "title": "Square root explained by Wolfram MathWorld" - } - ], - "process_graph": { - "power": { - "process_id": "power", - "arguments": { - "base": { - "from_parameter": "x" + "examples": [ + { + "arguments": { + "x": 0 + }, + "returns": 0 + }, + { + "arguments": { + "x": 1 + }, + "returns": 1 + }, + { + "arguments": { + "x": 9 + }, + "returns": 3 + }, + { + "arguments": { + "x": null + }, + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/SquareRoot.html", + "title": "Square root explained by Wolfram MathWorld" }, - "p": 0.5 - }, - "result": true + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/8766229", + "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" + } + ], + "process_graph": { + "power": { + "process_id": "power", + "arguments": { + "base": { + "from_parameter": "x" + }, + "p": 0.5 + }, + "result": true + } } - } -} \ No newline at end of file +} diff --git a/src/processes/subtract.json b/src/processes/subtract.json index 5f8f8d0..a29e1ee 100644 --- a/src/processes/subtract.json +++ b/src/processes/subtract.json @@ -1,7 +1,7 @@ { "id": "subtract", "summary": "Subtraction of two numbers", - "description": "Subtracts argument `y` from the argument `x` (*x - y*) and returns the computed result.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", + "description": "Subtracts argument `y` from the argument `x` (*`x - y`*) and returns the computed result.\n\nNo-data values are taken into account so that `null` is returned if any element is such a value.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it.", "categories": [ "math" ], @@ -71,4 +71,4 @@ "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" } ] -} \ No newline at end of file +} diff --git a/src/processes/sum.json b/src/processes/sum.json index 0933fd7..caa0acd 100644 --- a/src/processes/sum.json +++ b/src/processes/sum.json @@ -6,7 +6,6 @@ "math", "reducer" ], - "gee:custom": true, "parameters": [ { "name": "data", @@ -78,4 +77,4 @@ "title": "IEEE Standard 754-2019 for Floating-Point Arithmetic" } ] -} \ No newline at end of file +} diff --git a/src/processes/tan.json b/src/processes/tan.json index c3952ef..6e927ff 100644 --- a/src/processes/tan.json +++ b/src/processes/tan.json @@ -1,7 +1,7 @@ { "id": "tan", "summary": "Tangent", - "description": "Computes the tangent of `x`. The tangent is defined to be the sine of x divided by the cosine of x.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the tangent of `x`. The tangent is defined to be the sine of x divided by the cosine of x.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.\n\nThe computations follow [IEEE Standard 754](https://ieeexplore.ieee.org/document/8766229) whenever the processing environment supports it. Therefore, *`tan(pi()/2 + multipliy(pi(), n))`* with `n` being any integer results in ±infinity. -infinity for negative values passed to `tan`, +infinity otherwise. If the processing environment does not supports it, an exception is thrown.", "categories": [ "math > trigonometric" ], @@ -18,7 +18,7 @@ } ], "returns": { - "description": "The computed tangent of `x`.", + "description": "The computed tangent.", "schema": { "type": [ "number", @@ -39,6 +39,11 @@ "rel": "about", "href": "http://mathworld.wolfram.com/Tangent.html", "title": "Tangent explained by Wolfram MathWorld" + }, + { + "rel": "about", + "href": "https://ieeexplore.ieee.org/document/4610935", + "title": "IEEE Standard 754-2008 for Floating-Point Arithmetic" } ] -} \ No newline at end of file +} diff --git a/src/processes/tanh.json b/src/processes/tanh.json index 203f581..a38462c 100644 --- a/src/processes/tanh.json +++ b/src/processes/tanh.json @@ -1,14 +1,14 @@ { "id": "tanh", "summary": "Hyperbolic tangent", - "description": "Computes the hyperbolic tangent of `x`. The tangent is defined to be the hyperbolic sine of x divided by the hyperbolic cosine of x.\n\nWorks on radians only.\nThe no-data value `null` is passed through and therefore gets propagated.", + "description": "Computes the hyperbolic tangent of `x`. The tangent is defined to be the hyperbolic sine of x divided by the hyperbolic cosine of x.\n\nThe no-data value `null` is passed through and therefore gets propagated.", "categories": [ "math > trigonometric" ], "parameters": [ { "name": "x", - "description": "An angle in radians.", + "description": "An hyperbolic angle in radians.", "schema": { "type": [ "number", @@ -18,12 +18,14 @@ } ], "returns": { - "description": "The computed hyperbolic tangent of `x`.", + "description": "The computed hyperbolic tangent in the range *(-1, 1)*.", "schema": { "type": [ "number", "null" - ] + ], + "minimumExclusive": -1, + "maximumExclusive": 1 } }, "examples": [ @@ -41,4 +43,4 @@ "title": "Hyperbolic tangent explained by Wolfram MathWorld" } ] -} \ No newline at end of file +} diff --git a/src/processes/text_begins.json b/src/processes/text_begins.json index 0e264fc..766d5f0 100644 --- a/src/processes/text_begins.json +++ b/src/processes/text_begins.json @@ -1,92 +1,92 @@ { - "id": "text_begins", - "summary": "Text begins with another text", - "description": "Checks whether the text (also known as *string*) specified for `data` contains the text specified for `pattern` at the beginning. Both are expected to be encoded in UTF-8 by default. The no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "texts", - "comparison" - ], - "parameters": [ - { - "name": "data", - "description": "Text in which to find something at the beginning.", - "schema": { - "type": [ - "string", - "null" - ] - } + "id": "text_begins", + "summary": "Text begins with another text", + "description": "Checks whether the text (also known as *string*) specified for `data` contains the text specified for `pattern` at the beginning. Both are expected to be encoded in UTF-8 by default. The no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "texts", + "comparison" + ], + "parameters": [ + { + "name": "data", + "description": "Text in which to find something at the beginning.", + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "pattern", + "description": "Text to find at the beginning of `data`. Regular expressions are not supported.", + "schema": { + "type": "string" + } + }, + { + "name": "case_sensitive", + "description": "Case sensitive comparison can be disabled by setting this parameter to `false`.", + "schema": { + "type": "boolean" + }, + "default": true, + "optional": true + } + ], + "returns": { + "description": "`true` if `data` begins with `pattern`, false` otherwise.", + "schema": { + "type": [ + "boolean", + "null" + ] + } }, - { - "name": "pattern", - "description": "Text to find at the beginning of `data`. Regular expressions are not supported.", - "schema": { - "type": "string" - } - }, - { - "name": "case_sensitive", - "description": "Case sensitive comparison can be disabled by setting this parameter to `false`.", - "schema": { - "type": "boolean" - }, - "default": true, - "optional": true - } - ], - "returns": { - "description": "`true` if `data` begins with `pattern`, false` otherwise.", - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "amet" - }, - "returns": false - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "Lorem" - }, - "returns": true - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "lorem" - }, - "returns": false - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "lorem", - "case_sensitive": false - }, - "returns": true - }, - { - "arguments": { - "data": "Ä", - "pattern": "ä", - "case_sensitive": false - }, - "returns": true - }, - { - "arguments": { - "data": null, - "pattern": "null" - }, - "returns": null - } - ] -} \ No newline at end of file + "examples": [ + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "amet" + }, + "returns": false + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "Lorem" + }, + "returns": true + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "lorem" + }, + "returns": false + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "lorem", + "case_sensitive": false + }, + "returns": true + }, + { + "arguments": { + "data": "Ä", + "pattern": "ä", + "case_sensitive": false + }, + "returns": true + }, + { + "arguments": { + "data": null, + "pattern": "null" + }, + "returns": null + } + ] +} diff --git a/src/processes/text_merge.js b/src/processes/text_concat.js old mode 100755 new mode 100644 similarity index 83% rename from src/processes/text_merge.js rename to src/processes/text_concat.js index 753893f..073b19a --- a/src/processes/text_merge.js +++ b/src/processes/text_concat.js @@ -1,6 +1,6 @@ import GeeProcess from '../processgraph/process.js'; -export default class text_merge extends GeeProcess { +export default class text_concat extends GeeProcess { executeSync(node) { const data = node.getArgument('data'); diff --git a/src/processes/text_concat.json b/src/processes/text_concat.json new file mode 100644 index 0000000..698c1cb --- /dev/null +++ b/src/processes/text_concat.json @@ -0,0 +1,104 @@ +{ + "id": "text_concat", + "summary": "Concatenate elements to a single text", + "description": "Merges text representations (also known as *string*) of a set of elements to a single text, having the separator between each element.", + "categories": [ + "texts" + ], + "parameters": [ + { + "name": "data", + "description": "A set of elements. Numbers, boolean values and null values get converted to their (lower case) string representation. For example: `1` (integer), `-1.5` (number), `true` / `false` (boolean values)", + "schema": { + "type": "array", + "items": { + "type": [ + "string", + "number", + "boolean", + "null" + ] + } + } + }, + { + "name": "separator", + "description": "A separator to put between each of the individual texts. Defaults to an empty string.", + "schema": { + "type": [ + "string", + "number", + "boolean", + "null" + ] + }, + "default": "", + "optional": true + } + ], + "returns": { + "description": "A string containing a string representation of all the array elements in the same order, with the separator between each element.", + "schema": { + "type": "string" + } + }, + "examples": [ + { + "arguments": { + "data": [ + "Hello", + "World" + ], + "separator": " " + }, + "returns": "Hello World" + }, + { + "arguments": { + "data": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0 + ] + }, + "returns": "1234567890" + }, + { + "arguments": { + "data": [ + null, + true, + false, + 1, + -1.5, + "ß" + ], + "separator": "\n" + }, + "returns": "null\ntrue\nfalse\n1\n-1.5\nß" + }, + { + "arguments": { + "data": [ + 2, + 0 + ], + "separator": 1 + }, + "returns": "210" + }, + { + "arguments": { + "data": [] + }, + "returns": "" + } + ] +} diff --git a/src/processes/text_contains.json b/src/processes/text_contains.json index d596985..9b78318 100644 --- a/src/processes/text_contains.json +++ b/src/processes/text_contains.json @@ -1,92 +1,92 @@ { - "id": "text_contains", - "summary": "Text contains another text", - "description": "Checks whether the text (also known as *string*) specified for `data` contains the text specified for `pattern`. Both are expected to be encoded in UTF-8 by default. The no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "texts", - "comparison" - ], - "parameters": [ - { - "name": "data", - "description": "Text in which to find something in.", - "schema": { - "type": [ - "string", - "null" - ] - } + "id": "text_contains", + "summary": "Text contains another text", + "description": "Checks whether the text (also known as *string*) specified for `data` contains the text specified for `pattern`. Both are expected to be encoded in UTF-8 by default. The no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "texts", + "comparison" + ], + "parameters": [ + { + "name": "data", + "description": "Text in which to find something in.", + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "pattern", + "description": "Text to find in `data`. Regular expressions are not supported.", + "schema": { + "type": "string" + } + }, + { + "name": "case_sensitive", + "description": "Case sensitive comparison can be disabled by setting this parameter to `false`.", + "schema": { + "type": "boolean" + }, + "default": true, + "optional": true + } + ], + "returns": { + "description": "`true` if `data` contains the `pattern`, false` otherwise.", + "schema": { + "type": [ + "boolean", + "null" + ] + } }, - { - "name": "pattern", - "description": "Text to find in `data`. Regular expressions are not supported.", - "schema": { - "type": "string" - } - }, - { - "name": "case_sensitive", - "description": "Case sensitive comparison can be disabled by setting this parameter to `false`.", - "schema": { - "type": "boolean" - }, - "default": true, - "optional": true - } - ], - "returns": { - "description": "`true` if `data` contains the `pattern`, false` otherwise.", - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "openEO" - }, - "returns": false - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "ipsum dolor" - }, - "returns": true - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "Ipsum Dolor" - }, - "returns": false - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "SIT", - "case_sensitive": false - }, - "returns": true - }, - { - "arguments": { - "data": "ÄÖÜ", - "pattern": "ö", - "case_sensitive": false - }, - "returns": true - }, - { - "arguments": { - "data": null, - "pattern": "null" - }, - "returns": null - } - ] -} \ No newline at end of file + "examples": [ + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "openEO" + }, + "returns": false + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "ipsum dolor" + }, + "returns": true + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "Ipsum Dolor" + }, + "returns": false + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "SIT", + "case_sensitive": false + }, + "returns": true + }, + { + "arguments": { + "data": "ÄÖÜ", + "pattern": "ö", + "case_sensitive": false + }, + "returns": true + }, + { + "arguments": { + "data": null, + "pattern": "null" + }, + "returns": null + } + ] +} diff --git a/src/processes/text_ends.json b/src/processes/text_ends.json index 449de74..f31e8e1 100644 --- a/src/processes/text_ends.json +++ b/src/processes/text_ends.json @@ -1,92 +1,92 @@ { - "id": "text_ends", - "summary": "Text ends with another text", - "description": "Checks whether the text (also known as *string*) specified for `data` contains the text specified for `pattern` at the end. Both are expected to be encoded in UTF-8 by default. The no-data value `null` is passed through and therefore gets propagated.", - "categories": [ - "texts", - "comparison" - ], - "parameters": [ - { - "name": "data", - "description": "Text in which to find something at the end.", - "schema": { - "type": [ - "string", - "null" - ] - } + "id": "text_ends", + "summary": "Text ends with another text", + "description": "Checks whether the text (also known as *string*) specified for `data` contains the text specified for `pattern` at the end. Both are expected to be encoded in UTF-8 by default. The no-data value `null` is passed through and therefore gets propagated.", + "categories": [ + "texts", + "comparison" + ], + "parameters": [ + { + "name": "data", + "description": "Text in which to find something at the end.", + "schema": { + "type": [ + "string", + "null" + ] + } + }, + { + "name": "pattern", + "description": "Text to find at the end of `data`. Regular expressions are not supported.", + "schema": { + "type": "string" + } + }, + { + "name": "case_sensitive", + "description": "Case sensitive comparison can be disabled by setting this parameter to `false`.", + "schema": { + "type": "boolean" + }, + "default": true, + "optional": true + } + ], + "returns": { + "description": "`true` if `data` ends with `pattern`, false` otherwise.", + "schema": { + "type": [ + "boolean", + "null" + ] + } }, - { - "name": "pattern", - "description": "Text to find at the end of `data`. Regular expressions are not supported.", - "schema": { - "type": "string" - } - }, - { - "name": "case_sensitive", - "description": "Case sensitive comparison can be disabled by setting this parameter to `false`.", - "schema": { - "type": "boolean" - }, - "default": true, - "optional": true - } - ], - "returns": { - "description": "`true` if `data` ends with `pattern`, false` otherwise.", - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "amet" - }, - "returns": true - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "AMET" - }, - "returns": false - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "Lorem" - }, - "returns": false - }, - { - "arguments": { - "data": "Lorem ipsum dolor sit amet", - "pattern": "AMET", - "case_sensitive": false - }, - "returns": true - }, - { - "arguments": { - "data": "Ä", - "pattern": "ä", - "case_sensitive": false - }, - "returns": true - }, - { - "arguments": { - "data": null, - "pattern": "null" - }, - "returns": null - } - ] -} \ No newline at end of file + "examples": [ + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "amet" + }, + "returns": true + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "AMET" + }, + "returns": false + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "Lorem" + }, + "returns": false + }, + { + "arguments": { + "data": "Lorem ipsum dolor sit amet", + "pattern": "AMET", + "case_sensitive": false + }, + "returns": true + }, + { + "arguments": { + "data": "Ä", + "pattern": "ä", + "case_sensitive": false + }, + "returns": true + }, + { + "arguments": { + "data": null, + "pattern": "null" + }, + "returns": null + } + ] +} diff --git a/src/processes/text_merge.json b/src/processes/text_merge.json deleted file mode 100755 index ec10360..0000000 --- a/src/processes/text_merge.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "id": "text_merge", - "summary": "Concatenate elements to a string", - "description": "Merges string representations of a set of elements together to a single string, with the separator between each element.", - "categories": [ - "texts" - ], - "parameters": [ - { - "name": "data", - "description": "A set of elements. Numbers, boolean values and null values get converted to their (lower case) string representation. For example: `1` (integer), `-1.5` (number), `true` / `false` (boolean values)", - "schema": { - "type": "array", - "items": { - "type": [ - "string", - "number", - "boolean", - "null" - ] - } - } - }, - { - "name": "separator", - "description": "A separator to put between each of the individual texts. Defaults to an empty string.", - "schema": { - "type": [ - "string", - "number", - "boolean", - "null" - ] - }, - "default": "", - "optional": true - } - ], - "returns": { - "description": "Returns a string containing a string representation of all the array elements in the same order, with the separator between each element.", - "schema": { - "type": "string" - } - }, - "examples": [ - { - "arguments": { - "data": [ - "Hello", - "World" - ], - "separator": " " - }, - "returns": "Hello World" - }, - { - "arguments": { - "data": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0 - ] - }, - "returns": "1234567890" - }, - { - "arguments": { - "data": [ - null, - true, - false, - 1, - -1.5, - "ß" - ], - "separator": "\n" - }, - "returns": "null\ntrue\nfalse\n1\n-1.5\nß" - }, - { - "arguments": { - "data": [ - 2, - 0 - ], - "separator": 1 - }, - "returns": "210" - }, - { - "arguments": { - "data": [] - }, - "returns": "" - } - ] -} \ No newline at end of file diff --git a/src/processes/variance.json b/src/processes/variance.json index 46ecba2..7212c05 100644 --- a/src/processes/variance.json +++ b/src/processes/variance.json @@ -1,129 +1,128 @@ { - "id": "variance", - "summary": "Variance", + "id": "variance", + "summary": "Variance", "description": "Computes the sample variance of an array of numbers by calculating the square of the standard deviation (see ``sd()``). It is defined to be the expectation of the squared deviation of a random variable from its expected value. Basically, it measures how far the numbers in the array are spread out from their average value.\n\nAn array without non-`null` elements resolves always with `null`.", - "categories": [ - "math", - "reducer" - ], - "gee:custom": true, - "parameters": [ - { - "name": "data", + "categories": [ + "math > statistics", + "reducer" + ], + "parameters": [ + { + "name": "data", "description": "An array of numbers.", - "schema": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ] + "schema": { + "type": "array", + "items": { + "type": [ + "number", + "null" + ] + } + } } - } - } - ], - "returns": { - "description": "The computed sample variance.", - "schema": { - "type": [ - "number", - "null" - ] - } - }, - "examples": [ - { - "arguments": { - "data": [ - -1, - 1, - 3 - ] - }, - "returns": 4 - }, - { - "arguments": { - "data": [ - 2, - 3, - 3, - null, - 4, - 4, - 5 - ] - }, - "returns": 1.1 - }, - { - "description": "The input array is empty: return `null`.", - "arguments": { - "data": [] - }, - "returns": null - } - ], - "links": [ - { - "rel": "about", - "href": "http://mathworld.wolfram.com/Variance.html", - "title": "Variance explained by Wolfram MathWorld" - } - ], - "process_graph": { - "mean": { - "process_id": "mean", - "arguments": { - "data": { - "from_parameter": "data" + ], + "returns": { + "description": "The computed sample variance.", + "schema": { + "type": [ + "number", + "null" + ] } - } }, - "apply": { - "process_id": "apply", - "arguments": { - "data": { - "from_parameter": "data" + "examples": [ + { + "arguments": { + "data": [ + -1, + 1, + 3 + ] + }, + "returns": 4 }, - "process": { - "process-graph": { - "subtract": { - "process_id": "subtract", - "arguments": { - "x": { - "from_parameter": "x" - }, - "y": { - "from_parameter": "context" - } - } + { + "arguments": { + "data": [ + 2, + 3, + 3, + null, + 4, + 4, + 5 + ] + }, + "returns": 1.1 + }, + { + "description": "The input array is empty: return `null`.", + "arguments": { + "data": [] }, - "power": { - "process_id": "power", - "arguments": { - "base": { - "from_node": "subtract" + "returns": null + } + ], + "links": [ + { + "rel": "about", + "href": "http://mathworld.wolfram.com/Variance.html", + "title": "Variance explained by Wolfram MathWorld" + } + ], + "process_graph": { + "mean": { + "process_id": "mean", + "arguments": { + "data": { + "from_parameter": "data" + } + } + }, + "apply": { + "process_id": "apply", + "arguments": { + "data": { + "from_parameter": "data" }, - "p": 2 - }, - "result": true + "process": { + "process-graph": { + "subtract": { + "process_id": "subtract", + "arguments": { + "x": { + "from_parameter": "x" + }, + "y": { + "from_parameter": "context" + } + } + }, + "power": { + "process_id": "power", + "arguments": { + "base": { + "from_node": "subtract" + }, + "p": 2 + }, + "result": true + } + } + }, + "context": { + "from_node": "mean" + } } - } }, - "context": { - "from_node": "mean" - } - } - }, - "mean2": { - "process_id": "mean", - "arguments": { - "data": { - "from_node": "apply" + "mean2": { + "process_id": "mean", + "arguments": { + "data": { + "from_node": "apply" + } + }, + "result": true } - }, - "result": true } - } -} \ No newline at end of file +} diff --git a/src/processgraph/commons.js b/src/processgraph/commons.js index 2e74fe0..6ac874d 100644 --- a/src/processgraph/commons.js +++ b/src/processgraph/commons.js @@ -307,30 +307,30 @@ export default class Commons { let temporalFormat = null; let seasons = {}; switch (frequency) { - case 'hourly': + case 'hour': aggregationFormat = "yyyy-MM-DD-HH"; temporalFormat = "HH"; break; - case 'daily': + case 'day': aggregationFormat = "yyyy-DDD"; temporalFormat = "DDD"; break; - case 'weekly': + case 'week': aggregationFormat = "yyyy-ww"; temporalFormat = "ww"; break; - case 'monthly': + case 'month': aggregationFormat = "yyyy-MM"; temporalFormat = "MM"; break; - case 'yearly': + case 'year': aggregationFormat = "yyyy"; temporalFormat = "yyyy"; break; - case 'seasons': + case 'season': seasons = GeeUtils.seasons(node); break; - case 'tropical_seasons': + case 'tropical-season': seasons = GeeUtils.tropicalSeasons(node); break; } @@ -338,17 +338,17 @@ export default class Commons { // prepare image collection with aggregation labels images = images.sort('system:time_start'); switch (frequency) { - case 'hourly': - case 'daily': - case 'weekly': - case 'monthly': - case 'yearly': + case 'hour': + case 'day': + case 'week': + case 'month': + case 'year': return images.map(img => { const date = img.date(); return img.set('aggregationLabel', date.format(aggregationFormat)).set("label", date.format(temporalFormat)); }); - case 'seasons': - case 'tropical_seasons': { + case 'season': + case 'tropical-season': { // This is are lists with relative months, e.g. 0 is december of the prev. year, -1 is november etc. seasons = ee.Dictionary(seasons); // Convert the relative months like -1 to their absolute values like 11. diff --git a/src/processgraph/context.js b/src/processgraph/context.js index ff11a5b..a12a304 100644 --- a/src/processgraph/context.js +++ b/src/processgraph/context.js @@ -192,7 +192,7 @@ export default class ProcessingContext { case 'json': { const data = dataCube.getData(); if (typeof data === 'undefined') { - throw new Errors.Internal({message: 'Computation did not lead to any results'}); + throw new Errors.DataCubeEmpty(); } const json = JSON.stringify(data); const stream = new StringStream(json); diff --git a/src/processgraph/datacube.js b/src/processgraph/datacube.js index 3949bcd..b2e586d 100644 --- a/src/processgraph/datacube.js +++ b/src/processgraph/datacube.js @@ -31,6 +31,16 @@ export default class DataCube { } } + toJSON() { + const dimensions = {}; + for(const name in this.dimensions) { + dimensions[name] = this.dimensions[name].toSTAC(); + } + return { + "cube:dimensions": dimensions + } + } + getLogger() { return this.logger; } diff --git a/storage/errors/custom.json b/storage/errors/custom.json index 5cebdad..f3ff0ec 100644 --- a/storage/errors/custom.json +++ b/storage/errors/custom.json @@ -135,5 +135,13 @@ "tags": [ "Processes" ] + }, + "DataCubeEmpty": { + "description": null, + "message": "The file format doesn't support storing empty data cubes.", + "http": 400, + "tags": [ + "Processes" + ] } -} \ No newline at end of file +} diff --git a/tests/processgraph.test.js b/tests/processgraph.test.js index 305a06e..d1e535a 100644 --- a/tests/processgraph.test.js +++ b/tests/processgraph.test.js @@ -26,7 +26,7 @@ describe('Process Graph Registry', () => { test('Processes', () => { const registry = serverContext.processes(); - expect(registry.count()).toBe(67); + expect(registry.count()).toBe(68); expect(registry.get('load_collection')).not.toBe(null); });