!python3 -m pip install git+https://github.com/aireo-project/aireo_lib
Collecting git+https://github.com/aireo-project/aireo_lib Cloning https://github.com/aireo-project/aireo_lib to /tmp/pip-req-build-i8z3y846 Running command git clone -q https://github.com/aireo-project/aireo_lib /tmp/pip-req-build-i8z3y846 Installing build dependencies ... done Getting requirements to build wheel ... done Preparing wheel metadata ... done Requirement already satisfied: pyaml in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from aireo-library==0.0.post1.dev3+g946df44) (20.4.0) Requirement already satisfied: loguru in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from aireo-library==0.0.post1.dev3+g946df44) (0.5.3) Requirement already satisfied: xarray in /home/jovyan/.local/lib/python3.8/site-packages (from aireo-library==0.0.post1.dev3+g946df44) (0.18.2) Requirement already satisfied: numpy in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from aireo-library==0.0.post1.dev3+g946df44) (1.19.5) Requirement already satisfied: matplotlib in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from aireo-library==0.0.post1.dev3+g946df44) (3.4.2) Requirement already satisfied: stac-pydantic in /home/jovyan/.local/lib/python3.8/site-packages (from aireo-library==0.0.post1.dev3+g946df44) (1.3.9) Requirement already satisfied: pyparsing>=2.2.1 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from matplotlib->aireo-library==0.0.post1.dev3+g946df44) (2.4.7) Requirement already satisfied: python-dateutil>=2.7 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from matplotlib->aireo-library==0.0.post1.dev3+g946df44) (2.8.1) Requirement already satisfied: pillow>=6.2.0 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from matplotlib->aireo-library==0.0.post1.dev3+g946df44) (8.1.2) Requirement already satisfied: cycler>=0.10 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from matplotlib->aireo-library==0.0.post1.dev3+g946df44) (0.10.0) Requirement already satisfied: kiwisolver>=1.0.1 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from matplotlib->aireo-library==0.0.post1.dev3+g946df44) (1.3.1) Requirement already satisfied: six in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from cycler>=0.10->matplotlib->aireo-library==0.0.post1.dev3+g946df44) (1.15.0) Requirement already satisfied: PyYAML in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from pyaml->aireo-library==0.0.post1.dev3+g946df44) (5.4.1) Requirement already satisfied: pydantic>=1.6 in /home/jovyan/.local/lib/python3.8/site-packages (from stac-pydantic->aireo-library==0.0.post1.dev3+g946df44) (1.8.2) Requirement already satisfied: click in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from stac-pydantic->aireo-library==0.0.post1.dev3+g946df44) (7.1.2) Requirement already satisfied: geojson-pydantic in /home/jovyan/.local/lib/python3.8/site-packages (from stac-pydantic->aireo-library==0.0.post1.dev3+g946df44) (0.3.0) Requirement already satisfied: typing-extensions>=3.7.4.3 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from pydantic>=1.6->stac-pydantic->aireo-library==0.0.post1.dev3+g946df44) (3.7.4.3) Requirement already satisfied: setuptools>=40.4 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from xarray->aireo-library==0.0.post1.dev3+g946df44) (49.6.0.post20210108) Requirement already satisfied: pandas>=1.0 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from xarray->aireo-library==0.0.post1.dev3+g946df44) (1.2.4) Requirement already satisfied: pytz>=2017.3 in /opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages (from pandas>=1.0->xarray->aireo-library==0.0.post1.dev3+g946df44) (2021.1)
The notebook demonstrates the use of aireo_lib , a python library created as a part of the AIREO (Artificial Intelligence Ready Earth Observation training datasets) project. The project aims to make EO datasets easily accessible for the ML (Machine Learning) community. As such, AIREO specifications (shorthand specs) which define metadata elements to be included with the training dataset are proposed, supplemented by a best-practices document which suggests how to fill those metadata elements. Finally, the library takes all into account and implements specs, best-practices and offers an easy-to-use pythonic interface bridging the gap between EO and ML community.
Therefore, this notebook is divided into two sections, one for the training dataset creator (usually from the EO community) and the other for its user (usually from the ML community). The structure of the notebook is the following:
1) For Creator
- Create a [STAC](https://stacspec.org/) catalog object using the library
- Populate metadata elements prescribed by the AIREO specs
- Generate a STAC metadata directory using the library
- Check AIREO compliance level and metadata completeness
2) For User
- Create a training dataset object as defined in the library using only the STAC metadata
- Get example instances from the object and other dataset variables like the number of instances, etc.
- Use library's functions to plot the data
- Investigate statistics using the library
SpaceNet7 is a collection of satellite image time series covering 100 different locations in a diverse range of environments. It also includes a set of polygons for each image marking out the building footprints. The image data was collected by Planet satellites at an interval of roughly one month for each location for a period of two years. This is not compeltely consistent across different locations. The data was then manually annotated by a team at SpaceNet to produce the building footprint polygons. The full data from 60 areas was released as a public dataset.
We have simplified the dataset slightly for the purpose of creating a pilot AIREO dataset. We have converted all building polygons to boolean raster masks, and have stored these and the images in netcdf files as time series of raster data, one for each location. We have also standardized image resolution across all locations. This notebook only makes use of 5 AOIs out of 60 for demonstration purposes.
This dataset can be used to train ML models for the task of automatic building detection in satellite images, and for the tracking of building development over time.
The AIREO specs propose a hierarchical structure for STAC metadata. It is a two level structure where the dataset is represented by a collection of AOIs (Area Of Interests), hence, the dataset and AOI being the two levels.
At the dataset level we have a dataset catalog whose metadata elements are the core elements proposed in the AIREO spec. In addition to it, the common metadata elements across each AOI are also at the dataset level, which we shall call root level henceforth. Here, for each data variable there is a separate json which is a STAC Item by definition and is named using the field_schema metadata element. Additionally, there is also a datasheet file in markdown format at the root level which contains human readable information about the key elements of the dataset.
Each AOI has a separate folder within the root level. And in each AOI folder there is a STAC collection representing that AOI and additional json files for each data variable. The additional json files here too, are STAC Items and follow a similar naming convention to the ones at the root level. The assets for each AOI, i.e. the files containing actual data are also in the folder.
The diagram below summarises this hierarchical structure:
Root level (dataset)
│
│ DatasetCatalog.json
│ datasheet.md
│ references_output1.json
│ features_input1.json
│ ...
│
│
└───AOI 1
│ 1.json (AOI Collection)
│ feature_input1.json
│ reference_output1.json
│ <reference_asset>
│ <feature_asseet>
│
│
└───AOI 2
│ ...
│
│
└───AOI 3
│ ...
│
...
The aireo_lib library makes it easier to generate the STAC metadata directory as defined above. Some of the useful functionalities in the library are:
Define python dictionaries for metadata at the root level and use a simple function to add it to the STAC catalog. The library validates the data automatically when it is added.
Similarly, python dictionaries can be defined for each AOI and are also validated automatically.
Links and assets for all the json files are automatically generated.
Datasheet is also generated automatically.
The directory structure is created by the library and assets copied to their respective locations in the hierarchy.
Evaluating metadata completeness and compliance level.
Follow the code and comments below to understand the steps needed to generate STAC metadata with the library.
import aireo_lib.core
import os
import json
import numpy as np
from tqdm.notebook import tqdm
from shapely import geometry
import shutil
import xarray as xr
from pathlib import Path
from shapely import geometry
import geopandas as gpd
# Path to write the STAC root metadata file too
catalog_fn_w_path = os.environ['EDC_PATH']+'/data/SpaceNet7/sp7_stac/TDS.json'
# Creating an empty STAC Catalog object
new_tds_ctl_o = aireo_lib.core.tds_stac_io.DatasetSTACCatalog()
# AOI list int the TDS
dataset_path = os.environ['EDC_PATH']+'/data/SpaceNet7/Data/sp7_sample'
aoi_ids = [aoi_id for aoi_id in os.listdir(dataset_path) if aoi_id[0]!='.'][0:3]
# Creating root metadata dictionary
tds_root_core_metadata_d = {}
tds_root_core_metadata_d['aireo_version'] = "0.0.1-alpha.1"
tds_root_core_metadata_d['title'] = "Images with buildings labelled covering short range of time for each AOI"
tds_root_core_metadata_d['description'] = "Covers 60 areas of interest at 4m resolution with images at monthly intervals. Each image is annotated with polygons labelling buildings. Dataset allows for the monitioring and prediction of building development over time."
tds_root_core_metadata_d['created'] = '2020-07-13'
tds_root_core_metadata_d['license_url_list'] = 'https://creativecommons.org/licenses/by-sa/4.0/'
tds_root_core_metadata_d['license'] = "CC-BY-SA-4.0"
tds_root_core_metadata_d["providers_name"]= "[SpaceNet LLC]"
tds_root_core_metadata_d["providers_description"] = "Data gathered by Planet satellites, dataset then created by Spacenet "
tds_root_core_metadata_d["providers_roles"] = {"SpaceNet":["processor","host","licensor","producer"], 'AIREO':["producer", "processor" , "host"]}
tds_root_core_metadata_d["providers_url"]= {"Spacenet":"https://spacenet.ai/",
'AIREO': 'https://aireo.net/'}
tds_root_core_metadata_d['id'] = "706cf9e2-bd46-11eb-8529-0242ac130003"
tds_root_core_metadata_d['type'] = "Collection"
tds_root_core_metadata_d['stac_version'] = '1.0.0-beta.2'
tds_root_core_metadata_d['provenance'] = 'Data gathered from Planet satellites and annotatations produced by SpaceNet LLC'
tds_root_core_metadata_d['purpose'] = "Using semantic segmentation track buidling development over time. Segment individual images from each timestep then use this knowledge to track development over time for one AOI."
tds_root_core_metadata_d['tasks'] = ['Semantic Segmentation']
tds_root_core_metadata_d['data_preprocessing'] = 'Original dataset included images from one AOI as seperate tiff files. We have combined these into one netcdf datacube for each AOI. The building labels were stored as polygons in the original dataset. We have converted to raster masks and have stored them in netcdf datacubes, one for each AOI.'
tds_root_core_metadata_d['funding_info'] = "The AIREO project is funded by ESA. The underlying data was gathered by Planet, then annotated and released by SpaceNet for free use."
tds_root_core_metadata_d['field_schema'] = {'features': {'input1': ['georeferenced_eo_data','georeferenced_eo_datacube']}, 'references': {'output1': ['reference_data']}}
tds_root_core_metadata_d['example_definition'] = "An individual example consists of a single image, and a raster mask representing the buildings visible in the image."
tds_root_core_metadata_d['data_completeness'] = "Dataset is sufficent for task and requires no external sources."
tds_root_core_metadata_d['data_split'] = "Recommend train/test/validation split of 40 AOIs in train, 10 in test and 10 in validation. Should ensure the density of buildings in images is roughly equal for these splits ie. not training on sparsely populated areas then testing on densely populated areas."
tds_root_core_metadata_d['data_sharing'] = "The dataset will be shared on Euro Data Cube (EDC) and can be accessed through jupyter notebooks on EDC."
tds_root_core_metadata_d['compliance_level'] = 'level 1'
tds_root_core_metadata_d['example_window_size'] = 100
tds_root_core_metadata_d['example_stride'] = 80
tds_root_core_metadata_d['data_completeness'] = "The data spans a large geographic range. There are some unusable sections of the images due to cloud cover and instrument malfunction."
tds_root_core_metadata_d['data_split'] = "It is important when splitting data for testing, training and validation, that the density of buildings is similar in each split. For example if we train on sparsely developed areas then our model's performance will likely suffer when tested on highly developed areas."
tds_root_core_metadata_d['data_sharing'] = "The dataset will be shared on Euro Data Cube (EDC) and can be accessed through jupyter notebooks on EDC."
tds_root_core_metadata_d['compliance_level'] = 'level 1'
tds_root_core_metadata_d['links'] = []
# Make root level feature metadata
g_feature_metadata_d = {}
g_feature_metadata_d['type'] = "Feature"
g_feature_metadata_d['stac_version'] = "1.0.0-beta.2"
g_feature_metadata_d['stac_extensions'] = ["georeferenced_eo_data","georeferenced_eo_datacube"]
g_feature_metadata_d['id'] = "common_feature_metadata"
g_feature_metadata_d['collection'] = "706cf9e2-bd46-11eb-8529-0242ac130003"
g_feature_metadata_d["properties"] = {}
# add metadata from georeferencedeodata profile first
g_feature_metadata_d["properties"]['parent_identifier'] = "706cf9e2-bd46-11eb-8529-0242ac130003"
g_feature_metadata_d["properties"]['identifier'] = "Null"
g_feature_metadata_d["properties"]['composed_of'] = "Null"
g_feature_metadata_d["properties"]['linked_with'] = "Null"
g_feature_metadata_d['properties']['product_type'] = "Time series of monthly images for one AOI. Each image shares geometry and bounding box."
g_feature_metadata_d["properties"]["native_product_format"] = "netcdf"
g_feature_metadata_d["properties"]['processing_level'] = "Null"
g_feature_metadata_d["properties"]['auxiliary_dataset_filename'] = "Null"
g_feature_metadata_d['properties']['CRS'] = 'EPSG:3857'
# dimensions of the whole dataset
x_min = -13545862.01592866
y_min = -4510398.55370881
x_max = 16133718.82286585
y_max = 6887891.10417667
g_feature_metadata_d['bbox'] = [x_min,y_min,x_max,y_max]
g_feature_metadata_d['geometry'] = geometry.mapping(geometry.box(x_min,y_min,x_max,y_max,ccw=True))
# now add data for georeferencedeodatacube profile
g_feature_metadata_d["properties"]["dimensions"] = {}
g_feature_metadata_d["properties"]["dimensions"]["x"] = {
"type": "spatial",
"axis": "x",
"extent": [
x_min,
x_max
],
"reference_system": 3857
}
g_feature_metadata_d["properties"]["dimensions"]["y"] = {
"type": "spatial",
"axis": "y",
"extent": [
y_min,
y_max
],
"reference_system": 3857
}
g_feature_metadata_d["properties"]["dimensions"]["temporal"] = {
"type": "temporal",
"extent": [
"2017-07-01T00:00:00.000000000",
"2020-01-01T00:00:00.000000000"
]
}
g_feature_metadata_d["properties"]["dimensions"]["spectral"] = {
"type": "bands",
"values": [
"red",
"green",
"blue"
]
}
g_feature_metadata_d["properties"]['datetime'] = "2019"
g_feature_metadata_d['links'] = []
g_feature_metadata_d["assets"] = {}
# make feature metadata dictionary
feature_metadata_d = {}
feature_metadata_d['input1'] = g_feature_metadata_d
# create common reference data
g_ref_data_metadata_d = {}
g_ref_data_metadata_d['id'] = f'common_reference_metadata'
g_ref_data_metadata_d['type'] = "Feature"
g_ref_data_metadata_d['stac_version'] = "1.0.0-beta.2"
g_ref_data_metadata_d['stac_extensions'] = ["reference_data"]
g_ref_data_metadata_d['collection'] = "706cf9e2-bd46-11eb-8529-0242ac130003"
g_ref_data_metadata_d['properties'] = {}
g_ref_data_metadata_d['properties']['name'] = 'Reference Metadata'
g_ref_data_metadata_d['properties']['description'] = "The reference data consists of datacubes of raster masks representing the building outlines in the training images. One datacube corresponds to one AOI."
g_ref_data_metadata_d['properties']['type'] = "annotated"
g_ref_data_metadata_d['properties']['task'] = "Semantic Segmentation"
g_ref_data_metadata_d['properties']['classes'] = [[{'BUILDING':255,'NOT_BUILDING':0}]]
g_ref_data_metadata_d['properties']['overviews'] = ["The are dataset covers roughly 40000 square kilometers. 6.94% of this is labelled by this reference data as containing buildings."]
g_ref_data_metadata_d['properties']['collection_method'] = "The reference data was produced by manual annotation of the original satellite images."
g_ref_data_metadata_d['properties']['data_preprocessing'] = "The polygons in the original reference data were converted into rasters with the same dimensions and coordinates as the relevant feature data."
g_ref_data_metadata_d['properties']['CRS'] = 'EPSG:3857'
g_ref_data_metadata_d["properties"]['value'] = 0.
g_ref_data_metadata_d['properties']["orientation"]= "Null"
g_ref_data_metadata_d["properties"]['time_range'] = "2021"
g_ref_data_metadata_d["properties"]['datetime'] = "2019"
from shapely import geometry
g_ref_data_metadata_d['bbox'] = [x_min,y_min, x_max, y_max]
g_ref_data_metadata_d['geometry'] = geometry.mapping(geometry.box(x_min,y_min,x_max,y_max,ccw=True))
g_ref_data_metadata_d['links'] = []
g_ref_data_metadata_d["assets"] = {}
ref_metadata_d = {}
ref_metadata_d['output1'] = g_ref_data_metadata_d
# Check if feature data is compliant
aireo_lib.tds_stac_io.validate_item(feature_metadata_d['input1'])
True
# Add TDS global core elements metadata, and add global level profile metadata to the catalog object.
new_tds_ctl_o.add_tds_root_metadata(tds_root_core_metadata_d, feature_metadata_d, ref_metadata_d)
True
new_tds_ctl_o.valid_tds_root
True
# Adding metadata for each AOI
for aoi_id in tqdm(aoi_ids):
# Dictionary for each AOI collection metadata
aoi_metadata_d = {}
aoi_metadata_d['type'] = "Collection"
aoi_metadata_d["id"] = f"{aoi_id}"
aoi_metadata_d['stac_version'] = '1.0.0-beta.2'
aoi_metadata_d['title'] = f"{aoi_id} Collection"
aoi_metadata_d['description'] = "Datacube of Satellite images for one AOI and datacube of corresponding building masks."
aoi_metadata_d["license"] = "Various (CC-BY-4.0, Creative Commons CC BY-SA 3.0 IGO)"
masks_path = dataset_path + '/' + aoi_id + '/building_masks.nc'
with xr.open_dataarray(masks_path) as masks:
minx = masks.coords['x'].values[0]
maxx = masks.coords['x'].values[-1]
miny = masks.coords['y'].values[0]
maxy = masks.coords['y'].values[-1]
start_time = str(min(masks['date'].values))
end_time = str(max(masks['date'].values))
unique, counts = np.unique(masks.values,return_counts=True)
# calculate percentage of images taken up by buildings
building_percent = 100*(counts[1]/counts[0])
bbox = [minx,miny,maxx,maxy]
geo = geometry.mapping(geometry.box(minx,miny,maxx,maxy))
aoi_metadata_d["bbox"]= bbox
aoi_metadata_d['geometry'] = geo
aoi_metadata_d["extent"] = {"spatial" : {"bbox":[bbox]},
"temporal": {"interval":[[start_time,end_time]]}}
aoi_metadata_d['time_range'] = start_time+' to '+end_time
aoi_metadata_d['links'] = []
aoi_metadata_d["assets"] = {}
# Dictionary for each AOI's reference metadata
aoi_reference_metadata_d = {}
aoi_reference_metadata_d['id'] = f'reference_metadata_AOI_{aoi_id}'
aoi_reference_metadata_d['type'] = "Feature"
aoi_reference_metadata_d['stac_version'] = "1.0.0-beta.2"
aoi_reference_metadata_d['stac_extensions'] = ["reference_data"]
aoi_reference_metadata_d['collection'] = "706cf9e2-bd46-11eb-8529-0242ac130003"
aoi_reference_metadata_d['bbox'] = bbox
aoi_reference_metadata_d['geometry'] = geo
aoi_reference_metadata_d['properties'] = {}
aoi_reference_metadata_d["properties"]['name'] = str(aoi_id)+ " Reference metadata"
aoi_reference_metadata_d['properties']['description'] = "The reference data consists of time series of raster masks stored in datacubes. These masks cover the buildings present in the corresponding satellite images."
aoi_reference_metadata_d['properties']['type'] = "Raster"
aoi_reference_metadata_d['properties']['task'] = "Semantic Segmentation"
aoi_reference_metadata_d['properties']['classes'] = [[{'BUILDING':255,'NOT_BUILDING':0}]]
aoi_reference_metadata_d['properties']['overviews'] = [str(building_percent)+"% of this AOI is covered by buildings"]
aoi_reference_metadata_d['properties']['collection_method'] = "Building polygons were manually created by a team at SpaceNet."
aoi_reference_metadata_d['properties']['data_preprocessing'] = "The polygons in the original reference data were converted into rasters."
aoi_reference_metadata_d['properties']['CRS'] = 'EPSG:3857'
aoi_reference_metadata_d['time_range'] = start_time+' to '+end_time
aoi_reference_metadata_d["properties"]['value'] = 0
aoi_reference_metadata_d['properties']["orientation"]= "null"
aoi_reference_metadata_d["properties"]['datetime'] = start_time
aoi_reference_metadata_d['links'] = []
aoi_reference_metadata_d["assets"] = {}
aoi_reference_d = {}
aoi_reference_d['output1'] = aoi_reference_metadata_d
# Dictionary for each AOI's feature metadata
aoi_feature_data_metadata_d = {}
aoi_feature_data_metadata_d['type'] = "Feature"
aoi_feature_data_metadata_d['stac_version'] = "1.0.0-beta.2"
aoi_feature_data_metadata_d['stac_extensions'] = ["georeferenced_eo_datacube","georeferenced_eo_data"]
aoi_feature_data_metadata_d['id'] = f'predictive_feature_metadata_AOI_{aoi_id}'
aoi_feature_data_metadata_d['collection'] = "706cf9e2-bd46-11eb-8529-0242ac130003"
aoi_feature_data_metadata_d["bbox"]= bbox
aoi_feature_data_metadata_d['geometry'] = geo
# first add data from Georeferenced data profile
aoi_feature_data_metadata_d["properties"] = {}
aoi_feature_data_metadata_d["properties"]['parent_identifier'] = "706cf9e2-bd46-11eb-8529-0242ac130003"
aoi_feature_data_metadata_d["properties"]['identifier'] = aoi_id
aoi_feature_data_metadata_d["properties"]['composed_of'] = "Null"
aoi_feature_data_metadata_d["properties"]['linked_with'] = "Null"
aoi_feature_data_metadata_d['properties']['product_type'] = "Time series of monthly images for one AOI. Each image shares geometry and bounding box."
aoi_feature_data_metadata_d["properties"]["native_product_format"] = "netcdf"
aoi_feature_data_metadata_d["properties"]['processing_level'] = "Null"
aoi_feature_data_metadata_d["properties"]['auxiliary_dataset_filename'] = "Null"
aoi_feature_data_metadata_d["properties"]['identifier'] = str(aoi_id)
aoi_feature_data_metadata_d["properties"]['datetime'] = start_time
# add dimension object for datacube profile
aoi_feature_data_metadata_d["properties"]["dimensions"] = {}
aoi_feature_data_metadata_d["properties"]["dimensions"]["x"] = {
"type": "spatial",
"axis": "x",
"extent": [
minx,
maxx
],
"reference_system": 3857
}
aoi_feature_data_metadata_d["properties"]["dimensions"]["y"] = {
"type": "spatial",
"axis": "y",
"extent": [
miny,
maxy
],
"reference_system": 3857
}
aoi_feature_data_metadata_d["properties"]["dimensions"]["temporal"] = {
"type": "temporal",
"extent": [
start_time,
end_time
]
}
aoi_feature_data_metadata_d["properties"]["dimensions"]["spectral"] = {
"type": "bands",
"values": [
"red",
"green",
"blue"
]
}
aoi_feature_data_metadata_d['links'] = []
aoi_feature_data_metadata_d["assets"] = {}
aoi_feature_d = {}
aoi_feature_d['input1'] = aoi_feature_data_metadata_d
aoi_ref_data_asset_path_d = {'output1':dataset_path+'/'+aoi_id+'/building_masks.nc'}
aoi_feature_asset_path_d = {'input1':dataset_path+'/'+aoi_id+'/images_masked.nc'}
print(new_tds_ctl_o.add_aoi_metadata(aoi_metadata_d=aoi_metadata_d,
aoi_feature_metadata_d=aoi_feature_d,
aoi_ref_data_metadata_d=aoi_reference_d,
aoi_feature_asset_path_d=aoi_feature_asset_path_d,
aoi_ref_data_asset_path_d=aoi_ref_data_asset_path_d))
True True True
Prior to this step, you will need to create a folder called 'biomass_stac_generated' in your environment and leave it empty
import os
catalog_fn_w_path = './sp7_stac/TDS.json'
if os.path.exists('./sp7_stac'):
import shutil
shutil.rmtree(catalog_fn_w_path.replace('/TDS.json',''))
# Write catalog to json
new_tds_ctl_o.write_TDS_STAC_Catalog(catalog_fn_w_path)
new_tds_ctl_o = aireo_lib.core.tds_stac_io.DatasetSTACCatalog.from_TDSCatalog(catalog_fn_w_path)
new_tds_ctl_o.compute_compliance_level()
1
new_tds_ctl_o.report_metadata_completeness()
{'tds_core_metadata': {'required_metadata': 1.0, 'recommended_metadata': 0.3333333333333333, 'optional_metadata': 0.23529411764705882}}
class AOIDatasetSpaceNet:
"""
This class is to load and to store all data (input features/ reference data) for one area of interest. An area of interest is defined by its bounding box, its geometry, and its time interval. For each specific EO TDS the user needs to create a subclass of AOIDataset and implements its abstract methods.
"""
def __init__(self, AOI_STAC_collection, TDS_STAC_catalog):
self.AOI_STAC_collection = AOI_STAC_collection
self.TDS_STAC_catalog = TDS_STAC_catalog
self.stride = self.TDS_STAC_catalog.tds_ctl_root_info.tds_root_metadata_d['example_stride']
self.window_size = self.TDS_STAC_catalog.tds_ctl_root_info.tds_root_metadata_d['example_window_size']
for eo_feature in self.AOI_STAC_collection.aoi_all_field_metadata.features:
aoi_feature_asset_path_d = self.AOI_STAC_collection.aoi_all_field_metadata.features[eo_feature].data_asset_w_path
self.feature_var_name = 'features_'+eo_feature
self.feature_data = xr.open_dataarray(aoi_feature_asset_path_d)
for reference_data in self.AOI_STAC_collection.aoi_all_field_metadata.references:
aoi_ref_data_asset_path_d = self.AOI_STAC_collection.aoi_all_field_metadata.references[reference_data].data_asset_w_path
self.ref_var_name = 'references_'+reference_data
self.reference_data = xr.open_dataarray(aoi_ref_data_asset_path_d)
self.timesteps = self.feature_data['date'].values
self.data = self.feature_data.to_dataset(name=self.feature_var_name)
# Add second DataArray to existing dataset
self.data[self.ref_var_name] = self.reference_data
def __getitem__(self, index):
if index >= len(self):
sys.exit('index out of range')
# Return examples based on window size and stride metadata
sample_image = self.feature_data[0]
x1_ceiling = int((sample_image.shape[1]-self.window_size)/self.stride) +1
y1_ceiling = int((sample_image.shape[2]-self.window_size)/self.stride) +1
single_image_examples = x1_ceiling*y1_ceiling
timestep = int(index/single_image_examples)
image = self.feature_data[timestep]
image_index = index - timestep*single_image_examples
x1 = self.stride*(image_index%x1_ceiling)
y1 = self.stride*(int(image_index/x1_ceiling))
x2 = x1+self.window_size
y2 = y1+self.window_size
date = self.timesteps[timestep]
image = image[:,x1:x2,y1:y2]
building_mask = self.reference_data[timestep,x1:x2,y1:y2]
ds = self.data.isel(date=[timestep],band=[0,1,2,3],x=slice(x1,x2),y=slice(y1,y2)).squeeze()
return ds
# return the number of timesteps multiplied by number of examples in a single timestep
def __len__(self):
sample_image = self.feature_data[0]
x1_ceiling = int((sample_image.shape[1]-self.window_size)/self.stride) +1
y1_ceiling = int((sample_image.shape[2]-self.window_size)/self.stride) +1
single_image_examples = int(x1_ceiling)*int(y1_ceiling)
return len(self.timesteps)*single_image_examples
def get_length(self):
return len(self)
The user of the dataset can access most of what is offered by the dataset using just its STAC catalog. All he/she needs to do is create a dataset object by passing to it the path to the STAC catalog at the root level. The library automatically reads in all the metadata and loads the assets into the dataset object. Some of the functionalities that a dataset object offers through aireo_lib are:
Can access an example instance from the dataset which serves as an input-output pair for a Machine Learning algorithm.
Xarrays are used to store data and give examples.
Dataset can also return each AOI independently
Offer basic plotting functions for each variable in the dataset and AOI.
Some statistics can also be calculated at both the AOI level and whole dataset level.
from aireo_lib.core import EOTrainingDataset
sp7_tds_ctl_fn = Path(os.environ['EDC_PATH']+'/data/SpaceNet7/sp7_stac/TDS.json')
eo_tds_obj = EOTrainingDataset(sp7_tds_ctl_fn, AOIDatasetSpaceNet)
len(eo_tds_obj)
18000
eo_tds_obj[4204]
<xarray.Dataset> Dimensions: (band: 4, x: 100, y: 100) Coordinates: * y (y) float64 3.771e+06 3.771e+06 ... 3.77e+06 3.77e+06 * x (x) float64 2.237e+06 2.237e+06 ... 2.238e+06 2.238e+06 date datetime64[ns] 2019-11-01 * band (band) int32 1 2 3 4 Data variables: features_input1 (band, y, x) int16 48 42 42 46 53 ... 255 255 255 255 references_output1 (y, x) int16 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 255 255 0
array([3770941.964764, 3770937.18745 , 3770932.410135, 3770927.632821, 3770922.855507, 3770918.078193, 3770913.300878, 3770908.523564, 3770903.74625 , 3770898.968935, 3770894.191621, 3770889.414307, 3770884.636993, 3770879.859678, 3770875.082364, 3770870.30505 , 3770865.527736, 3770860.750421, 3770855.973107, 3770851.195793, 3770846.418479, 3770841.641164, 3770836.86385 , 3770832.086536, 3770827.309221, 3770822.531907, 3770817.754593, 3770812.977279, 3770808.199964, 3770803.42265 , 3770798.645336, 3770793.868022, 3770789.090707, 3770784.313393, 3770779.536079, 3770774.758765, 3770769.98145 , 3770765.204136, 3770760.426822, 3770755.649507, 3770750.872193, 3770746.094879, 3770741.317565, 3770736.54025 , 3770731.762936, 3770726.985622, 3770722.208308, 3770717.430993, 3770712.653679, 3770707.876365, 3770703.09905 , 3770698.321736, 3770693.544422, 3770688.767108, 3770683.989793, 3770679.212479, 3770674.435165, 3770669.657851, 3770664.880536, 3770660.103222, 3770655.325908, 3770650.548594, 3770645.771279, 3770640.993965, 3770636.216651, 3770631.439336, 3770626.662022, 3770621.884708, 3770617.107394, 3770612.330079, 3770607.552765, 3770602.775451, 3770597.998137, 3770593.220822, 3770588.443508, 3770583.666194, 3770578.88888 , 3770574.111565, 3770569.334251, 3770564.556937, 3770559.779622, 3770555.002308, 3770550.224994, 3770545.44768 , 3770540.670365, 3770535.893051, 3770531.115737, 3770526.338423, 3770521.561108, 3770516.783794, 3770512.00648 , 3770507.229166, 3770502.451851, 3770497.674537, 3770492.897223, 3770488.119908, 3770483.342594, 3770478.56528 , 3770473.787966, 3770469.010651])
array([2237161.332507, 2237166.109822, 2237170.887136, 2237175.66445 , 2237180.441765, 2237185.219079, 2237189.996393, 2237194.773707, 2237199.551022, 2237204.328336, 2237209.10565 , 2237213.882964, 2237218.660279, 2237223.437593, 2237228.214907, 2237232.992221, 2237237.769536, 2237242.54685 , 2237247.324164, 2237252.101479, 2237256.878793, 2237261.656107, 2237266.433421, 2237271.210736, 2237275.98805 , 2237280.765364, 2237285.542678, 2237290.319993, 2237295.097307, 2237299.874621, 2237304.651935, 2237309.42925 , 2237314.206564, 2237318.983878, 2237323.761193, 2237328.538507, 2237333.315821, 2237338.093135, 2237342.87045 , 2237347.647764, 2237352.425078, 2237357.202392, 2237361.979707, 2237366.757021, 2237371.534335, 2237376.311649, 2237381.088964, 2237385.866278, 2237390.643592, 2237395.420907, 2237400.198221, 2237404.975535, 2237409.752849, 2237414.530164, 2237419.307478, 2237424.084792, 2237428.862106, 2237433.639421, 2237438.416735, 2237443.194049, 2237447.971363, 2237452.748678, 2237457.525992, 2237462.303306, 2237467.080621, 2237471.857935, 2237476.635249, 2237481.412563, 2237486.189878, 2237490.967192, 2237495.744506, 2237500.52182 , 2237505.299135, 2237510.076449, 2237514.853763, 2237519.631077, 2237524.408392, 2237529.185706, 2237533.96302 , 2237538.740335, 2237543.517649, 2237548.294963, 2237553.072277, 2237557.849592, 2237562.626906, 2237567.40422 , 2237572.181534, 2237576.958849, 2237581.736163, 2237586.513477, 2237591.290792, 2237596.068106, 2237600.84542 , 2237605.622734, 2237610.400049, 2237615.177363, 2237619.954677, 2237624.731991, 2237629.509306, 2237634.28662 ])
array('2019-11-01T00:00:00.000000000', dtype='datetime64[ns]')
array([1, 2, 3, 4], dtype=int32)
array([[[ 48, 42, ..., 154, 155], [ 45, 40, ..., 140, 139], ..., [ 76, 74, ..., 169, 163], [ 71, 73, ..., 157, 145]], [[ 43, 38, ..., 126, 128], [ 41, 36, ..., 115, 114], ..., [ 63, 62, ..., 146, 139], [ 59, 61, ..., 134, 122]], [[ 31, 27, ..., 92, 89], [ 28, 24, ..., 83, 81], ..., [ 44, 42, ..., 109, 101], [ 43, 43, ..., 101, 88]], [[255, 255, ..., 255, 255], [255, 255, ..., 255, 255], ..., [255, 255, ..., 255, 255], [255, 255, ..., 255, 255]]], dtype=int16)
array([[ 0, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0], ..., [ 0, 0, 0, ..., 255, 255, 255], [ 0, 0, 0, ..., 255, 255, 255], [ 0, 0, 0, ..., 255, 255, 0]], dtype=int16)
help(eo_tds_obj.get_subset)
Help on method get_subset in module aireo_lib.core: get_subset(index_arr, data_type='xarray') method of aireo_lib.core.EOTrainingDataset instance Returns a subset of examples of the dataset, the return type could be xarray dataset or numpy array. :param index_arr: the indexes of the examples :type index_arr: list[int] :param data_type: type of each returned example :return: A list of xarray's :rtype: xarray.Dataset
eo_tds_obj.get_subset([19,1121])
[<xarray.Dataset> Dimensions: (band: 4, x: 100, y: 100) Coordinates: * y (y) float64 2.035e+06 2.035e+06 ... 2.034e+06 2.034e+06 * x (x) float64 -8.563e+06 -8.563e+06 ... -8.563e+06 date datetime64[ns] 2018-10-01 * band (band) int32 1 2 3 4 Data variables: features_input1 (band, y, x) int16 ... references_output1 (y, x) int16 ..., <xarray.Dataset> Dimensions: (band: 4, x: 100, y: 100) Coordinates: * y (y) float64 2.032e+06 2.032e+06 ... 2.031e+06 2.031e+06 * x (x) float64 -8.564e+06 -8.564e+06 ... -8.563e+06 date datetime64[ns] 2019-04-01 * band (band) int32 1 2 3 4 Data variables: features_input1 (band, y, x) int16 ... references_output1 (y, x) int16 ...]
aoi_objs = eo_tds_obj.get_aoi_datasets()
len(aoi_objs[1])
3600
from importlib import reload
from aireo_lib.plotting import EOTDSPlot as aireo_viz
reload(aireo_lib.plotting)
plot_d = aireo_viz.plot_example(EOTDS=eo_tds_obj,
ex_index=128,
field_names=['features_input1', 'references_output1'])
aoi_obj = eo_tds_obj.get_aoi_dataset(2)
# Basic plot of all the variables in an AOI, returns a dict of matplotlib figures
aoi_plots_d = aireo_viz.plot_aoi_dataset(aoi_obj)
aoi_plots_d
{'features_input1': <Figure size 640x480 with 1 Axes>, 'references_output1': <Figure size 640x480 with 1 Axes>}
aireo_viz.map_aois(eo_tds_obj)
import aireo_lib.statistics
from importlib import reload
reload(aireo_lib.statistics)
<module 'aireo_lib.statistics' from '/opt/conda/envs/eurodatacube-gpu-0.24.5/lib/python3.8/site-packages/aireo_lib/statistics.py'>
aireo_lib.statistics.EOTDSStatistics.reference_data_statistics(eo_tds_obj)
{'references_output1_aoi0': Counter({0: 23955211, 255: 1044789}), 'references_output1_aoi1': Counter({0: 22815686, 255: 2184314}), 'references_output1_aoi2': Counter({0: 23400203, 255: 599797}), 'references_output1_aoi3': Counter({0: 24698825, 255: 1301175}), 'references_output1_aoi4': Counter({0: 23278423, 255: 1721577}), 'whole_TDS_stats': {0: 118148348, 255: 6851652}}
aireo_lib.statistics.EOTDSStatistics.metadata_statistics(eo_tds_obj)
{'tds_core_metadata': {'required_metadata': 1.0, 'recommended_metadata': 0.3333333333333333, 'optional_metadata': 0.23529411764705882}}
aireo_lib.statistics.EOTDSStatistics.dataset_statistics(eo_tds_obj)
{'num_examples': 18000, 'references_stats': {'references_output1_aoi0': Counter({0: 23955211, 255: 1044789}), 'references_output1_aoi1': Counter({0: 22815686, 255: 2184314}), 'references_output1_aoi2': Counter({0: 23400203, 255: 599797}), 'references_output1_aoi3': Counter({0: 24698825, 255: 1301175}), 'references_output1_aoi4': Counter({0: 23278423, 255: 1721577}), 'whole_TDS_stats': {0: 118148348, 255: 6851652}}, 'features_stats': {'aoi_0_channel_0': {'mean': 123.8392085, 'std': 85.74647842386017, 'max': 255, 'min': 0}, 'aoi_0_channel_1': {'mean': 117.35135975, 'std': 87.50644128049113, 'max': 255, 'min': 0}, 'aoi_0_channel_2': {'mean': 124.858521, 'std': 84.97290367930557, 'max': 255, 'min': 0}, 'aoi_0_channel_3': {'mean': 123.87602725, 'std': 81.03238719183359, 'max': 255, 'min': 10}, 'aoi_0_channel_4': {'mean': 116.57333525, 'std': 85.32633332354737, 'max': 255, 'min': 6}, 'aoi_0_channel_5': {'mean': 124.970657, 'std': 83.23103582491535, 'max': 255, 'min': 0}, 'aoi_0_channel_6': {'mean': 135.36820025, 'std': 77.90177855046642, 'max': 255, 'min': 7}, 'aoi_0_channel_7': {'mean': 124.89532925, 'std': 81.89869963732073, 'max': 255, 'min': 0}, 'aoi_0_channel_8': {'mean': 138.02938625, 'std': 77.20226179781467, 'max': 255, 'min': 2}, 'aoi_0_channel_9': {'mean': 141.97108425, 'std': 74.41934668236084, 'max': 255, 'min': 15}, 'aoi_0_channel_10': {'mean': 124.80170425, 'std': 80.1143273331653, 'max': 255, 'min': 15}, 'aoi_0_channel_11': {'mean': 131.4700485, 'std': 79.73908660379563, 'max': 255, 'min': 0}, 'aoi_0_channel_12': {'mean': 133.13600025, 'std': 78.22282775304161, 'max': 255, 'min': 12}, 'aoi_0_channel_13': {'mean': 130.64855375, 'std': 79.8882657640243, 'max': 255, 'min': 0}, 'aoi_0_channel_14': {'mean': 135.8925105, 'std': 79.26209121962027, 'max': 255, 'min': 0}, 'aoi_0_channel_15': {'mean': 129.075553, 'std': 81.26439428645375, 'max': 255, 'min': 1}, 'aoi_0_channel_16': {'mean': 133.5038135, 'std': 81.2708695994895, 'max': 255, 'min': 0}, 'aoi_0_channel_17': {'mean': 141.78626525, 'std': 73.22144778141592, 'max': 255, 'min': 11}, 'aoi_0_channel_18': {'mean': 139.34040775, 'std': 75.60000271040815, 'max': 255, 'min': 7}, 'aoi_0_channel_19': {'mean': 131.4839225, 'std': 81.46713577887702, 'max': 255, 'min': 5}, 'aoi_0_channel_20': {'mean': 124.8148895, 'std': 84.63123502349941, 'max': 255, 'min': 0}, 'aoi_0_channel_21': {'mean': 127.88002575, 'std': 84.95645757639234, 'max': 255, 'min': 0}, 'aoi_0_channel_22': {'mean': 133.37973125, 'std': 79.47025857154219, 'max': 255, 'min': 6}, 'aoi_0_channel_23': {'mean': 144.47827075, 'std': 70.57850491714662, 'max': 255, 'min': 33}, 'aoi_0_channel_24': {'mean': 144.4181195, 'std': 71.85718157626084, 'max': 255, 'min': 18}, 'aoi_1_channel_0': {'mean': 163.326323, 'std': 63.082780406380984, 'max': 255, 'min': 17}, 'aoi_1_channel_1': {'mean': 157.12603525, 'std': 65.88036075619004, 'max': 255, 'min': 28}, 'aoi_1_channel_2': {'mean': 144.4638535, 'std': 72.74750242056791, 'max': 255, 'min': 0}, 'aoi_1_channel_3': {'mean': 151.286522, 'std': 68.56019733886058, 'max': 255, 'min': 0}, 'aoi_1_channel_4': {'mean': 142.61522875, 'std': 74.19453248949793, 'max': 255, 'min': 0}, 'aoi_1_channel_5': {'mean': 147.22827625, 'std': 72.95015099507114, 'max': 255, 'min': 0}, 'aoi_1_channel_6': {'mean': 164.90429625, 'std': 62.33625177649241, 'max': 255, 'min': 2}, 'aoi_1_channel_7': {'mean': 158.14060525, 'std': 63.50777699552776, 'max': 255, 'min': 33}, 'aoi_1_channel_8': {'mean': 157.398015, 'std': 65.0060753742276, 'max': 255, 'min': 23}, 'aoi_1_channel_9': {'mean': 169.15770075, 'std': 59.76599270256842, 'max': 255, 'min': 35}, 'aoi_1_channel_10': {'mean': 162.119265, 'std': 63.503035170452726, 'max': 255, 'min': 24}, 'aoi_1_channel_11': {'mean': 158.430747, 'std': 65.5295182915456, 'max': 255, 'min': 23}, 'aoi_1_channel_12': {'mean': 144.7713385, 'std': 72.17003738684355, 'max': 255, 'min': 11}, 'aoi_1_channel_13': {'mean': 172.03042025, 'std': 58.057727567985324, 'max': 255, 'min': 40}, 'aoi_1_channel_14': {'mean': 161.37645725, 'std': 63.349180643390426, 'max': 255, 'min': 14}, 'aoi_1_channel_15': {'mean': 166.479854, 'std': 61.74144890702433, 'max': 255, 'min': 20}, 'aoi_1_channel_16': {'mean': 153.3427265, 'std': 67.65107666213588, 'max': 255, 'min': 11}, 'aoi_1_channel_17': {'mean': 131.048609, 'std': 78.05731447574341, 'max': 255, 'min': 10}, 'aoi_1_channel_18': {'mean': 158.068671, 'std': 66.52160744294844, 'max': 255, 'min': 0}, 'aoi_1_channel_19': {'mean': 171.19071925, 'std': 57.95171776071602, 'max': 255, 'min': 37}, 'aoi_1_channel_20': {'mean': 170.70456025, 'std': 59.54143205452916, 'max': 255, 'min': 0}, 'aoi_1_channel_21': {'mean': 48.5609115, 'std': 83.96735866566951, 'max': 255, 'min': 0}, 'aoi_1_channel_22': {'mean': 146.9358895, 'std': 70.72187779141473, 'max': 255, 'min': 21}, 'aoi_1_channel_23': {'mean': 174.59723125, 'std': 55.47426840512648, 'max': 255, 'min': 51}, 'aoi_1_channel_24': {'mean': 173.167864, 'std': 56.976702705382294, 'max': 255, 'min': 31}, 'aoi_2_channel_0': {'mean': 159.17915225, 'std': 62.598774378747336, 'max': 255, 'min': 0}, 'aoi_2_channel_1': {'mean': 156.11740725, 'std': 64.64038675462598, 'max': 255, 'min': 13}, 'aoi_2_channel_2': {'mean': 155.90708275, 'std': 66.08855293948136, 'max': 255, 'min': 0}, 'aoi_2_channel_3': {'mean': 156.96184, 'std': 64.3838100830824, 'max': 255, 'min': 0}, 'aoi_2_channel_4': {'mean': 163.02008725, 'std': 58.45560456237193, 'max': 255, 'min': 15}, 'aoi_2_channel_5': {'mean': 152.22776125, 'std': 66.79779896495833, 'max': 255, 'min': 4}, 'aoi_2_channel_6': {'mean': 149.952995, 'std': 67.3626665522527, 'max': 255, 'min': 0}, 'aoi_2_channel_7': {'mean': 160.44449275, 'std': 60.5856688123949, 'max': 255, 'min': 38}, 'aoi_2_channel_8': {'mean': 174.504791, 'std': 53.0792672193798, 'max': 255, 'min': 47}, 'aoi_2_channel_9': {'mean': 170.66480475, 'std': 55.29532249561793, 'max': 255, 'min': 25}, 'aoi_2_channel_10': {'mean': 174.47526875, 'std': 53.19809018531839, 'max': 255, 'min': 34}, 'aoi_2_channel_11': {'mean': 168.45766475, 'std': 56.83450308770721, 'max': 255, 'min': 8}, 'aoi_2_channel_12': {'mean': 137.085284, 'std': 73.0604513203917, 'max': 255, 'min': 18}, 'aoi_2_channel_13': {'mean': 141.06220325, 'std': 71.05113346390533, 'max': 255, 'min': 14}, 'aoi_2_channel_14': {'mean': 168.540119, 'std': 56.1672372603981, 'max': 255, 'min': 36}, 'aoi_2_channel_15': {'mean': 135.06962025, 'std': 75.4900242069825, 'max': 255, 'min': 0}, 'aoi_2_channel_16': {'mean': 163.013963, 'std': 58.8012950498086, 'max': 255, 'min': 20}, 'aoi_2_channel_17': {'mean': 135.20635075, 'std': 73.68530496386624, 'max': 255, 'min': 22}, 'aoi_2_channel_18': {'mean': 137.60837775, 'std': 73.63211599066871, 'max': 255, 'min': 10}, 'aoi_2_channel_19': {'mean': 157.34887625, 'std': 63.31100766148161, 'max': 255, 'min': 27}, 'aoi_2_channel_20': {'mean': 161.15167825, 'std': 60.28380473608546, 'max': 255, 'min': 21}, 'aoi_2_channel_21': {'mean': 135.89142825, 'std': 76.58566939006995, 'max': 255, 'min': 0}, 'aoi_2_channel_22': {'mean': 149.90493575, 'std': 70.16131050328508, 'max': 255, 'min': 0}, 'aoi_2_channel_23': {'mean': 149.308126, 'std': 70.58677073551479, 'max': 255, 'min': 0}, 'aoi_3_channel_0': {'mean': 123.3660885, 'std': 93.58447917101539, 'max': 255, 'min': 0}, 'aoi_3_channel_1': {'mean': 119.03949825, 'std': 90.35485486202862, 'max': 255, 'min': 0}, 'aoi_3_channel_2': {'mean': 124.186373, 'std': 93.1367513342873, 'max': 255, 'min': 0}, 'aoi_3_channel_3': {'mean': 122.40390825, 'std': 89.5830735093163, 'max': 255, 'min': 0}, 'aoi_3_channel_4': {'mean': 102.14981025, 'std': 90.692574506621, 'max': 255, 'min': 0}, 'aoi_3_channel_5': {'mean': 121.07989275, 'std': 90.48434376121917, 'max': 255, 'min': 0}, 'aoi_3_channel_6': {'mean': 120.31731075, 'std': 91.84566158038142, 'max': 255, 'min': 0}, 'aoi_3_channel_7': {'mean': 53.472411, 'std': 86.26141847516229, 'max': 255, 'min': 0}, 'aoi_3_channel_8': {'mean': 128.18371525, 'std': 88.5333541297115, 'max': 255, 'min': 0}, 'aoi_3_channel_9': {'mean': 125.09219675, 'std': 92.67739729842052, 'max': 255, 'min': 0}, 'aoi_3_channel_10': {'mean': 118.544177, 'std': 89.7204814487341, 'max': 255, 'min': 0}, 'aoi_3_channel_11': {'mean': 122.5278295, 'std': 86.40770630863274, 'max': 255, 'min': 0}, 'aoi_3_channel_12': {'mean': 115.3912785, 'std': 90.02151788675559, 'max': 255, 'min': 0}, 'aoi_3_channel_13': {'mean': 129.32750275, 'std': 85.29478393898872, 'max': 255, 'min': 0}, 'aoi_3_channel_14': {'mean': 82.5039225, 'std': 90.14231093173723, 'max': 255, 'min': 0}, 'aoi_3_channel_15': {'mean': 36.1199605, 'std': 70.93477933269713, 'max': 255, 'min': 0}, 'aoi_3_channel_16': {'mean': 125.74167475, 'std': 83.92087632296983, 'max': 255, 'min': 0}, 'aoi_3_channel_17': {'mean': 118.57582925, 'std': 89.68443894525312, 'max': 255, 'min': 0}, 'aoi_3_channel_18': {'mean': 40.09101625, 'std': 77.78603384472198, 'max': 255, 'min': 0}, 'aoi_3_channel_19': {'mean': 116.26681925, 'std': 90.39337680515023, 'max': 255, 'min': 0}, 'aoi_3_channel_20': {'mean': 122.1272245, 'std': 90.16701527679969, 'max': 255, 'min': 0}, 'aoi_3_channel_21': {'mean': 129.52720175, 'std': 90.6499102485203, 'max': 255, 'min': 0}, 'aoi_3_channel_22': {'mean': 121.5609825, 'std': 89.45618465558805, 'max': 255, 'min': 0}, 'aoi_3_channel_23': {'mean': 53.1353505, 'std': 85.14190443748693, 'max': 255, 'min': 0}, 'aoi_3_channel_24': {'mean': 55.36323875, 'std': 81.80099964462852, 'max': 255, 'min': 0}, 'aoi_3_channel_25': {'mean': 78.005299, 'std': 94.03424173363985, 'max': 255, 'min': 0}, 'aoi_4_channel_0': {'mean': 118.973423, 'std': 83.20503251103901, 'max': 255, 'min': 10}, 'aoi_4_channel_1': {'mean': 126.8121245, 'std': 80.78023106426765, 'max': 255, 'min': 14}, 'aoi_4_channel_2': {'mean': 125.03034175, 'std': 81.96926397515227, 'max': 255, 'min': 1}, 'aoi_4_channel_3': {'mean': 125.964485, 'std': 77.42643844117326, 'max': 255, 'min': 23}, 'aoi_4_channel_4': {'mean': 115.14402775, 'std': 84.96231221698967, 'max': 255, 'min': 7}, 'aoi_4_channel_5': {'mean': 128.2880095, 'std': 80.17994790487141, 'max': 255, 'min': 0}, 'aoi_4_channel_6': {'mean': 116.42356675, 'std': 84.2104275577453, 'max': 255, 'min': 0}, 'aoi_4_channel_7': {'mean': 116.3662955, 'std': 87.5746662346292, 'max': 255, 'min': 5}, 'aoi_4_channel_8': {'mean': 129.11207675, 'std': 75.33946305590526, 'max': 255, 'min': 35}, 'aoi_4_channel_9': {'mean': 115.08718125, 'std': 89.03433279179237, 'max': 255, 'min': 9}, 'aoi_4_channel_10': {'mean': 122.802989, 'std': 82.04556939692645, 'max': 255, 'min': 10}, 'aoi_4_channel_11': {'mean': 120.025169, 'std': 84.63928780431365, 'max': 255, 'min': 6}, 'aoi_4_channel_12': {'mean': 139.72545475, 'std': 70.79622422598328, 'max': 255, 'min': 33}, 'aoi_4_channel_13': {'mean': 135.8504385, 'std': 74.03116164736103, 'max': 255, 'min': 23}, 'aoi_4_channel_14': {'mean': 126.683639, 'std': 81.97573610354264, 'max': 255, 'min': 2}, 'aoi_4_channel_15': {'mean': 126.243398, 'std': 84.16547648480106, 'max': 255, 'min': 3}, 'aoi_4_channel_16': {'mean': 120.70459125, 'std': 84.69901294242119, 'max': 255, 'min': 0}, 'aoi_4_channel_17': {'mean': 119.03276075, 'std': 82.67219662306812, 'max': 255, 'min': 8}, 'aoi_4_channel_18': {'mean': 137.793789, 'std': 74.6488273486161, 'max': 255, 'min': 25}, 'aoi_4_channel_19': {'mean': 111.515614, 'std': 87.88722390770465, 'max': 255, 'min': 0}, 'aoi_4_channel_20': {'mean': 136.6428285, 'std': 74.57845011140684, 'max': 255, 'min': 23}, 'aoi_4_channel_21': {'mean': 113.08089825, 'std': 85.90787476840043, 'max': 255, 'min': 3}, 'aoi_4_channel_22': {'mean': 119.818902, 'std': 81.33056897940901, 'max': 255, 'min': 18}, 'aoi_4_channel_23': {'mean': 124.7050795, 'std': 80.65273673223176, 'max': 255, 'min': 13}, 'aoi_4_channel_24': {'mean': 132.01434075, 'std': 78.18191081121579, 'max': 255, 'min': 0}}}