diff --git a/dicoogle/src/main/java/pt/ua/dicoogle/plugins/PluginController.java b/dicoogle/src/main/java/pt/ua/dicoogle/plugins/PluginController.java index 30fa178a1..4194bf368 100755 --- a/dicoogle/src/main/java/pt/ua/dicoogle/plugins/PluginController.java +++ b/dicoogle/src/main/java/pt/ua/dicoogle/plugins/PluginController.java @@ -32,10 +32,7 @@ import pt.ua.dicoogle.sdk.datastructs.Report; import pt.ua.dicoogle.sdk.datastructs.SearchResult; import pt.ua.dicoogle.sdk.datastructs.dim.DimLevel; -import pt.ua.dicoogle.sdk.mlprovider.MLDataset; -import pt.ua.dicoogle.sdk.mlprovider.MLInference; -import pt.ua.dicoogle.sdk.mlprovider.MLInferenceRequest; -import pt.ua.dicoogle.sdk.mlprovider.MLProviderInterface; +import pt.ua.dicoogle.sdk.mlprovider.*; import pt.ua.dicoogle.sdk.settings.ConfigurationHolder; import pt.ua.dicoogle.sdk.task.JointQueryTask; import pt.ua.dicoogle.sdk.task.Task; @@ -876,6 +873,19 @@ public Task datastore(final DatastoreRequest datasetRequest) { return prepareTask; } + public Task cache(String provider, final MLDicomDataset dataset) { + String taskName = "MLPredictionTask" + UUID.randomUUID(); + MLProviderInterface mlInterface = getMachineLearningProviderByName(provider, true); + if (mlInterface == null) { + logger.error("MLProvider with name {} not found", provider); + return null; + } + + Task task = mlInterface.cache(dataset); + task.setName(taskName); + return task; + } + // Methods for Web UI /** Retrieve all web UI plugin descriptors for the given slot id. diff --git a/dicoogle/src/main/java/pt/ua/dicoogle/server/web/servlets/mlprovider/CacheServlet.java b/dicoogle/src/main/java/pt/ua/dicoogle/server/web/servlets/mlprovider/CacheServlet.java new file mode 100644 index 000000000..ef1a98b18 --- /dev/null +++ b/dicoogle/src/main/java/pt/ua/dicoogle/server/web/servlets/mlprovider/CacheServlet.java @@ -0,0 +1,51 @@ +package pt.ua.dicoogle.server.web.servlets.mlprovider; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.io.IOUtils; +import org.restlet.data.Status; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import pt.ua.dicoogle.plugins.PluginController; +import pt.ua.dicoogle.sdk.mlprovider.MLDicomDataset; +import pt.ua.dicoogle.server.web.utils.ResponseUtil; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class CacheServlet extends HttpServlet { + + private static final Logger log = LoggerFactory.getLogger(DatastoreServlet.class); + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + String dataString = IOUtils.toString(req.getReader()); + if (dataString == null) { + resp.sendError(404, "Empty POST body"); + return; + } + + String provider = req.getParameter("provider"); + + if(provider == null || provider.isEmpty()){ + ResponseUtil.sendError(resp, Status.CLIENT_ERROR_BAD_REQUEST.getCode(), "Provider provided was invalid"); + return; + } + + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + MLDicomDataset dataset; + try { + dataset = mapper.readValue(dataString, MLDicomDataset.class); + PluginController.getInstance().cache(provider, dataset); + } catch (Exception e) { + log.error("Error parsing json string", e); + ResponseUtil.sendError(resp, Status.CLIENT_ERROR_BAD_REQUEST.getCode(), "Malformed request"); + } + } + +} diff --git a/dicoogle/src/main/java/pt/ua/dicoogle/server/web/servlets/mlprovider/ImplementedMethodsServlet.java b/dicoogle/src/main/java/pt/ua/dicoogle/server/web/servlets/mlprovider/ImplementedMethodsServlet.java new file mode 100644 index 000000000..4a24192f1 --- /dev/null +++ b/dicoogle/src/main/java/pt/ua/dicoogle/server/web/servlets/mlprovider/ImplementedMethodsServlet.java @@ -0,0 +1,39 @@ +package pt.ua.dicoogle.server.web.servlets.mlprovider; + +import com.fasterxml.jackson.databind.ObjectMapper; +import pt.ua.dicoogle.plugins.PluginController; +import pt.ua.dicoogle.sdk.mlprovider.MLMethod; +import pt.ua.dicoogle.sdk.mlprovider.MLProviderInterface; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Set; + +public class ImplementedMethodsServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + ObjectMapper mapper = new ObjectMapper(); + + String provider = request.getParameter("provider"); + + if(provider == null || provider.isEmpty()){ + response.sendError(404, "Provider provided was invalid"); + return; + + } + + MLProviderInterface mlPlugin = PluginController.getInstance().getMachineLearningProviderByName(provider, true); + Set implementedMethods = mlPlugin.getImplementedMethods(); + response.setContentType("application/json"); + PrintWriter out = response.getWriter(); + mapper.writeValue(out, implementedMethods); + out.close(); + out.flush(); + } + +} diff --git a/sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLMethod.java b/sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLMethod.java new file mode 100644 index 000000000..c92299ed1 --- /dev/null +++ b/sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLMethod.java @@ -0,0 +1,19 @@ +package pt.ua.dicoogle.sdk.mlprovider; + +/** + * This enum lists the available methods of the MLProvider interface. + * This is used when requesting the available methods of a provider. + * It is a ENUM instead for example of a String to restrict the possible values. + */ +public enum MLMethod { + INFER, + BULK_INFER, + DATASTORE, + CACHE, + LIST_MODELS, + CREATE_MODEL, + MODEL_INFO, + TRAIN_MODEL, + STOP_TRAINING, + DELETE_MODEL, +} diff --git a/sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLProviderInterface.java b/sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLProviderInterface.java index e15c2eb1e..ff2887daa 100644 --- a/sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLProviderInterface.java +++ b/sdk/src/main/java/pt/ua/dicoogle/sdk/mlprovider/MLProviderInterface.java @@ -48,6 +48,16 @@ public abstract class MLProviderInterface implements DicooglePlugin { */ public abstract void dataStore(MLDataset dataset); + /** + * This method is similar to dataStore in that is also used to upload data to a provider. + * The main difference is that this method should be used to cache DICOM objects on the provider, + * so that the provider can for example run the inference tasks locally. + * Only DICOM objects can be cached. + * @param dataset a DICOM dataset to cache. + * @return a task to the cache operation. Returns true if the dataset was cached. + */ + public abstract Task cache(MLDicomDataset dataset); + /** * This method creates a model using a specific dataset */ @@ -100,6 +110,12 @@ public abstract class MLProviderInterface implements DicooglePlugin { */ public abstract boolean isAvailable(); + /** + * This method can be used to determine which of the methods of this interface are implemented. + * @return a list of the methods implemented. + */ + public abstract Set getImplementedMethods(); + public Set getAcceptedDataTypes() { return acceptedDataTypes; }