Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import org.integratedmodelling.klab.Authentication;
import org.integratedmodelling.klab.Observables;
import org.integratedmodelling.klab.api.auth.IUserIdentity;
import org.integratedmodelling.klab.api.data.IGeometry;
import org.integratedmodelling.klab.api.data.IGeometry.Dimension.Type;
import org.integratedmodelling.klab.api.data.IResource;
Expand Down Expand Up @@ -78,6 +79,8 @@
import org.integratedmodelling.klab.stac.extensions.COGAssetExtension;
import org.integratedmodelling.klab.stac.extensions.STACFeatureExtension;
import org.integratedmodelling.klab.stac.extensions.STACIIASAExtension;
import org.integratedmodelling.klab.stac.extensions.WEEDModelSTACExtension;

import org.integratedmodelling.klab.utils.JsonUtils;
import org.integratedmodelling.klab.utils.s3.S3URLUtils;
import org.locationtech.jts.geom.Envelope;
Expand Down Expand Up @@ -328,11 +331,9 @@ public boolean test(HMStacAsset asset) { // Assuming for now that "eo:bands" wou
return true;
}
}
} else { // meaning eo:bands is not present like Microsoft Planetary, in this
// case this would be like the asset key i.e. Id
return asset.getId().equals(assetId);
}
return false;

return asset.getId().equals(assetId); // case this would be like the asset key i.e. Id
}
};
}
Expand Down Expand Up @@ -576,7 +577,6 @@ public boolean test(HMStacAsset asset) { // Assuming for now that "eo:bands" wou
+ "The transformation process could affect the data.");
}


// Specific Implementation for the Slow Requests flow in WEED
if (collection.getId().contains("EU_modelV2-1-MECE")
&& resource.getUrn().contains("im.resources-main")) {
Expand All @@ -588,8 +588,19 @@ public boolean test(HMStacAsset asset) { // Assuming for now that "eo:bands" wou
);

if (!unionMLStacInference.contains(poly)) {
scope.getMonitor().warn("The requested extend for ML inferences is not completely contained in STAC, Starting ML Inference Request");

scope.getMonitor().info("Fetching Model IDs to pass to the Slow Request UDP");
List<String >modelIds = null;
try {
var modelIDs = WEEDModelSTACExtension.GetONNXModelIDs(bbox, scope.getMonitor(), targetSemantics);
if (modelIDs == null || modelIDs.size() == 0) {
throw new Exception("No ONNX Models were found over the specified context");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new KlabIllegalStateException("Error occured while getting ONNX Model info over the specified context");
}
OpenEO service = OpenEOAdapter.getClient("openeo_weed.dataspace.copernicus.eu");
List<Process> processes = new ArrayList<>();
String processNamespace = "https://raw.githubusercontent.com/ESA-WEED-project/OpenEO-UDP-UDF-catalogue/refs/heads/main/UDP/json/udp_starter.json";
Expand All @@ -598,31 +609,35 @@ public boolean test(HMStacAsset asset) { // Assuming for now that "eo:bands" wou
Process process = JsonUtils.load(new URL(processNamespace),
Process.class);
process.encodeSelf(processNamespace);

scope.getMonitor().warn("The requested extend for ML inferences is not completely contained in STAC, Starting ML Inference Request");
processes.add(process);

JSONObject arguments = new JSONObject()
.put("bbox", new JSONObject()
.put("crs", 4326)
.put("west", bbox.get(0))
.put("south", bbox.get(3))
.put("east", bbox.get(1))
.put("north", bbox.get(2)))
.put("digitalId", "AM1729") // Forms the STAC coordinate later
.put("scenarioId", "DT_SLOW_FLOW") // Forms the STAC coordinate later
.put("year", ctxTime.getEnd().getYear())
.put("onnx_model", "EUNIS2021plus_panEU_v201_2024_OneZone") // Hardcoding for now only for Europe, until the "BEST" model is decided!
.put("dt_url", "https://services.integratedmodelling.org/runtime/main/api/v1/dt/ESA_INSTITUTIONAL.3vh554o6h6c");
for (var modelId:modelIds) { // triggering multiple UDPs parallely
JSONObject arguments = new JSONObject()
.put("bbox", new JSONObject() // convert this to a geojson
.put("crs", 4326)
.put("west", bbox.get(0))
.put("south", bbox.get(3))
.put("east", bbox.get(1))
.put("north", bbox.get(2)))
.put("digitalId", "AM1729") // Forms the STAC coordinate later
.put("scenarioId", "DT_SLOW_FLOW") // Forms the STAC coordinate later
.put("year", ctxTime.getEnd().getYear())
.put("onnx_model", modelId) // Hardcoding for now only for Europe, until the "BEST" model is decided!
.put("userId", Authentication.INSTANCE.getAuthenticatedIdentity(IUserIdentity.class).getUsername())
.put("dt_url", "https://services.integratedmodelling.org/runtime/main/api/v1/dt/ESA_INSTITUTIONAL.510zsaubjxr");


OpenEOFuture job = service.submit(processID, arguments,
scope.getMonitor(), processes.toArray(new Process[processes.size()]));
if (job.isCancelled()) {
scope.getMonitor().warn("job canceled");
} else if (job.getError() != null) {
scope.getMonitor().error(job.getError());
} else {
scope.getMonitor().info("Inference Request has been submitted to the ML Workflows");
OpenEOFuture job = service.submit(processID, arguments,
scope.getMonitor(), processes.toArray(new Process[processes.size()]));

if (job.isCancelled()) {
scope.getMonitor().warn("job canceled");
} else if (job.getError() != null) {
scope.getMonitor().error(job.getError());
} else {
scope.getMonitor().info("Inference Request has been submitted to the ML Workflows");
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package org.integratedmodelling.klab.stac.extensions;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;

import org.geotools.api.feature.simple.SimpleFeature;
import org.geotools.data.geojson.GeoJSONReader;
import org.hortonmachine.gears.io.stac.HMStacManager;
import org.hortonmachine.gears.libs.monitor.LogProgressMonitor;
import org.integratedmodelling.klab.api.knowledge.IObservable;
import org.integratedmodelling.klab.api.runtime.monitoring.IMonitor;

import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;

public class WEEDModelSTACExtension {

String MODEL_STAC_API = "https://catalogue.weed.apex.esa.int/collections/model-STAC";

public static List<String> GetONNXModelIDs(List<Double> bbox, IMonitor monitor, IObservable targetSemantics) {


monitor.debug("Making a Search Query to the Model STAC");
try {

JSONObject searchPayload = new JSONObject()
.put("limit", 1000)
.put("bbox", new ArrayList<>(List.of(
bbox.get(0),
bbox.get(2),
bbox.get(1),
bbox.get(3)
)))

.put("collections", new JSONArray().put("model-STAC"));

HttpResponse<JsonNode> response = Unirest
.post("https://catalogue.weed.apex.esa.int/search")
.header("Content-Type", "application/json")
.body(searchPayload)
.asJson();

JSONObject body = response.getBody().getObject();
JSONArray features = body.getJSONArray("features");

List<Map.Entry<String, Float>> pairs = new ArrayList<>();

float highestModelVersion = Float.MIN_VALUE;

Iterator<Object> featureIterator = features.iterator();
while (featureIterator.hasNext()) {
JSONObject feature = (JSONObject) featureIterator.next();
SimpleFeature feat = GeoJSONReader.parseFeature(feature.toString());
if (targetSemantics.toString().toLowerCase().contains("eunis")) {
if (feat.getAttribute("topology") != null &&
feat.getAttribute("topology").toString().toLowerCase().startsWith("eunis")) { // it should've been "typology" instead of "topology"
pairs.add(Map.entry(feat.getID(), ((Number) feat.getAttribute("model_version")).floatValue()));
highestModelVersion = Math.max(highestModelVersion, ((Number) feat.getAttribute("model_version")).floatValue());
}
}

if (targetSemantics.toString().toLowerCase().contains("iucn")) {
if (feat.getAttribute("topology") != null &&
feat.getAttribute("topology").toString().toLowerCase().startsWith("iucn")) { // it should've been "typology" instead of "topology"
pairs.add(Map.entry(feat.getID(), ((Number) feat.getAttribute("model_version")).floatValue()));
highestModelVersion = Math.max(highestModelVersion, ((Number) feat.getAttribute("model_version")).floatValue());
}
}
}

var filterModelVersion = highestModelVersion;
pairs = pairs.stream()
.filter(item -> item.getValue().equals(filterModelVersion))
.toList();

return pairs.stream()
.map(Map.Entry::getKey)
.toList();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

}
Loading