diff --git a/GCBM_New_Demo_Run.zip b/GCBM_New_Demo_Run.zip index 250cb646..97591140 100644 Binary files a/GCBM_New_Demo_Run.zip and b/GCBM_New_Demo_Run.zip differ diff --git a/local/rest_api_gcbm/gcbm.py b/local/rest_api_gcbm/gcbm.py new file mode 100644 index 00000000..f0da5694 --- /dev/null +++ b/local/rest_api_gcbm/gcbm.py @@ -0,0 +1,566 @@ +from typing import Dict, Any + +import os +import shutil +import pathlib +import json + +import rasterio + + +class GCBMList: + """ + This is a base class for GCBM pre-processing scripts to use. It prevents users to do: ._append() + """ + + def __init__(self, files=dict(), config=[], category=None): + # TODO: set simulation folder as global + self.dirpath = "input/test-run" + self.data = list() + self.files = files + self.config = config + self.category = category + + def __iter__(self): + return self.data + + def __getitem__(self, idx): + return self.data[idx] + + def is_category(self, path): + if self.category is None: + raise NotImplementedError( + "Please implement `is_category` method, which is used by _append() method" + ) + else: + return self.category in path + + def _append(self, file_path, check=True): + # Unlike list.append() in Python, this returns a bool - whether the append was successful or not + checks if the file path is of the current category + if check: + if self.is_category(file_path): + self.data.append(file_path) + return True + return False + else: + self.data.append(file_path) + return True + + def _update_config(self): + json_paths = {} + for file in self.data: + json_config_file = GCBMList.change_extension(file, ".json") + json_filepath = os.path.join(self.dirpath, json_config_file) + + if json_config_file.name not in self.config: + self.generate_config(file, json_config_file) + else: + # TODO: This is not required I guess + with open(json_filepath, "w+") as _config: + json.dump(self.files[file], _config, indent=4) + json_paths[file] = json_filepath + return json_paths + + def generate_config(self, file, json_config_file): + filepath = os.path.join(self.dirpath, file) + json_filepath = os.path.join(self.dirpath, json_config_file) + + mode = "w+" + + with open(json_filepath, mode) as _file: + if mode == "r+": + config = json.load(_file) + else: + config = dict() + + # Defaults + if ".tiff" in file: + with rasterio.open(filepath) as raster_obj: + tr = raster_obj.transform + config["cellLatSize"] = tr[0] + config["cellLonSize"] = -tr[4] + config["nodata"] = raster_obj.nodata + + config["blockLonSize"] = config["cellLonSize"] * 400 + config["blockLatSize"] = config["cellLatSize"] * 400 + config["tileLatSize"] = config["cellLatSize"] * 4000 + config["tileLonSize"] = config["cellLonSize"] * 4000 + config["layer_type"] = "GridLayer" + config["layer_data"] = "Byte" + # TODO: Should we add these if year/type aren't provided in attributes? + # config["has_year"] = False + # config["has_type"] = False + + json.dump(config, _file, indent=4) + + self.files[file] = config + self.config.append(json_config_file.name) + + @staticmethod + def _search_in_attributes(input_dict: Dict[str, Any], to_find: str): + for key, val in input_dict.items(): + if key == to_find: + return val + if isinstance(val, dict): + return GCBMList._search_in_attributes(val, to_find) + return None + + def setattr(self, file, attributes, category): + config = self.files[file] + config["attributes"] = attributes + + for key, output_key in zip( + ["year", f"{category}_type"], ["has_year", "has_type"] + ): + val = GCBMList._search_in_attributes(attributes, key) + if val: + config[output_key] = True + + self.files[file] = config + # Output paths are returned to keep track + json_paths = self._update_config() + return json_paths + + @staticmethod + def change_extension(file_path, new_extension): + # TODO: let's use pathlib.Path everywhere, for now it's okay here + pathlib_path = pathlib.Path(file_path) + return pathlib_path.with_suffix(new_extension) + + +class GCBMDisturbanceList(GCBMList): + def __init__(self, files, config): + category = "disturbance" + self.dirpath = "input/test-run" + self.files = files + self.config = config + super().__init__(files=files, config=config, category=category) + + +class GCBMclassifierList(GCBMList): + def __init__(self, files, config): + self.dirpath = "input/test-run" + category = "classifier" + self.files = files + self.config = config + super().__init__(category=category) + + +class GCBMMiscellaneousList(GCBMList): + def __init__(self, files, config): + self.dirpath = "input/test-run" + category = "miscellaneous" + self.files = files + self.config = config + super().__init__(category=category) + + +class GCBMDatabase: + def __init__(self): + self.files = [] + self.config = [{"SQLite": {}}] + + def _append(self, file_path, check=True): + if check: + if ".db" in file_path: + self.files.append(file_path) + return True + else: + return False + else: + self.files.append(file_path) + return True + + def _update_config(self): + for idx, _ in enumerate(self.config): + self.config[idx]["SQLite"] = {"path": self.files[idx], "type": "SQLite"} + + +class GCBMSimulation: + def __init__(self): + # create a global index + self.dirpath = "input/test-run" + self.config_dir_path = "templates" + self.files = {} + + # Tracks the output path for the input received through `add_file` method + self.json_paths = {} + + # TODO: Once categories are changed from strings to Enums, we should find a better way to have supported categories + self.supported_categories = ["classifier", "disturbance", "miscellaneous", "db"] + + # create sub-indices of different types + self.config = list() + self.parameters = [] # this is the input_db + + self.create_simulation_folder() + self.create_file_index() + + self.classifier = GCBMclassifierList(files={}, config=self.config) + self.disturbance = GCBMDisturbanceList(files={}, config=self.config) + self.miscellaneous = GCBMMiscellaneousList(files={}, config=self.config) + self.db = GCBMDatabase() + + def create_simulation_folder(self): + for dir_path in [self.dirpath, self.config_dir_path]: + if not os.path.exists(dir_path): + os.makedirs(dir_path) + + def create_file_index(self): + assert os.path.isdir( + self.config_dir_path + ), f"Given config directory path: {self.config_dir_path} either does not exist or is not a directory." + for dirpath, _, filenames in os.walk(self.config_dir_path): + for filename in filenames: + # Don't read any data, but create the json file + abs_filepath = os.path.abspath(os.path.join(dirpath, filename)) + + data = GCBMSimulation.safe_read_json(abs_filepath) + + # TODO: Discussion - should this be abs_filepath, or do we want just the filename? + self.files[filename] = data + + # TODO: This should not happen here? maybe connect an endpoint directly to the sync_config method + # self.sync_config(abs_filepath) + + # AO: sync_config is a write method, saving the current config + # state file - doing dumb copy until implemented. + sim_filepath = os.path.join(self.dirpath, filename) + shutil.copy(abs_filepath, sim_filepath) + + def _insert_sql_data(self): + data = {} + # Question to Andrew: there will always be one database file that will be uploaded, right? + # in the app.py, L266, we loop through {input_dir}/db/ folder, and keep overwriting the data["Providers"]["SQLite"] + # so only one file's data is stored (that is the last one from os.listdir) + for file_path in self.db.files: + data["path"] = os.path.abspath(file_path) + data["type"] = "SQLite" + return data + + def _insert_categories_data(self): + data = [] + for category in self.supported_categories: + # We have handled SQL in _insert_sql_data() + if category == "db": + continue + for file_path in getattr(self, category).data: + dict_category = {} + dict_category["name"] = file_path.strip(".tiff") + dict_category["layer_path"] = os.path.abspath(file_path) + # Question to Andrew: since suffix is gone for the file paths, this (layer_prefix) is not required, right? + dict_category["layer_prefix"] = dict_category["name"] + data.append(dict_category) + return data + + def _fill_sizes(self, data, keys): + # TODO: We need to assert that all files have the same data... @ankitaS11 + visited = {x: False for x in keys} + for key in keys: + if visited[key]: + continue + for val in self.classifier.files.values(): + if key in val: + data["Providers"]["RasterTiled"][key] = val[key] + visited[key] = True + return data + + def _generate_provider_config(self, dirpath: str): + with open(f"{dirpath}/provider_config.json", "r+") as provider_config: + data = json.load(provider_config) + + provider_config.seek(0) + data["Providers"]["SQLite"] = self._insert_sql_data() + data["Providers"]["RasterTiled"]["layers"] = self._insert_categories_data() + self._fill_sizes(data, ["cellLonSize", "cellLatSize", "blockLonSize", "blockLatSize", "tileLatSize", "tileLonSize"]) + + json.dump(data, provider_config, indent=4) + + def _generate_modules_cbm_config(self, dirpath: str): + with open(f"{dirpath}/modules_cbm.json", "r+") as modules_cbm_config: + data = json.load(modules_cbm_config) + modules_cbm_config.seek(0) + data["Modules"]["CBMDisturbanceListener"]["settings"]["vars"] = [os.path.splitext(path)[0] for path in self.disturbance.data] + json.dump(data, modules_cbm_config, indent=4) + + def _add_variables(self, dirpath: str): + with open(f"{dirpath}/variables.json", "r+") as variables_config: + data = json.load(variables_config) + variables_config.seek(0) + for category in self.supported_categories: + if category == "db": + continue + for path in getattr(self, category).data: + name = os.path.splitext(path)[0] + data["Variables"][name] = { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": name + } + } + json.dump(data, variables_config, indent=4) + + # file_path: disturbance (NOT MUST), classifier (MUST), miscellaneous (MUST) + def add_file(self, file_path: str, category: str = ""): + """ + This function: + + 1. Checks if the given file is one of the categories: registers, classifier, and miscellaneous. + 2. The provided file path to the buffer, and updates the config (JSON). + + Parameters + ========== + 1. file_path (str), no default + 2. category (str), default = "", if skipped - then the categories will be deduced from the file path + """ + + # TODO: update to accept input from Flask endpoint + # FIXME: The flask end point should do the pre-processing to be able to only pass the `file_path` as a string + # TODO: update in app.py to send valid data to add_file + filename = os.path.basename(file_path) + shutil.copy(file_path, os.path.join(self.dirpath, filename)) + + def _disturbance(filename, check=True): + if self.disturbance._append(filename, check): + self.json_paths.update(self.disturbance._update_config()) + + def _classifier(filename, check=True): + if self.classifier._append(filename, check): + self.json_paths.update(self.classifier._update_config()) + + def _miscellaneous(filename, check=True): + if self.miscellaneous._append(filename, check): + self.json_paths.update(self.miscellaneous._update_config()) + + def _db(filename, check=True): + if self.db._append(filename, check): + # This just stores, and doesn't write anything yet... + self.db._update_config() + + if category != "": + if category == "disturbance": + _disturbance(filename, check=False) + elif category == "classifier": + print("Found it here: ", filename) + _classifier(filename, check=False) + elif category == "miscellaneous": + _miscellaneous(filename, check=False) + elif category == "db": + _db(filename, check=False) + else: + raise ValueError( + f"Given category {category} not supported, supported categories are: {self.supported_categories}" + ) + else: + deduced_category = "" + if self.disturbance._append(filename): + self.json_paths.update(self.disturbance._update_config()) + deduced_category = "disturbance" + elif self.classifier._append(filename): + self.json_paths.update(self.classifier._update_config()) + deduced_category = "classifier" + elif self.miscellaneous._append(filename): + self.json_paths.update(self.miscellaneous._update_config()) + deduced_category = "miscellaneous" + elif self.db._append(filename): + self.db._update_config() + deduced_category = "db" + else: + raise ValueError( + f"Couldn't deduce a valid from the file path {file_path}, supported categories: {self.supported_categories}" + ) + print( + f"Category wasn't provided, deduced category: {deduced_category} it from the file path: {file_path}" + ) + + def generate_configs(self): + self._generate_provider_config(self.dirpath) + self._generate_modules_cbm_config(self.dirpath) + self._add_variables(self.dirpath) + + def sync_config(self, file_path): + def _write_to_file(file_path, data): + with open(file_path, "w+") as _file: + _file.write(data) + + data = GCBMSimulation.safe_read_json(file_path) + + if self.files[file_path] != data: + # Means data has changed, so update the file_path + _write_to_file(file_path, data) + # Also update the dict + self.files[file_path] = data + + # TODO (@ankitaS11): We can just have these as class methods later, this will reduce the redundancy in the code later + def update_disturbance_config(self): + self.json_paths.update(self.disturbance._update_config()) + + def update_classifier_config(self): + self.json_paths.update(self.classifier._update_config()) + + def update_miscellaneous_config(self): + self.json_paths.update(self.miscellaneous._update_config()) + + # TODO: category should be an enum instead of a string to avoid any mistakes + def set_attributes(self, category: str, file_path: str, payload: dict): + base_path = os.path.basename(file_path) + if category == "disturbance": + self.disturbance.setattr( + file=base_path, attributes=payload, category=category + ) + elif category == "classifier": + self.classifier.setattr( + file=base_path, attributes=payload, category=category + ) + elif category == "miscellaneous": + self.miscellaneous.setattr( + file=base_path, attributes=payload, category=category + ) + else: + raise ValueError( + f"Expected a valid category name out of {self.supported_categories}, but got {category}. Note that setting attributes for a database file is not supported." + ) + + @staticmethod + def safe_read_json(file_path): + + # TODO: add read method for gcbm_config.cfg and logging.conf + if ".cfg" in file_path: + filename = os.path.join("input/test-run", "gcbm_config.cfg") + shutil.copy(file_path, filename) + return {} + + if ".conf" in file_path: + filename = os.path.join("input/test-run", "logging.conf") + shutil.copy(file_path, filename) + return {} + + # check JSON + if ".json" not in file_path: + raise UserWarning(f"Given path {file_path} not a valid json file") + + # Make sure it's a file and not a directory + if not os.path.isfile(file_path): + raise UserWarning( + f"Got a directory {file_path} inside the config directory path, skipping it." + ) + with open(file_path, "r") as json_file: + data = json.load(json_file) + return data + + +if __name__ == "__main__": + sim = GCBMSimulation() + sim.add_file( + "tests/reference/test_data/new_demo_run/disturbances_2011.tiff", category="disturbance" + ) + # sim.set_attributes("disturbances_2011.tiff", {"year": 2011, "disturbance_type": "Wildfire", "transition": 1}) + sim.set_attributes( + category="disturbance", + file_path="disturbances_2011.tiff", + payload={"year": 2011, "disturbance_type": "Wildfire", "transition": 1}, + ) + + sim.add_file( + "tests/reference/test_data/new_demo_run/disturbances_2012.tiff", category="disturbance" + ) + sim.set_attributes( + file_path="disturbances_2012.tiff", + category="disturbance", + payload={"year": 2012, "disturbance_type": "Wildfire", "transition": 1}, + ) + + sim.add_file("tests/reference/test_data/new_demo_run/disturbances_2013.tiff") + # sim.set_attributes( + # file_path="disturbances_2013.tiff", + # category="disturbance", + # payload={ + # "year": 2013, + # "disturbance_type": "Mountain pine beetle — Very severe impact", + # "transition": 1, + # }, + # ) + + # TODO: Check how to handle multiple attributes entries (L442-451 of `app.py:master`) + sim.set_attributes( + file_path="disturbances_2013.tiff", + category="disturbance", + payload={ + "1": { + "year": 2013, + "disturbance_type": "Mountain pine beetle — Very severe impact", + "transition": 1, + }, + "2": {"year": 2013, "disturbance_type": "Wildfire", "transition": 1}, + }, + ) + + sim.add_file("tests/reference/test_data/new_demo_run/disturbances_2014.tiff") + sim.set_attributes( + file_path="disturbances_2014.tiff", + category="disturbance", + payload={ + "year": 2014, + "disturbance_type": "Mountain pine beetle — Very severe impact", + "transition": 1, + }, + ) + + sim.add_file("tests/reference/test_data/new_demo_run/disturbances_2015.tiff") + sim.set_attributes( + file_path="disturbances_2015.tiff", + category="disturbance", + payload={"year": 2015, "disturbance_type": "Wildfire", "transition": 1}, + ) + + sim.add_file("tests/reference/test_data/new_demo_run/disturbances_2016.tiff") + sim.set_attributes( + file_path="disturbances_2016.tiff", + category="disturbance", + payload={"year": 2016, "disturbance_type": "Wildfire", "transition": 1}, + ) + + sim.add_file("tests/reference/test_data/new_demo_run/disturbances_2018.tiff") + sim.set_attributes( + file_path="disturbances_2018.tiff", + category="disturbance", + payload={"year": 2018, "disturbance_type": "Wildfire", "transition": 1}, + ) + + # TODO: classifier don't have 'year' attributes + sim.add_file("tests/reference/test_data/new_demo_run/Classifier1.tiff", category="classifier") + sim.set_attributes( + file_path="Classifier1.tiff", + category="classifier", + payload={ + "1": "TA", + "2": "BP", + "3": "BS", + "4": "JP", + "5": "WS", + "6": "WB", + "7": "BF", + "8": "GA", + }, + ) + + sim.add_file("tests/reference/test_data/new_demo_run/Classifier2.tiff", category="classifier") + sim.set_attributes( + file_path="Classifier2.tiff", + category="classifier", + payload={"1": "5", "2": "6", "3": "7", "4": "8"}, + ) + + sim.add_file( + "tests/reference/test_data/new_demo_run/initial_age.tiff", category="miscellaneous" + ) + sim.add_file( + "tests/reference/test_data/new_demo_run/mean_annual_temperature.tiff", + category="miscellaneous", + ) + + # TODO: make it work + sim.add_file("tests/reference/test_data/new_demo_run/gcbm_input.db") + sim.generate_configs() diff --git a/local/rest_api_gcbm/templates/modules_cbm.json b/local/rest_api_gcbm/templates/modules_cbm.json index 0b237195..4af42093 100644 --- a/local/rest_api_gcbm/templates/modules_cbm.json +++ b/local/rest_api_gcbm/templates/modules_cbm.json @@ -13,9 +13,7 @@ "order": 3, "library": "moja.modules.cbm", "settings": { - "vars": [ - - ] + "vars": [] } }, "CBMDisturbanceEventModule": { @@ -56,4 +54,4 @@ "library": "internal.flint" } } -} \ No newline at end of file +} diff --git a/local/rest_api_gcbm/templates/provider_config.json b/local/rest_api_gcbm/templates/provider_config.json index 43343960..e600288b 100644 --- a/local/rest_api_gcbm/templates/provider_config.json +++ b/local/rest_api_gcbm/templates/provider_config.json @@ -1,7 +1,7 @@ { "Providers": { "SQLite": { - "path": "../input_database/gcbm_input.db", + "path": "", "type": "SQLite" }, "RasterTiled": { diff --git a/local/rest_api_gcbm/templates/variables.json b/local/rest_api_gcbm/templates/variables.json index f2d8bc2f..211de747 100644 --- a/local/rest_api_gcbm/templates/variables.json +++ b/local/rest_api_gcbm/templates/variables.json @@ -107,16 +107,6 @@ "provider": "SQLite" } }, - "initial_classifier_set": { - "transform": { - "type": "CompositeTransform", - "library": "internal.flint", - "vars": [ - "Classifier2", - "Classifier1" - ] - } - }, "disturbance_matrix_associations": { "transform": { "queryString": "SELECT dt.name AS disturbance_type, dma.spatial_unit_id, dma.disturbance_matrix_id FROM disturbance_matrix_association dma INNER JOIN disturbance_type dt ON dma.disturbance_type_id = dt.id", @@ -165,14 +155,6 @@ "provider": "SQLite" } }, - "mean_annual_temperature": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "mean_annual_temperature" - } - }, "decay_parameters": { "transform": { "queryString": "SELECT p.name AS pool, dp.base_decay_rate AS organic_matter_decay_rate, dp.prop_to_atmosphere AS prop_to_atmosphere, dp.q10 AS q10, dp.reference_temp AS reference_temp, dp.max_rate AS max_decay_rate_soft FROM decay_parameter dp INNER JOIN dom_pool dom ON dp.dom_pool_id = dom.id INNER JOIN pool p ON p.id = dom.pool_id", @@ -180,78 +162,6 @@ "library": "internal.flint", "provider": "SQLite" } - }, - "disturbances_2012": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "disturbances_2012" - } - }, - "disturbances_2011": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "disturbances_2011" - } - }, - "disturbances_2015": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "disturbances_2015" - } - }, - "disturbances_2014": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "disturbances_2014" - } - }, - "disturbances_2018": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "disturbances_2018" - } - }, - "disturbances_2016": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "disturbances_2016" - } - }, - "Classifier2": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "Classifier2" - } - }, - "Classifier1": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "Classifier1" - } - }, - "disturbances_2013": { - "transform": { - "library": "internal.flint", - "type": "LocationIdxFromFlintDataTransform", - "provider": "RasterTiled", - "data_id": "disturbances_2013" - } } } -} \ No newline at end of file +} diff --git a/local/rest_api_gcbm/tests/compare_json.py b/local/rest_api_gcbm/tests/compare_json.py new file mode 100644 index 00000000..ca0d0d31 --- /dev/null +++ b/local/rest_api_gcbm/tests/compare_json.py @@ -0,0 +1,52 @@ +import os +import json +import sys + +def compare_json(json_1, json_2): + try: + assert sorted(json_1.items()) == sorted(json_2.items()) + return True + except AssertionError: + return False + +def read_json(path: str): + with open(path, "r") as _file: + return json.load(_file) + +if __name__ == "__main__": + if len(sys.argv) >= 3: + original_folder = sys.argv[1] + new_folder = sys.argv[2] + print(f"Note: using {original_folder} for original JSONs and {new_folder} for new JSONs folders.") + else: + original_folder = "tests/reference/" + new_folder = "input/test-run/" + original_paths = sorted(os.listdir(original_folder)) + + #TODO: how do we check non-json config + new_paths = [file for file in sorted(os.listdir(new_folder)) if ".json" in file] + + didnt_match = [] + matched = [] + for path, new_path in zip(original_paths, new_paths): + + path = original_folder + path + new_path = new_folder + new_path + + print(f"Now comparing: {path} vs {new_path}") + if ".json" in path: + obj_original, obj_new = read_json(path), read_json(new_path) + did_match = compare_json(obj_original, obj_new) + + if not did_match: + didnt_match.append(new_path) + else: + matched.append(path) + + + print(f"Failures: {len(didnt_match)}/{len(new_paths)}") + print(f"Success: {len(matched)}/{len(new_paths)}") + + if len(didnt_match) != 0: + print("Files that didn't match are: ") + print(didnt_match) diff --git a/local/rest_api_gcbm/tests/readme.md b/local/rest_api_gcbm/tests/readme.md new file mode 100644 index 00000000..431d4488 --- /dev/null +++ b/local/rest_api_gcbm/tests/readme.md @@ -0,0 +1,6 @@ +## Compare auto-generated config against the GCBM Demo run + +Steps: +1. Extract `GCBM_New_Demo_Run.zip` into `local/rest_api_gcbm/tests/` +2. Run `python3 gcbm.py` +3. Run `python3 tests/compare_json.py` diff --git a/local/rest_api_gcbm/tests/reference/Classifier1.json b/local/rest_api_gcbm/tests/reference/Classifier1.json new file mode 100644 index 00000000..f1b22ebc --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/Classifier1.json @@ -0,0 +1,21 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": "TA", + "2": "BP", + "3": "BS", + "4": "JP", + "5": "WS", + "6": "WB", + "7": "BF", + "8": "GA" + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/Classifier2.json b/local/rest_api_gcbm/tests/reference/Classifier2.json new file mode 100644 index 00000000..fc46071e --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/Classifier2.json @@ -0,0 +1,17 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": "5", + "2": "6", + "3": "7", + "4": "8" + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/disturbances_2011.json b/local/rest_api_gcbm/tests/reference/disturbances_2011.json new file mode 100644 index 00000000..25a3c9bf --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/disturbances_2011.json @@ -0,0 +1,18 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": { + "year": 2011, + "disturbance_type": "Wildfire", + "transition": 1 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/disturbances_2012.json b/local/rest_api_gcbm/tests/reference/disturbances_2012.json new file mode 100644 index 00000000..15500f70 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/disturbances_2012.json @@ -0,0 +1,18 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": { + "year": 2012, + "disturbance_type": "Wildfire", + "transition": 1 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/disturbances_2013.json b/local/rest_api_gcbm/tests/reference/disturbances_2013.json new file mode 100644 index 00000000..90c451d5 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/disturbances_2013.json @@ -0,0 +1,23 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": { + "year": 2013, + "disturbance_type": "Mountain pine beetle — Very severe impact", + "transition": 1 + }, + "2": { + "year": 2013, + "disturbance_type": "Wildfire", + "transition": 1 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/disturbances_2014.json b/local/rest_api_gcbm/tests/reference/disturbances_2014.json new file mode 100644 index 00000000..16426963 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/disturbances_2014.json @@ -0,0 +1,18 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": { + "year": 2014, + "disturbance_type": "Mountain pine beetle — Very severe impact", + "transition": 1 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/disturbances_2015.json b/local/rest_api_gcbm/tests/reference/disturbances_2015.json new file mode 100644 index 00000000..72869bdb --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/disturbances_2015.json @@ -0,0 +1,18 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": { + "year": 2015, + "disturbance_type": "Wildfire", + "transition": 1 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/disturbances_2016.json b/local/rest_api_gcbm/tests/reference/disturbances_2016.json new file mode 100644 index 00000000..ab2b0d62 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/disturbances_2016.json @@ -0,0 +1,18 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": { + "year": 2016, + "disturbance_type": "Wildfire", + "transition": 1 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/disturbances_2018.json b/local/rest_api_gcbm/tests/reference/disturbances_2018.json new file mode 100644 index 00000000..f7c50f24 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/disturbances_2018.json @@ -0,0 +1,18 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "attributes": { + "1": { + "year": 2018, + "disturbance_type": "Mountain pine beetle — Low impact", + "transition": 1 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/gcbm_config.cfg b/local/rest_api_gcbm/tests/reference/gcbm_config.cfg new file mode 100644 index 00000000..e6640ac9 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/gcbm_config.cfg @@ -0,0 +1,7 @@ +config=localdomain.json +config=pools_cbm.json +config=modules_cbm.json +config=modules_output.json +config=spinup.json +config=variables.json +config=internal_variables.json diff --git a/local/rest_api_gcbm/tests/reference/initial_age.json b/local/rest_api_gcbm/tests/reference/initial_age.json new file mode 100644 index 00000000..348249e7 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/initial_age.json @@ -0,0 +1,11 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Int16", + "nodata": 32767, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025 +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/internal_variables.json b/local/rest_api_gcbm/tests/reference/internal_variables.json new file mode 100644 index 00000000..d9f71537 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/internal_variables.json @@ -0,0 +1,34 @@ +{ + "Variables": { + "spatialLocationInfo": { + "flintdata": { + "type": "SpatialLocationInfo", + "library": "internal.flint", + "settings": {} + } + }, + "simulateLandUnit": true, + "is_decaying": true, + "spinup_moss_only": false, + "run_peatland": false, + "peatlandId": -1, + "is_forest": true, + "run_moss": false, + "run_delay": false, + "landUnitBuildSuccess": true, + "regen_delay": 0, + "age": 0, + "tileIndex": 0, + "blockIndex": 0, + "cellIndex": 0, + "LandUnitId": -1, + "landUnitArea": 0, + "classifier_set": {}, + "localDomainId": 0, + "LocalDomainId": 1, + "age_class": 0, + "historic_land_class": "FL", + "current_land_class": "FL", + "unfccc_land_class": "UNFCCC_FL_R_FL" + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/localdomain.json b/local/rest_api_gcbm/tests/reference/localdomain.json new file mode 100644 index 00000000..5bb04f33 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/localdomain.json @@ -0,0 +1,31 @@ +{ + "Libraries": { + "moja.modules.cbm": "external", + "moja.modules.gdal": "external" + }, + "LocalDomain": { + "start_date": "2010/01/01", + "end_date": "2021/01/01", + "landUnitBuildSuccess": "landUnitBuildSuccess", + "simulateLandUnit": "simulateLandUnit", + "sequencer_library": "moja.modules.cbm", + "sequencer": "CBMSequencer", + "timing": "annual", + "type": "spatial_tiled", + "landscape": { + "provider": "RasterTiled", + "num_threads": 4, + "tiles": [ + { + "x": -106, + "y": 55, + "index": 12674 + } + ], + "x_pixels": 4000, + "y_pixels": 4000, + "tile_size_x": 1.0, + "tile_size_y": 1.0 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/logging.conf b/local/rest_api_gcbm/tests/reference/logging.conf new file mode 100644 index 00000000..a2c0b8e0 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/logging.conf @@ -0,0 +1,17 @@ +[Core] +DisableLogging=false + +[Sinks.console] +Destination=Console +Asynchronous=false +AutoFlush=true +Format="<%TimeStamp%> (%Severity%) - %Message%" +Filter="%Severity% >= info" + +[Sinks.file] +Destination=TextFile +FileName="..\\output\\logs\\Moja_Debug.log" +Asynchronous=false +AutoFlush=true +Format="<%TimeStamp%> (%Severity%) - %Message%" +Filter="%Severity% >= debug" diff --git a/local/rest_api_gcbm/tests/reference/mean_annual_temperature.json b/local/rest_api_gcbm/tests/reference/mean_annual_temperature.json new file mode 100644 index 00000000..4a83b6e3 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/mean_annual_temperature.json @@ -0,0 +1,11 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Float32", + "nodata": 3.4e+38, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025 +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/modules_cbm.json b/local/rest_api_gcbm/tests/reference/modules_cbm.json new file mode 100644 index 00000000..5be43b01 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/modules_cbm.json @@ -0,0 +1,65 @@ +{ + "Modules": { + "CBMBuildLandUnitModule": { + "order": 1, + "library": "moja.modules.cbm" + }, + "CBMSequencer": { + "order": 2, + "library": "moja.modules.cbm" + }, + "CBMDisturbanceListener": { + "enabled": true, + "order": 3, + "library": "moja.modules.cbm", + "settings": { + "vars": [ + "disturbances_2012", + "disturbances_2011", + "disturbances_2015", + "disturbances_2016", + "disturbances_2018", + "disturbances_2014", + "disturbances_2013" + ] + } + }, + "CBMDisturbanceEventModule": { + "enabled": true, + "order": 4, + "library": "moja.modules.cbm" + }, + "CBMTransitionRulesModule": { + "enabled": true, + "order": 5, + "library": "moja.modules.cbm" + }, + "CBMLandClassTransitionModule": { + "enabled": true, + "order": 6, + "library": "moja.modules.cbm" + }, + "CBMGrowthModule": { + "enabled": true, + "order": 7, + "library": "moja.modules.cbm" + }, + "CBMDecayModule": { + "enabled": true, + "order": 8, + "library": "moja.modules.cbm", + "settings": { + "extra_decay_removals": false + } + }, + "CBMAgeIndicators": { + "enabled": true, + "order": 9, + "library": "moja.modules.cbm" + }, + "TransactionManagerAfterSubmitModule": { + "order": 10, + "library": "internal.flint" + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/modules_output.json b/local/rest_api_gcbm/tests/reference/modules_output.json new file mode 100644 index 00000000..717f648b --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/modules_output.json @@ -0,0 +1,816 @@ +{ + "Modules": { + "WriteVariableGeotiff": { + "enabled": true, + "order": 11, + "library": "moja.modules.gdal", + "settings": { + "items": [ + { + "data_name": "Age", + "enabled": true, + "variable_data_type": "Int16", + "on_notification": "OutputStep", + "variable_name": "age" + }, + { + "pool_name": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther" + ], + "data_name": "AG_Biomass_C", + "enabled": true, + "variable_data_type": "float", + "on_notification": "OutputStep" + }, + { + "pool_name": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "data_name": "Total_Ecosystem_C", + "enabled": true, + "variable_data_type": "float", + "on_notification": "OutputStep" + }, + { + "pool_name": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "data_name": "Total_Biomass_C", + "enabled": true, + "variable_data_type": "float", + "on_notification": "OutputStep" + }, + { + "pool_name": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "data_name": "Dead_Organic_Matter_C", + "enabled": true, + "variable_data_type": "float", + "on_notification": "OutputStep" + }, + { + "pool_name": [ + "BelowGroundVeryFastSoil", + "BelowGroundSlowSoil" + ], + "data_name": "Soil_C", + "enabled": true, + "variable_data_type": "float", + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "to": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "from": [ + "Atmosphere" + ] + }, + "data_name": "NPP", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": [ + { + "to": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "from": [ + "Atmosphere" + ] + }, + { + "subtract": true, + "from": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "to": [ + "CO2", + "CH4", + "CO" + ], + "flux_source": "annual_process" + } + ], + "data_name": "NEP", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": [ + { + "flux_source": "annual_process", + "from": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "to": [ + "CO2", + "CH4", + "CO" + ] + } + ], + "data_name": "Decomp_Releases", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": [ + { + "to": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "from": [ + "Atmosphere" + ] + }, + { + "subtract": true, + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "to": [ + "Products" + ], + "flux_source": "disturbance" + }, + { + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "subtract": true, + "to": [ + "CO2", + "CH4", + "CO" + ] + } + ], + "data_name": "NBP", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": [ + { + "to": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "from": [ + "Atmosphere" + ] + }, + { + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "subtract": true, + "to": [ + "CO2", + "CH4", + "CO" + ] + }, + { + "subtract": true, + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "to": [ + "Products" + ], + "flux_source": "disturbance" + } + ], + "data_name": "Delta_Total_Ecosystem", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": [ + { + "to": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "from": [ + "Atmosphere" + ] + }, + { + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "subtract": true, + "to": [ + "CO2", + "CH4", + "CO" + ] + }, + { + "subtract": true, + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "to": [ + "Products" + ], + "flux_source": "disturbance" + }, + { + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "subtract": true, + "to": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + } + ], + "data_name": "Delta_Total_Biomass", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": [ + { + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "to": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + { + "from": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "subtract": true, + "to": [ + "CO2", + "CH4", + "CO", + "Products" + ] + } + ], + "data_name": "Delta_Total_DOM", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "to": [ + "CO2", + "CH4", + "CO" + ], + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + "data_name": "Total_Emissions", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "to": [ + "CO2", + "CH4", + "CO" + ], + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ] + }, + "data_name": "Total_Biomass_Emissions", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "to": [ + "CO2", + "CH4", + "CO" + ], + "from": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + "data_name": "Total_DOM_Emissions", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "to": [ + "CO2" + ], + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + "data_name": "Total_CO2_Emissions", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "to": [ + "CO" + ], + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + "data_name": "Total_CO_Emissions", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "to": [ + "CH4" + ], + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + "data_name": "Total_CH4_Emissions", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": [ + { + "to": [ + "CO2", + "CH4", + "CO" + ], + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + { + "flux_source": "disturbance", + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ], + "to": [ + "Products" + ] + } + ], + "data_name": "Ecosystem_Removals", + "enabled": true, + "on_notification": "OutputStep" + }, + { + "variable_data_type": "float", + "flux": { + "flux_source": "disturbance", + "from": [ + "SoftwoodMerch", + "SoftwoodFoliage", + "SoftwoodOther", + "SoftwoodCoarseRoots", + "SoftwoodFineRoots", + "HardwoodMerch", + "HardwoodFoliage", + "HardwoodOther", + "HardwoodCoarseRoots", + "HardwoodFineRoots" + ], + "to": [ + "AboveGroundVeryFastSoil", + "BelowGroundVeryFastSoil", + "AboveGroundFastSoil", + "BelowGroundFastSoil", + "MediumSoil", + "AboveGroundSlowSoil", + "BelowGroundSlowSoil", + "SoftwoodStemSnag", + "SoftwoodBranchSnag", + "HardwoodStemSnag", + "HardwoodBranchSnag" + ] + }, + "data_name": "Bio_To_DOM_From_Disturbances", + "enabled": true, + "on_notification": "OutputStep" + } + ], + "output_path": "..\\output" + } + }, + "CBMAggregatorLandUnitData": { + "enabled": true, + "order": 12, + "library": "moja.modules.cbm", + "settings": { + "reporting_classifier_set": "reporting_classifiers" + } + }, + "CBMAggregatorSQLiteWriter": { + "enabled": true, + "order": 13, + "library": "moja.modules.cbm", + "settings": { + "databasename": "..\\output\\gcbm_output.db" + } + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/pools_cbm.json b/local/rest_api_gcbm/tests/reference/pools_cbm.json new file mode 100644 index 00000000..35979d38 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/pools_cbm.json @@ -0,0 +1,34 @@ +{ + "Pools": { + "AboveGroundFastSoil": 0.0, + "AboveGroundSlowSoil": 0.0, + "AboveGroundVeryFastSoil": 0.0, + "Atmosphere": 0.0, + "BelowGroundFastSoil": 0.0, + "BelowGroundSlowSoil": 0.0, + "BelowGroundVeryFastSoil": 0.0, + "BlackCarbon": 0.0, + "CH4": 0.0, + "CO": 0.0, + "CO2": 0.0, + "DissolvedOrganicCarbon": 0.0, + "HardwoodBranchSnag": 0.0, + "HardwoodCoarseRoots": 0.0, + "HardwoodFineRoots": 0.0, + "HardwoodFoliage": 0.0, + "HardwoodMerch": 0.0, + "HardwoodOther": 0.0, + "HardwoodStemSnag": 0.0, + "MediumSoil": 0.0, + "NO2": 0.0, + "Peat": 0.0, + "Products": 0.0, + "SoftwoodBranchSnag": 0.0, + "SoftwoodCoarseRoots": 0.0, + "SoftwoodFineRoots": 0.0, + "SoftwoodFoliage": 0.0, + "SoftwoodMerch": 0.0, + "SoftwoodOther": 0.0, + "SoftwoodStemSnag": 0.0 + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/provider_config.json b/local/rest_api_gcbm/tests/reference/provider_config.json new file mode 100644 index 00000000..f4c7ff50 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/provider_config.json @@ -0,0 +1,75 @@ +{ + "Providers": { + "SQLite": { + "path": "gcbm_input.db", + "type": "SQLite" + }, + "RasterTiled": { + "layers": [ + { + "name": "disturbances_2012", + "layer_path": "disturbances_2012.tiff", + "layer_prefix": "disturbances_2012" + }, + { + "name": "disturbances_2011", + "layer_path": "disturbances_2011.tiff", + "layer_prefix": "disturbances_2011" + }, + { + "name": "disturbances_2015", + "layer_path": "disturbances_2015.tiff", + "layer_prefix": "disturbances_2015" + }, + { + "name": "disturbances_2014", + "layer_path": "disturbances_2014.tiff", + "layer_prefix": "disturbances_2014" + }, + { + "name": "disturbances_2018", + "layer_path": "disturbances_2018.tiff", + "layer_prefix": "disturbances_2018" + }, + { + "name": "disturbances_2016", + "layer_path": "disturbances_2016.tiff", + "layer_prefix": "disturbances_2016" + }, + { + "name": "Classifier2", + "layer_path": "Classifier2.tiff", + "layer_prefix": "Classifier2" + }, + { + "name": "initial_age", + "layer_path": "initial_age.tiff", + "layer_prefix": "initial_age" + }, + { + "name": "mean_annual_temperature", + "layer_path": "mean_annual_temperature.tiff", + "layer_prefix": "mean_annual_temperature" + }, + { + "name": "Classifier1", + "layer_path": "Classifier1.tiff", + "layer_prefix": "Classifier1" + }, + { + "name": "disturbances_2013", + "layer_path": "disturbances_2013.tiff", + "layer_prefix": "disturbances_2013" + } + ], + "blockLonSize": 0.1, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "cellLatSize": 0.00025, + "cellLonSize": 0.00025, + "blockLatSize": 0.1, + "type": "RasterTiledGDAL", + "library": "moja.modules.gdal" + } + } +} diff --git a/local/rest_api_gcbm/tests/reference/spinup.json b/local/rest_api_gcbm/tests/reference/spinup.json new file mode 100644 index 00000000..1365b141 --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/spinup.json @@ -0,0 +1,56 @@ +{ + "Spinup": { + "enabled": true, + "sequencer_library": "moja.modules.cbm", + "simulateLandUnit": "simulateLandUnit", + "landUnitBuildSuccess": "landUnitBuildSuccess", + "sequencer": "CBMSpinupSequencer" + }, + "SpinupVariables": { + "delay": 0, + "minimum_rotation": 10, + "run_delay": false + }, + "Variables": { + "spinup_parameters": { + "transform": { + "queryString": "SELECT s.return_interval AS return_interval, s.max_rotations AS max_rotations, dt.name AS historic_disturbance_type, dt.name AS last_pass_disturbance_type, s.mean_annual_temperature AS mean_annual_temperature, 0 as delay FROM spinup_parameter s INNER JOIN disturbance_type dt ON s.historic_disturbance_type_id = dt.id INNER JOIN spatial_unit spu ON spu.spinup_parameter_id = s.id INNER JOIN admin_boundary a ON spu.admin_boundary_id = a.id INNER JOIN eco_boundary e ON spu.eco_boundary_id = e.id WHERE a.name = {var:admin_boundary} AND e.name = {var:eco_boundary}", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + } + }, + "SpinupModules": { + "CBMSpinupSequencer": { + "create_new": true, + "library": "moja.modules.cbm", + "order": 1 + }, + "CBMBuildLandUnitModule": { + "create_new": true, + "library": "moja.modules.cbm", + "order": 2 + }, + "CBMGrowthModule": { + "create_new": true, + "library": "moja.modules.cbm", + "order": 3 + }, + "CBMDecayModule": { + "create_new": true, + "library": "moja.modules.cbm", + "order": 4 + }, + "TransactionManagerAfterSubmitModule": { + "create_new": true, + "library": "internal.flint", + "order": 5 + }, + "CBMSpinupDisturbanceModule": { + "create_new": true, + "library": "moja.modules.cbm", + "order": 6 + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/reference/variables.json b/local/rest_api_gcbm/tests/reference/variables.json new file mode 100644 index 00000000..f2d8bc2f --- /dev/null +++ b/local/rest_api_gcbm/tests/reference/variables.json @@ -0,0 +1,257 @@ +{ + "Variables": { + "enable_peatland": false, + "enable_moss": false, + "admin_boundary": "British Columbia", + "eco_boundary": "Taiga Plains", + "initial_age": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "initial_age" + } + }, + "initial_historic_land_class": "FL", + "initial_current_land_class": "FL", + "age_class_range": 20, + "age_maximum": 300, + "slow_ag_to_bg_mixing_rate": 0.006, + "disturbance_matrices": { + "transform": { + "queryString": "SELECT dm.id AS disturbance_matrix_id, source_pool.name as source_pool_name, dest_pool.name as dest_pool_name, dv.proportion FROM disturbance_matrix dm INNER JOIN disturbance_matrix_value dv ON dm.id = dv.disturbance_matrix_id INNER JOIN pool source_pool ON dv.source_pool_id = source_pool.id INNER JOIN pool dest_pool ON dv.sink_pool_id = dest_pool.id", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "softwood_yield_table": { + "transform": { + "queryString": "SELECT gcv.age AS age, SUM(gcv.merchantable_volume) AS merchantable_volume FROM (SELECT CASE WHEN gc.id IS NOT NULL THEN gc.id ELSE -1 END AS growth_curve_component_id FROM growth_curve_component gc INNER JOIN species s ON s.id = gc.species_id INNER JOIN forest_type ft ON ft.id = s.forest_type_id WHERE gc.growth_curve_id = {var:growth_curve_id} AND LOWER(ft.name) LIKE LOWER('Softwood')) AS gc INNER JOIN growth_curve_component_value gcv ON gc.growth_curve_component_id = gcv.growth_curve_component_id GROUP BY gcv.age", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "reporting_classifiers": { + "transform": { + "allow_nulls": true, + "type": "CompositeTransform", + "library": "internal.flint", + "vars": [ + "classifier_set" + ] + } + }, + "land_class_transitions": { + "transform": { + "queryString": "SELECT dt.name AS disturbance_type, lc.code AS land_class_transition, lc.is_forest, lc.years_to_permanent FROM disturbance_type dt INNER JOIN land_class lc ON dt.transition_land_class_id = lc.id", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "transition_rules": { + "transform": { + "queryString": "SELECT t.id AS id, age, regen_delay, description, tt.name AS reset_type FROM transition t INNER JOIN transition_type tt ON t.transition_type_id = tt.id", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "transition_rule_matches": { + "transform": { + "classifier_set_var": "classifier_set", + "type": "TransitionRuleTransform", + "library": "moja.modules.cbm", + "provider": "SQLite" + } + }, + "spatial_unit_id": { + "transform": { + "queryString": "SELECT spu.id FROM spatial_unit spu INNER JOIN admin_boundary a ON spu.admin_boundary_id = a.id INNER JOIN eco_boundary e ON spu.eco_boundary_id = e.id WHERE a.name = {var:admin_boundary} AND e.name = {var:eco_boundary}", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "hardwood_yield_table": { + "transform": { + "queryString": "SELECT gcv.age AS age, SUM(gcv.merchantable_volume) AS merchantable_volume FROM (SELECT CASE WHEN gc.id IS NOT NULL THEN gc.id ELSE -1 END AS growth_curve_component_id FROM growth_curve_component gc INNER JOIN species s ON s.id = gc.species_id INNER JOIN forest_type ft ON ft.id = s.forest_type_id WHERE gc.growth_curve_id = {var:growth_curve_id} AND LOWER(ft.name) LIKE LOWER('Hardwood')) AS gc INNER JOIN growth_curve_component_value gcv ON gc.growth_curve_component_id = gcv.growth_curve_component_id GROUP BY gcv.age", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "turnover_rates": { + "transform": { + "queryString": "SELECT COALESCE(sw_turnover.foliage, 0) AS sw_foliage_turnover, COALESCE(hw_turnover.foliage, 0) AS hw_foliage_turnover, COALESCE(sw_turnover.stem, 0) AS sw_stem_turnover, COALESCE(hw_turnover.stem, 0) AS hw_stem_turnover, COALESCE(sw_turnover.branch, 0) AS sw_branch_turnover, COALESCE(hw_turnover.branch, 0) AS hw_branch_turnover, COALESCE(sw_turnover.branch_snag_split, 0) AS sw_other_to_branch_snag_split, COALESCE(hw_turnover.branch_snag_split, 0) AS hw_other_to_branch_snag_split, COALESCE(sw_turnover.stem_snag, 0) AS sw_stem_snag_turnover, COALESCE(hw_turnover.stem_snag, 0) AS hw_stem_snag_turnover, COALESCE(sw_turnover.branch_snag, 0) AS sw_branch_snag_turnover, COALESCE(hw_turnover.branch_snag, 0) AS hw_branch_snag_turnover, COALESCE(sw_turnover.coarse_ag_split, 0) AS sw_coarse_root_split, COALESCE(hw_turnover.coarse_ag_split, 0) AS hw_coarse_root_split, COALESCE(sw_turnover.coarse_root, 0) AS sw_coarse_root_turnover, COALESCE(hw_turnover.coarse_root, 0) AS hw_coarse_root_turnover, COALESCE(sw_turnover.fine_ag_split, 0) AS sw_fine_root_ag_split, COALESCE(hw_turnover.fine_ag_split, 0) AS hw_fine_root_ag_split, COALESCE(sw_turnover.fine_root, 0) AS sw_fine_root_turnover, COALESCE(hw_turnover.fine_root, 0) AS hw_fine_root_turnover FROM growth_curve gc LEFT JOIN ( SELECT growth_curve_id, foliage, stem, branch, branch_snag_split, stem_snag, branch_snag, coarse_ag_split, coarse_root, fine_ag_split, fine_root FROM turnover_parameter_association tpa INNER JOIN eco_boundary e ON tpa.eco_boundary_id = e.id INNER JOIN genus g ON tpa.genus_id = g.id INNER JOIN species s ON s.genus_id = g.id INNER JOIN forest_type f ON s.forest_type_id = f.id INNER JOIN growth_curve_component gcc ON gcc.species_id = s.id INNER JOIN turnover_parameter t ON tpa.turnover_parameter_id = t.id WHERE gcc.growth_curve_id = {var:growth_curve_id} AND e.name = {var:eco_boundary} AND f.name = 'Softwood' ORDER BY gcc.id LIMIT 1 ) AS sw_turnover ON gc.id = sw_turnover.growth_curve_id LEFT JOIN ( SELECT growth_curve_id, foliage, stem, branch, branch_snag_split, stem_snag, branch_snag, coarse_ag_split, coarse_root, fine_ag_split, fine_root FROM turnover_parameter_association tpa INNER JOIN eco_boundary e ON tpa.eco_boundary_id = e.id INNER JOIN genus g ON tpa.genus_id = g.id INNER JOIN species s ON s.genus_id = g.id INNER JOIN forest_type f ON s.forest_type_id = f.id INNER JOIN growth_curve_component gcc ON gcc.species_id = s.id INNER JOIN turnover_parameter t ON tpa.turnover_parameter_id = t.id WHERE gcc.growth_curve_id = {var:growth_curve_id} AND e.name = {var:eco_boundary} AND f.name = 'Hardwood' ORDER BY gcc.id LIMIT 1 ) AS hw_turnover ON gc.id = hw_turnover.growth_curve_id WHERE gc.id = {var:growth_curve_id}", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "disturbance_type_codes": { + "transform": { + "queryString": "SELECT dt.name AS disturbance_type, dt.code AS disturbance_type_code FROM disturbance_type dt", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "transition_rule_classifiers": { + "transform": { + "queryString": "SELECT t.id, c.name AS classifier_name, cv.value AS classifier_value FROM transition t INNER JOIN transition_classifier_value tcv ON t.id = tcv.transition_id INNER JOIN classifier_value cv ON tcv.classifier_value_id = cv.id INNER JOIN classifier c ON cv.classifier_id = c.id", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "initial_classifier_set": { + "transform": { + "type": "CompositeTransform", + "library": "internal.flint", + "vars": [ + "Classifier2", + "Classifier1" + ] + } + }, + "disturbance_matrix_associations": { + "transform": { + "queryString": "SELECT dt.name AS disturbance_type, dma.spatial_unit_id, dma.disturbance_matrix_id FROM disturbance_matrix_association dma INNER JOIN disturbance_type dt ON dma.disturbance_type_id = dt.id", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "other_to_branch_snag_split": { + "transform": { + "queryString": "SELECT t.branch_snag_split AS slow_mixing_rate FROM eco_boundary e INNER JOIN turnover_parameter t ON e.turnover_parameter_id = t.id WHERE e.name LIKE {var:eco_boundary}", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "growth_curve_id": { + "transform": { + "classifier_set_var": "classifier_set", + "type": "GrowthCurveTransform", + "library": "moja.modules.cbm", + "provider": "SQLite" + } + }, + "volume_to_biomass_parameters": { + "transform": { + "queryString": "SELECT ft.name AS forest_type, f.a as a, f.b as b, f.a_nonmerch as a_non_merch, f.b_nonmerch as b_non_merch, f.k_nonmerch as k_non_merch, f.cap_nonmerch as cap_non_merch, f.a_sap as a_sap, f.b_sap as b_sap, f.k_sap as k_sap, f.cap_sap as cap_sap, f.a1 as a1, f.a2 as a2, f.a3 as a3, f.b1 as b1, f.b2 as b2, f.b3 as b3, f.c1 as c1, f.c2 as c2, f.c3 as c3, f.min_volume as min_volume, f.max_volume as max_volume, f.low_stemwood_prop as low_stemwood_prop, f.high_stemwood_prop as high_stemwood_prop, f.low_stembark_prop as low_stembark_prop, f.high_stembark_prop as high_stembark_prop, f.low_branches_prop AS low_branches_prop, f.high_branches_prop as high_branches_prop, f.low_foliage_prop AS low_foliage_prop, f.high_foliage_prop AS high_foliage_prop, sp.sw_top_proportion AS softwood_top_prop, sp.sw_stump_proportion AS softwood_stump_prop, sp.hw_top_proportion AS hardwood_top_prop, sp.hw_stump_proportion AS hardwood_stump_prop, rp.hw_a AS hw_a, rp.hw_b AS hw_b, rp.sw_a AS sw_a, rp.frp_a AS frp_a, rp.frp_b AS frp_b, rp.frp_c AS frp_c FROM vol_to_bio_factor_association fa INNER JOIN vol_to_bio_factor f ON f.id = fa.vol_to_bio_factor_id INNER JOIN species s ON fa.species_id = s.id INNER JOIN growth_curve_component gcc ON s.id = gcc.species_id INNER JOIN forest_type ft ON s.forest_type_id = ft.id INNER JOIN spatial_unit spu ON fa.spatial_unit_id = spu.id INNER JOIN admin_boundary a ON spu.admin_boundary_id = a.id INNER JOIN stump_parameter sp ON a.stump_parameter_id = sp.id INNER JOIN root_parameter rp ON rp.id = fa.root_parameter_id WHERE gcc.growth_curve_id = {var:growth_curve_id} AND spu.id = {var:spatial_unit_id} ORDER BY gcc.id DESC", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "spu": { + "transform": { + "queryString": "select s.id AS spu_id from spatial_unit s inner join admin_boundary a on s.admin_boundary_id = a.id inner join eco_boundary e on s.eco_boundary_id = e.id where a.name like {var:admin_boundary} and e.name like {var:eco_boundary}", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "land_class_data": { + "transform": { + "queryString": "SELECT code AS land_class, is_forest, years_to_permanent FROM land_class lc", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "mean_annual_temperature": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "mean_annual_temperature" + } + }, + "decay_parameters": { + "transform": { + "queryString": "SELECT p.name AS pool, dp.base_decay_rate AS organic_matter_decay_rate, dp.prop_to_atmosphere AS prop_to_atmosphere, dp.q10 AS q10, dp.reference_temp AS reference_temp, dp.max_rate AS max_decay_rate_soft FROM decay_parameter dp INNER JOIN dom_pool dom ON dp.dom_pool_id = dom.id INNER JOIN pool p ON p.id = dom.pool_id", + "type": "SQLQueryTransform", + "library": "internal.flint", + "provider": "SQLite" + } + }, + "disturbances_2012": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "disturbances_2012" + } + }, + "disturbances_2011": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "disturbances_2011" + } + }, + "disturbances_2015": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "disturbances_2015" + } + }, + "disturbances_2014": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "disturbances_2014" + } + }, + "disturbances_2018": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "disturbances_2018" + } + }, + "disturbances_2016": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "disturbances_2016" + } + }, + "Classifier2": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "Classifier2" + } + }, + "Classifier1": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "Classifier1" + } + }, + "disturbances_2013": { + "transform": { + "library": "internal.flint", + "type": "LocationIdxFromFlintDataTransform", + "provider": "RasterTiled", + "data_id": "disturbances_2013" + } + } + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/test_data/belize/LifeZone.tiff b/local/rest_api_gcbm/tests/test_data/belize/LifeZone.tiff new file mode 100644 index 00000000..baf39832 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/belize/LifeZone.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/belize/LifeZone_moja.json b/local/rest_api_gcbm/tests/test_data/belize/LifeZone_moja.json new file mode 100644 index 00000000..5f6fb4cd --- /dev/null +++ b/local/rest_api_gcbm/tests/test_data/belize/LifeZone_moja.json @@ -0,0 +1,16 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.01, + "cellLonSize": 0.01, + "attributes": { + "1": "Tropical Dry", + "2": "Tropical Moist", + "3": "Tropical Premontane Wet, Transition to Basal - Atlantic" + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/test_data/belize/LifeZone_moja.tiff.aux.xml b/local/rest_api_gcbm/tests/test_data/belize/LifeZone_moja.tiff.aux.xml new file mode 100644 index 00000000..5c307a4b --- /dev/null +++ b/local/rest_api_gcbm/tests/test_data/belize/LifeZone_moja.tiff.aux.xml @@ -0,0 +1,14 @@ + + + + + -0.5 + 255.5 + 256 + 1 + 0 + 0|9681|5123|3516|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0 + + + + diff --git a/local/rest_api_gcbm/tests/test_data/belize/bounding_box.tiff b/local/rest_api_gcbm/tests/test_data/belize/bounding_box.tiff new file mode 100644 index 00000000..59dc21e7 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/belize/bounding_box.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature.tiff b/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature.tiff new file mode 100644 index 00000000..aa3bedbc Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature_moja.json b/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature_moja.json new file mode 100644 index 00000000..fdac3fad --- /dev/null +++ b/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature_moja.json @@ -0,0 +1,11 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Float32", + "nodata": 3.3999999521443642e+38, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.01, + "cellLonSize": 0.01 +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature_moja.tiff.aux.xml b/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature_moja.tiff.aux.xml new file mode 100644 index 00000000..0d74fffe --- /dev/null +++ b/local/rest_api_gcbm/tests/test_data/belize/mean_annual_temperature_moja.tiff.aux.xml @@ -0,0 +1,14 @@ + + + + + -0.5 + 255.5 + 256 + 1 + 0 + 0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|76|720|1881|1618|5088|8835|102|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0 + + + + diff --git a/local/rest_api_gcbm/tests/test_data/belize/study_area.json b/local/rest_api_gcbm/tests/test_data/belize/study_area.json new file mode 100644 index 00000000..549aed71 --- /dev/null +++ b/local/rest_api_gcbm/tests/test_data/belize/study_area.json @@ -0,0 +1,60 @@ +{ + "tile_size": 1.0, + "block_size": 0.1, + "tiles": [ + { + "x": -90, + "y": 16, + "index": 26730 + }, + { + "x": -90, + "y": 17, + "index": 26370 + }, + { + "x": -90, + "y": 18, + "index": 26010 + }, + { + "x": -90, + "y": 19, + "index": 25650 + }, + { + "x": -89, + "y": 16, + "index": 26731 + }, + { + "x": -89, + "y": 17, + "index": 26371 + }, + { + "x": -89, + "y": 18, + "index": 26011 + }, + { + "x": -89, + "y": 19, + "index": 25651 + } + ], + "pixel_size": 0.01, + "layers": [ + { + "name": "mean_annual_temperature", + "type": "RasterLayer" + }, + { + "name": "LifeZone", + "type": "VectorLayer", + "tags": [ + "classifier" + ] + } + ] +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/Classifier1.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/Classifier1.tiff new file mode 100644 index 00000000..95260931 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/Classifier1.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/Classifier2.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/Classifier2.tiff new file mode 100644 index 00000000..9060185d Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/Classifier2.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2011.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2011.tiff new file mode 100644 index 00000000..f5541f14 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2011.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2012.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2012.tiff new file mode 100644 index 00000000..8a6beaa1 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2012.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2013.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2013.tiff new file mode 100644 index 00000000..eb2f3ad6 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2013.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2014.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2014.tiff new file mode 100644 index 00000000..20eb4b16 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2014.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2015.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2015.tiff new file mode 100644 index 00000000..3fea1509 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2015.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2016.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2016.tiff new file mode 100644 index 00000000..91c22426 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2016.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2018.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2018.tiff new file mode 100644 index 00000000..39ab4719 Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/disturbances_2018.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/gcbm_input.db b/local/rest_api_gcbm/tests/test_data/new_demo_run/gcbm_input.db new file mode 100644 index 00000000..9fd320de Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/gcbm_input.db differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/initial_age.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/initial_age.tiff new file mode 100644 index 00000000..e97800cb Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/initial_age.tiff differ diff --git a/local/rest_api_gcbm/tests/test_data/new_demo_run/mean_annual_temperature.tiff b/local/rest_api_gcbm/tests/test_data/new_demo_run/mean_annual_temperature.tiff new file mode 100644 index 00000000..6f85a9dd Binary files /dev/null and b/local/rest_api_gcbm/tests/test_data/new_demo_run/mean_annual_temperature.tiff differ diff --git a/local/rest_api_gcbm/tests/tests_simulations.py b/local/rest_api_gcbm/tests/tests_simulations.py new file mode 100644 index 00000000..cfd8f1d2 --- /dev/null +++ b/local/rest_api_gcbm/tests/tests_simulations.py @@ -0,0 +1,99 @@ +# This file tests the following GCBM simulations: +# 1. GCBM Belize with disturbance +# 2. GCBM Belize without disturbance +# 3. GCBM New Demo Run + +import sys +sys.path.append("../") + +import pytest + +from gcbm import GCBMSimulation + + +belize_dict = { + "classifier": ["test_data/belize/LifeZone.tiff"], + "miscellaneous": ["test_data/belize/mean_annual_temperature.tiff"], +} + +new_demo_run_dict = { + "disturbance": ["test_data/new_demo_run/disturbances_2011.tiff", "test_data/new_demo_run/disturbances_2012.tiff"], + "classifier": ["test_data/new_demo_run/Classifier1.tiff"], + "miscellaneous": ["test_data/new_demo_run/mean_annual_temperature.tiff"], +} + +def filter_input_dict(input_dict, if_disturbance): + filtered_dict = input_dict + if not if_disturbance: + # Ignore disturbances from the dictionary + filtered_dict = {k: v for k, v in input_dict.items() if k != "disturbance"} + + # Do sanity check on input dict + def _sanity_check(dict): + assert "classifier" in list(dict.keys()) and "miscellaneous" in list(dict.keys()), f"classifier and miscellaneous keys expected in the dict but got {dict.keys()} for simulation {simulation_name}" + + _sanity_check(filtered_dict) + return filtered_dict + + +@pytest.mark.parametrize( + "simulation_name, input_dict, if_disturbance", + [ + ("belize", belize_dict, True), + ("belize", belize_dict, False), + ("new_demo_run", new_demo_run_dict, True), + ("new_demo_run", new_demo_run_dict, False), + ], +) +def test_simulation_add(simulation_name, input_dict, if_disturbance): + import os + + filtered_dict = filter_input_dict(input_dict, if_disturbance) + # Test that JSON files are generated for the configs of the simulation + gcbm = GCBMSimulation() + for key, val in filtered_dict.items(): + for path in val: + gcbm.add_file(category=key, file_path=path) + expected_path = "input/test-run/" + path.split("/")[-1] + assert os.path.isfile(expected_path), f"Failed for {simulation_name}, expected {expected_path} to exist." + + +@pytest.mark.parametrize( + "simulation_name, input_dict, if_disturbance", + [ + ("belize", belize_dict, True), + ("belize", belize_dict, False), + ("new_demo_run", new_demo_run_dict, True), + ("new_demo_run", new_demo_run_dict, False), + ], +) +def test_simulation_set_attr(simulation_name, input_dict, if_disturbance): + # Do sanity check on input dict + def sanity_check(dict): + assert "classifier" in list(dict.keys()) and "miscellaneous" in list(dict.keys()), f"classifier and miscellaneous keys expected in the dict but got {dict.keys()} for simulation {simulation_name}" + + # Assert if the json contains the expected data (payload) + def check_data_in_json(json_path, expected_data): + import json + with open(json_path, "r") as json_file: + json_obj = json.load(json_file) + for key, val in expected_data.items(): + assert json_obj["attributes"][key] == val + + print(f"Starting test for simulation {simulation_name}") + filtered_dict = input_dict + if not if_disturbance: + # Ignore disturbances from the dictionary + filtered_dict = {k: v for k, v in input_dict.items() if k != "disturbance"} + + sanity_check(filtered_dict) + + # Test that JSON files are generated for the configs of the simulation + import os + sim = GCBMSimulation() + for key, val in filtered_dict.items(): + for path in val: + sim.add_file(category=key, file_path=path) + payload = {"year": 2011, "disturbance_type": "Wildfire", "transition": 1} + sim.set_attributes(category=key, file_path=path, payload=payload) + check_data_in_json(json_path=sim.json_paths[os.path.basename(path)], expected_data=payload) diff --git a/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.json b/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.json new file mode 100644 index 00000000..5f6fb4cd --- /dev/null +++ b/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.json @@ -0,0 +1,16 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Byte", + "nodata": 255, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.01, + "cellLonSize": 0.01, + "attributes": { + "1": "Tropical Dry", + "2": "Tropical Moist", + "3": "Tropical Premontane Wet, Transition to Basal - Atlantic" + } +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.tiff b/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.tiff new file mode 100644 index 00000000..baf39832 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.tiff.aux.xml b/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.tiff.aux.xml new file mode 100644 index 00000000..5c307a4b --- /dev/null +++ b/local/rest_api_gcbm/tests/tiff/belize/LifeZone_moja.tiff.aux.xml @@ -0,0 +1,14 @@ + + + + + -0.5 + 255.5 + 256 + 1 + 0 + 0|9681|5123|3516|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0 + + + + diff --git a/local/rest_api_gcbm/tests/tiff/belize/bounding_box.tiff b/local/rest_api_gcbm/tests/tiff/belize/bounding_box.tiff new file mode 100644 index 00000000..59dc21e7 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/belize/bounding_box.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.json b/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.json new file mode 100644 index 00000000..fdac3fad --- /dev/null +++ b/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.json @@ -0,0 +1,11 @@ +{ + "layer_type": "GridLayer", + "layer_data": "Float32", + "nodata": 3.3999999521443642e+38, + "tileLatSize": 1.0, + "tileLonSize": 1.0, + "blockLatSize": 0.1, + "blockLonSize": 0.1, + "cellLatSize": 0.01, + "cellLonSize": 0.01 +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.tiff b/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.tiff new file mode 100644 index 00000000..aa3bedbc Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.tiff.aux.xml b/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.tiff.aux.xml new file mode 100644 index 00000000..0d74fffe --- /dev/null +++ b/local/rest_api_gcbm/tests/tiff/belize/mean_annual_temperature_moja.tiff.aux.xml @@ -0,0 +1,14 @@ + + + + + -0.5 + 255.5 + 256 + 1 + 0 + 0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|76|720|1881|1618|5088|8835|102|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0 + + + + diff --git a/local/rest_api_gcbm/tests/tiff/belize/study_area.json b/local/rest_api_gcbm/tests/tiff/belize/study_area.json new file mode 100644 index 00000000..549aed71 --- /dev/null +++ b/local/rest_api_gcbm/tests/tiff/belize/study_area.json @@ -0,0 +1,60 @@ +{ + "tile_size": 1.0, + "block_size": 0.1, + "tiles": [ + { + "x": -90, + "y": 16, + "index": 26730 + }, + { + "x": -90, + "y": 17, + "index": 26370 + }, + { + "x": -90, + "y": 18, + "index": 26010 + }, + { + "x": -90, + "y": 19, + "index": 25650 + }, + { + "x": -89, + "y": 16, + "index": 26731 + }, + { + "x": -89, + "y": 17, + "index": 26371 + }, + { + "x": -89, + "y": 18, + "index": 26011 + }, + { + "x": -89, + "y": 19, + "index": 25651 + } + ], + "pixel_size": 0.01, + "layers": [ + { + "name": "mean_annual_temperature", + "type": "RasterLayer" + }, + { + "name": "LifeZone", + "type": "VectorLayer", + "tags": [ + "classifier" + ] + } + ] +} \ No newline at end of file diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/Classifier1_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/Classifier1_moja.tiff new file mode 100644 index 00000000..95260931 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/Classifier1_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/Classifier2_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/Classifier2_moja.tiff new file mode 100644 index 00000000..9060185d Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/Classifier2_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2011_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2011_moja.tiff new file mode 100644 index 00000000..f5541f14 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2011_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2012_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2012_moja.tiff new file mode 100644 index 00000000..8a6beaa1 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2012_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2013_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2013_moja.tiff new file mode 100644 index 00000000..eb2f3ad6 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2013_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2014_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2014_moja.tiff new file mode 100644 index 00000000..20eb4b16 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2014_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2015_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2015_moja.tiff new file mode 100644 index 00000000..3fea1509 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2015_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2016_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2016_moja.tiff new file mode 100644 index 00000000..91c22426 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2016_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2018_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2018_moja.tiff new file mode 100644 index 00000000..39ab4719 Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/disturbances_2018_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/initial_age_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/initial_age_moja.tiff new file mode 100644 index 00000000..e97800cb Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/initial_age_moja.tiff differ diff --git a/local/rest_api_gcbm/tests/tiff/new_demo_run/mean_annual_temperature_moja.tiff b/local/rest_api_gcbm/tests/tiff/new_demo_run/mean_annual_temperature_moja.tiff new file mode 100644 index 00000000..6f85a9dd Binary files /dev/null and b/local/rest_api_gcbm/tests/tiff/new_demo_run/mean_annual_temperature_moja.tiff differ