# Final visualisation strategy Input > pre-processing > analysis > output > `FINAL OUTPUT` > upload In this very generalised AIKP flow, `FINAL OUTPUT` signifies creation of the final version of data output (from AIKP) that would go to the COS and be presented in the webUI. For raster data, that means creation of COG (raster) and GeoJSON (metadata). For vector data, that means custom GeoJSON. For tabular data, that means …. For multidimensional data, that means …. For time series, that means …. ## ai makecog CLI command `/ocli/cli/ai.py` After desired output raster data is created inside the AIKP (as .tiff or ENVI), this general command/tool transformes it to COG. - determines the correct input/output files for a geospatial task (now DEM, DEM normals, or standard raster data) - verifies the input file exists and is unambiguous - calls make_cog function (`ocli/ai/export_tools/make_cog`) `ocli/ai/export_tools/make_cog` - responsible for generating a Cloud-Optimized GeoTIFF (COG) from a raster file using GDAL converts a raster input file (e.g. GeoTIFF or IMG) into a COG format - it’s essentially a polished wrapper around gdal.Translate() with added checks, logging, and smart config - input (what it expects) and output names predefined ``` bash input_default = filenames.pred8c output_path = filenames.out_cog_tiff ``` ``` bash def make_cog(input_path, output_path, callback=None, mask_band=None, nodata=None, bandList=None, overview_resampling='average'): ``` - additional options: - full / zone = passed as `@argument_zone` = full satellite image/tiff or bounding box around ROI (comes also from previous computational steps) - --source = override default input path, supports `.geojson` and `.tiff` - --nodata = if not preset during visualization step - --mask-band = if not preset during visualization step - --overview-resample <> = choice of resampling algorithms, options: - nearest = nearest neighbor interpolation, fastest, but can look blocky, best for categorical data - average = computes the mean value of the contributing input pixels, good for continuous data = DEFAULT - bilinear = bilinear interpolation, takes a weighted average of the 4 nearest input pixels, good for continuous rasters - cubic = bicubic interpolation, uses 16 surrounding pixels, produces smoother results than bilinear, but a bit slower, better for visual presentation or fine-scaled data - cubicspline =cubic spline interpolation, slower, but visually higher-quality - lanczos = high-quality interpolation using a Lanczos filter (sinc function), uses a larger neighborhood ( 6×6 pixels), slowest, but highest quality ## ai makegeojson CLI command `ai/makegeojson_startegy.py` `GeoJsonStrategy` class is responsible for generating GeoJSON data based on a given task. By default for raster data, it uses a standard method to generate metadata. However, if a custom strategy is defined in the task’s configuration, it tries to dynamically import that custom logic and execute it. This is used for other output data types like vector, for example. When initialized, it checks if the task has a template configuration by looking for a specific module (`make_geo_json.py`) inside that template (which contains a custom execute() method). - if the custom module isn’t found, it logs a message and falls back to the default built-in `make_geojson_common()` method - if the custom module is found and successfully loaded, it runs that. ### Parameters As always, additional options are available. #### --friendly-name `--friendly-name="+task specific details"` The use of --friendly-name is recommended, as it helps with finding the result in the GUI and is generally more user friendly to have a file named for example “Croatia 20-01-2023” than “zfahkfahk3837ud_uh44”. Friendly name separated by / creates the tree structure in webUI, allowing for easier file organization. Beginning of friendly name can be set with task set command before recipe creation (`task set friendly_name="user/chosen/strucutre/"` ), while this option in makegeojson step allows for adding the last step/name of the published dataset based on user decided name. - `--friendly-name="task specific details"` - overrides friendly name. - `--friendly-name="+suffix_string"` - appends the 'suffix_string' to existing friendly name. #### --cos-key `--cos-key="+_v2"` The --cos-key parameter is not necessary when the publishing is done for the first (and only) time in the task, but if the same task is being reused to publish several different files, then the use of the cos key is mandatory. - `--cos-key="custom/path/to/document"` - override file name. - `--cos-key="+_suffix_string"` - appends the '_suffix_string' to existing file name (before the extension). Example: `bucket/path/to/filename.glb` becomes `bucket/path/to/filename_suffix_string.glb` #### --friendly-name and --cos-key collaboration By default `friendly-name` and `cos-key` are taken from a task recipe. In some cases, you may need/want to reuse the existing task to publish several artifacts. So the use of `--friendly-name` and `--cos-key` simultaneously to override document name and file (artifact) name allows to not override a previously published document. `--friendly-name` and `--cos-key` changes corresponding parameters in GeoJSON document. Then it published during `ai publish post` as is. `ai upload` should upload produced task artifact with `--cos-key` taken from generated GeoJSON (by `ai makegeojson` command). ### default makegeojson for raster data `ai/export_tools.py` This is where default `make_geo_json()` function is defined (used by `make_geojson_common()` method explained above). When `make_geo_json()` is called, it generates a structured GeoJSON object based on raster metadata and configuration details from the recipe. - checks if the recipe contains all the necessary keys for generating GeoJSON—like the COS key (cloud storage unique key) and a result key - loads metadata from the specified raster file (cog_path) using GDAL tools, extracting coordinate bounds and zoom level - builds the properties for the GeoJSON: this includes information like the raster’s friendly name, storage location, roles, classification data (read from local JSON maps), and band info. Depending on the schema type (like ‘Tangram’), it composes tile source info as well. - packages all this into a GeoJSON Feature, attaches optional metadata, and returns it ### custom makegeojson module An example of this can be found in `ocli/aikp/vector_basic/`. First, `ai makegeojson` CLI command triggers the `GeoJsonStrategy` in `ai/makegeojson_startegy.py`. Since it is not a default raster data, it pickes up a custom module inside the AIKP `ocli/aikp/vector_basic/make_geo_json.py`. This module contains `execute()` that creates (in vector_basic AIKP example) `AssembleVectorData` object using the current task and calls its run() method. `AssembleVectorData` object is defined in the AIKP itself (as it can be specific for AIKP) and example can be found in `ocli/aikp/vector_basic/assemble_recipe.py`. ## AIKP developers steps If you're working with raster data and want to use the default processing path - make sure your final output is prepared as a .tiff or ENVI file so that the `ai makecog` command can convert it into a COG using the predefined input and output names - `ai makegeojson` command will automatically generate the associated GeoJSON metadata by invoking the standard `make_geo_json()` function, which extracts key raster metadata and constructs a structured GeoJSON object If you need custom logic for creating GeoJSON—for vector or other data—you have 2 options ### Option 1 - create a custom module named `make_geo_json.py` within your AIKP template - `make_go_json.py` module must contain `execute()` method with passed Repo and Task parameters: ``` bash @pass_task @pass_repo def execute(repo: Repo, task: Task) -> None: # your custom logic here ``` - `GeoJsonStrategy` will detect this custom module and execute its `execute()` method, replacing the default behavior with your custom GeoJSON generation process. - `RECIPE_DEFAULTS` dictionary in `config.py` of your AIKP should specify the module name containing the `execute()` method: ``` bash RECIPE_DEFAULTS = { 'makegeojson': 'make_geo_json', # make_geo_json.py # this name is up to you as a developer # for example 'makegeojson': 'example_module' # and this name coresponds to the example_module.py inside of AIKP directory that has execute method ...} ``` ### Option 2 Implement `makegeojson(cls, task: Task)` function inside your TaskTemplate implementation