From 5d4f5510bd4ed81069d7040524dd03ec254a88e7 Mon Sep 17 00:00:00 2001 From: kfilippopolitis Date: Tue, 22 Nov 2022 17:20:43 +0200 Subject: [PATCH 1/2] AlgorithmsAPI's functionality is now moved to a new Service layer. Experiments now will run to their proper engines according to the get algorithms. --- config/application.tmpl | 1 + .../eu/hbp/mip/controllers/AlgorithmsAPI.java | 227 +-------------- .../eu/hbp/mip/services/AlgorithmService.java | 269 ++++++++++++++++++ .../hbp/mip/services/ExperimentService.java | 49 ++-- src/main/resources/application.yml | 1 + 5 files changed, 299 insertions(+), 248 deletions(-) create mode 100644 src/main/java/eu/hbp/mip/services/AlgorithmService.java diff --git a/config/application.tmpl b/config/application.tmpl index e42153df..0a309c1a 100644 --- a/config/application.tmpl +++ b/config/application.tmpl @@ -34,6 +34,7 @@ spring: ### EXTERNAL SERVICES ### services: + algorithmsUpdateInterval: {{ .Env.ALGORITHM_UPDATE_INTERVAL}} mipengine: algorithmsUrl: {{ .Env.MIPENGINE_URL}}/algorithms attributesUrl: {{ .Env.MIPENGINE_URL}}/data_models_attributes diff --git a/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java index 44e40651..8addb863 100644 --- a/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java +++ b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java @@ -1,38 +1,18 @@ package eu.hbp.mip.controllers; -import com.github.jmchilton.blend4j.galaxy.GalaxyInstance; -import com.github.jmchilton.blend4j.galaxy.GalaxyInstanceFactory; -import com.github.jmchilton.blend4j.galaxy.WorkflowsClient; -import com.github.jmchilton.blend4j.galaxy.beans.Workflow; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients; -import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance; import eu.hbp.mip.models.DTOs.ExaremeAlgorithmDTO; -import eu.hbp.mip.models.DTOs.MIPEngineAlgorithmDTO; -import eu.hbp.mip.models.galaxy.WorkflowDTO; import eu.hbp.mip.services.ActiveUserService; -import eu.hbp.mip.utils.CustomResourceLoader; -import eu.hbp.mip.utils.HTTPUtil; +import eu.hbp.mip.services.AlgorithmService; import eu.hbp.mip.utils.Logger; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.Resource; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import retrofit2.Call; -import retrofit2.Response; -import java.io.IOException; -import java.net.ConnectException; -import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import static eu.hbp.mip.utils.InputStreamConverter.convertInputStreamToString; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @RestController @@ -40,218 +20,21 @@ @Api(value = "/algorithms") public class AlgorithmsAPI { - private static final Gson gson = new Gson(); - + private final AlgorithmService algorithmService; private final ActiveUserService activeUserService; - - @Value("#{'${services.mipengine.algorithmsUrl}'}") - private String mipengineAlgorithmsUrl; - - @Value("#{'${services.exareme.algorithmsUrl}'}") - private String exaremeAlgorithmsUrl; - - @Value("#{'${services.galaxy.galaxyUrl}'}") - private String galaxyUrl; - - @Value("#{'${services.galaxy.galaxyApiKey}'}") - private String galaxyApiKey; - - @Value("#{'${files.disabledAlgorithms_json}'}") - private String disabledAlgorithmsFilePath; - - public AlgorithmsAPI(ActiveUserService activeUserService, CustomResourceLoader resourceLoader) { + public AlgorithmsAPI(ActiveUserService activeUserService, AlgorithmService algorithmService) { this.activeUserService = activeUserService; - this.resourceLoader = resourceLoader; + this.algorithmService = algorithmService; } @ApiOperation(value = "List all algorithms", response = String.class) @RequestMapping(method = RequestMethod.GET) public ResponseEntity> getAlgorithms() { Logger logger = new Logger(activeUserService.getActiveUser().getUsername(), "(GET) /algorithms"); - logger.LogUserAction("Executing..."); - ArrayList mipengineAlgorithms = getMIPEngineAlgorithms(logger); - ArrayList exaremeAlgorithms = getExaremeAlgorithms(logger); - ArrayList galaxyAlgorithms = getGalaxyWorkflows(logger); - - ArrayList algorithms = new ArrayList<>(); - - // Remove Exareme algorithms that exist in the Exareme2 - if (mipengineAlgorithms != null && exaremeAlgorithms != null){ - int old_exareme_algorithm_size = exaremeAlgorithms.size(); - - for (ExaremeAlgorithmDTO algorithm : mipengineAlgorithms) { - exaremeAlgorithms.removeIf(obj -> Objects.equals(obj.getName(), algorithm.getName())); - } - logger.LogUserAction("Removed "+ (old_exareme_algorithm_size - exaremeAlgorithms.size()) +" deprecated exareme algorithms"); - } - - if (exaremeAlgorithms != null) { - algorithms.addAll(exaremeAlgorithms); - logger.LogUserAction("Loaded " + exaremeAlgorithms.size() + " exareme algorithms"); - } else { - logger.LogUserAction("Fetching exareme algorithms failed"); - } - if (mipengineAlgorithms != null) { - algorithms.addAll(mipengineAlgorithms); - logger.LogUserAction("Loaded " + mipengineAlgorithms.size() + " mipengine algorithms"); - } else { - logger.LogUserAction("Fetching mipengine algorithms failed"); - } - if (galaxyAlgorithms != null) { - algorithms.addAll(galaxyAlgorithms); - logger.LogUserAction("Loaded " + galaxyAlgorithms.size() + " galaxy algorithms"); - } else { - logger.LogUserAction("Fetching galaxy workflows failed"); - } - - List disabledAlgorithms = new ArrayList<>(); - try { - disabledAlgorithms = getDisabledAlgorithms(); - } catch (IOException e) { - logger.LogUserAction("The disabled algorithms could not be loaded."); - } - - // Remove any disabled algorithm - ArrayList allowedAlgorithms = new ArrayList<>(); - for (ExaremeAlgorithmDTO algorithm : algorithms) { - if (!disabledAlgorithms.contains(algorithm.getName())) { - allowedAlgorithms.add(algorithm); - } - } - - logger.LogUserAction("Removed "+ (algorithms.size() - allowedAlgorithms.size()) +" disabled algorithms"); + List allowedAlgorithms = algorithmService.getAlgorithms(logger); logger.LogUserAction("Successfully listed " + allowedAlgorithms.size() + " algorithms"); return ResponseEntity.ok(allowedAlgorithms); } - - /** - * This method gets all the available exareme algorithms and - * - * @return a list of AlgorithmDTOs or null if something fails - */ - public ArrayList getExaremeAlgorithms(Logger logger) { - ArrayList algorithms; - // Get exareme algorithms - try { - StringBuilder response = new StringBuilder(); - HTTPUtil.sendGet(exaremeAlgorithmsUrl, response); - algorithms = gson.fromJson( - response.toString(), - new TypeToken>() { - }.getType() - ); - } catch (Exception e) { - logger.LogUserAction("An exception occurred: " + e.getMessage()); - return null; - } - - logger.LogUserAction("Completed, returned " + algorithms.size() + " Exareme algorithms."); - return algorithms; - } - - /** - * This method gets all the available mipengine algorithms and - * - * @return a list of AlgorithmDTOs or null if something fails - */ - public ArrayList getMIPEngineAlgorithms(Logger logger) { - ArrayList mipEngineAlgorithms; - // Get MIPEngine algorithms - try { - StringBuilder response = new StringBuilder(); - HTTPUtil.sendGet(mipengineAlgorithmsUrl, response); - mipEngineAlgorithms = gson.fromJson( - response.toString(), - new TypeToken>() { - }.getType() - ); - } catch (Exception e) { - logger.LogUserAction("An exception occurred: " + e.getMessage()); - return null; - } - - ArrayList algorithms = new ArrayList<>(); - mipEngineAlgorithms.forEach(mipEngineAlgorithm -> algorithms.add(new ExaremeAlgorithmDTO(mipEngineAlgorithm))); - - logger.LogUserAction("Completed, returned " + algorithms.size() + " Exareme2 algorithms."); - return algorithms; - } - - /** - * This method gets all the available galaxy workflows, converts them into algorithms and - * - * @return a list of AlgorithmDTOs or null if something fails - */ - public ArrayList getGalaxyWorkflows(Logger logger) { - List workflowList; - try { - // Get all the workflows with the galaxy client - final GalaxyInstance instance = GalaxyInstanceFactory.get(galaxyUrl, galaxyApiKey); - final WorkflowsClient workflowsClient = instance.getWorkflowsClient(); - - workflowList = new ArrayList<>(workflowsClient.getWorkflows()); - } catch (Exception e) { - logger.LogUserAction("Error when calling list galaxy workflows: " + e.getMessage()); - return null; - } - - // Get the workflow details with the custom client to receive them as a WorkflowDTO - List workflows = new ArrayList<>(); - // Create the request client - RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class); - for (Workflow workflow : workflowList) { - // Call Galaxy to run the workflow - Call call = service.getWorkflowFromGalaxy(workflow.getId(), galaxyApiKey); - try { - Response response = call.execute(); - - if (response.code() == 200) { // Call succeeded - workflows.add(response.body()); - - } else { // Something unexpected happened - String msgErr = gson.toJson(response.errorBody()); - logger.LogUserAction("Error Response: " + msgErr); - return null; - } - } catch (Exception e) { - logger.LogUserAction("An exception occurred: " + e.getMessage()); - return null; - } - } - logger.LogUserAction("Workflows fetched: " + workflows.size()); - - // Convert the workflows to algorithms - ArrayList algorithms = new ArrayList<>(); - for (WorkflowDTO workflow : workflows) { - logger.LogUserAction("Converting workflow: " + workflow); - - algorithms.add(workflow.convertToAlgorithmDTO()); - - logger.LogUserAction("Converted algorithm: " + algorithms.get(algorithms.size() - 1)); - } - - logger.LogUserAction("Completed!"); - return algorithms; - } - - private final CustomResourceLoader resourceLoader; - - /** - * Fetches the disabled algorithms from a .json file - * - * @return a list with their names - * @throws IOException when the file could not be loaded - */ - List getDisabledAlgorithms() throws IOException { - - Resource resource = resourceLoader.getResource(disabledAlgorithmsFilePath); - - return gson.fromJson(convertInputStreamToString( - resource.getInputStream()), - new TypeToken>() { - }.getType() - ); - } } diff --git a/src/main/java/eu/hbp/mip/services/AlgorithmService.java b/src/main/java/eu/hbp/mip/services/AlgorithmService.java new file mode 100644 index 00000000..5388b8d5 --- /dev/null +++ b/src/main/java/eu/hbp/mip/services/AlgorithmService.java @@ -0,0 +1,269 @@ +package eu.hbp.mip.services; + +import com.github.jmchilton.blend4j.galaxy.GalaxyInstance; +import com.github.jmchilton.blend4j.galaxy.GalaxyInstanceFactory; +import com.github.jmchilton.blend4j.galaxy.WorkflowsClient; +import com.github.jmchilton.blend4j.galaxy.beans.Workflow; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients; +import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance; +import eu.hbp.mip.models.DTOs.ExaremeAlgorithmDTO; +import eu.hbp.mip.models.DTOs.MIPEngineAlgorithmDTO; +import eu.hbp.mip.models.galaxy.WorkflowDTO; +import eu.hbp.mip.utils.CustomResourceLoader; +import eu.hbp.mip.utils.Exceptions.BadRequestException; +import eu.hbp.mip.utils.HTTPUtil; +import eu.hbp.mip.utils.Logger; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Service; +import retrofit2.Call; +import retrofit2.Response; + +import java.io.IOException; +import java.util.*; + +import static eu.hbp.mip.utils.InputStreamConverter.convertInputStreamToString; + +@Service +public class AlgorithmService { + + private static final Gson gson = new Gson(); + + private long algorithmsUpdated = 0; + private List algorithmDTOS = new ArrayList<>(); + + @Value("#{'${services.algorithmsUpdateInterval}'}") + private int algorithmsUpdateInterval; + + @Value("#{'${services.mipengine.algorithmsUrl}'}") + private String mipengineAlgorithmsUrl; + + @Value("#{'${services.exareme.algorithmsUrl}'}") + private String exaremeAlgorithmsUrl; + + @Value("#{'${services.galaxy.galaxyUrl}'}") + private String galaxyUrl; + + @Value("#{'${services.galaxy.galaxyApiKey}'}") + private String galaxyApiKey; + + @Value("#{'${files.disabledAlgorithms_json}'}") + private String disabledAlgorithmsFilePath; + + public AlgorithmService(CustomResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + public ArrayList getAlgorithms(Logger logger) { + ArrayList mipengineAlgorithms = getMIPEngineAlgorithms(logger); + ArrayList exaremeAlgorithms = getExaremeAlgorithms(logger); + ArrayList galaxyAlgorithms = getGalaxyWorkflows(logger); + + ArrayList algorithms = new ArrayList<>(); + + // Remove Exareme algorithms that exist in the Exareme2 + if (mipengineAlgorithms != null && exaremeAlgorithms != null){ + int old_exareme_algorithm_size = exaremeAlgorithms.size(); + + for (ExaremeAlgorithmDTO algorithm : mipengineAlgorithms) { + exaremeAlgorithms.removeIf(obj -> Objects.equals(obj.getName(), algorithm.getName())); + } + logger.LogUserAction("Removed "+ (old_exareme_algorithm_size - exaremeAlgorithms.size()) +" deprecated exareme algorithms"); + } + + if (exaremeAlgorithms != null) { + algorithms.addAll(exaremeAlgorithms); + logger.LogUserAction("Loaded " + exaremeAlgorithms.size() + " exareme algorithms"); + } else { + logger.LogUserAction("Fetching exareme algorithms failed"); + } + if (mipengineAlgorithms != null) { + algorithms.addAll(mipengineAlgorithms); + logger.LogUserAction("Loaded " + mipengineAlgorithms.size() + " mipengine algorithms"); + } else { + logger.LogUserAction("Fetching mipengine algorithms failed"); + } + if (galaxyAlgorithms != null) { + algorithms.addAll(galaxyAlgorithms); + logger.LogUserAction("Loaded " + galaxyAlgorithms.size() + " galaxy algorithms"); + } else { + logger.LogUserAction("Fetching galaxy workflows failed"); + } + + List disabledAlgorithms = new ArrayList<>(); + try { + disabledAlgorithms = getDisabledAlgorithms(); + } catch (IOException e) { + logger.LogUserAction("The disabled algorithms could not be loaded."); + } + + // Remove any disabled algorithm + ArrayList allowedAlgorithms = new ArrayList<>(); + for (ExaremeAlgorithmDTO algorithm : algorithms) { + if (!disabledAlgorithms.contains(algorithm.getName())) { + allowedAlgorithms.add(algorithm); + } + } + + logger.LogUserAction("Removed "+ (algorithms.size() - allowedAlgorithms.size()) +" disabled algorithms"); + + this.algorithmsUpdated = System.currentTimeMillis(); + this.algorithmDTOS = allowedAlgorithms; + + return allowedAlgorithms; + } + + private boolean areAlgorithmsOutDated (){ + if (this.algorithmsUpdated == 0) return true; + return (int)((System.currentTimeMillis() - this.algorithmsUpdated) / 1000) > algorithmsUpdateInterval; + } + + public String getEngineName(Logger logger, String algorithmName){ + if(areAlgorithmsOutDated()) getAlgorithms(logger); + Optional exaremeAlgorithmDTO = this.algorithmDTOS.stream().filter(algorithmDTO -> algorithmDTO.getName().equals(algorithmName)).findAny(); + if (exaremeAlgorithmDTO.isPresent()) return getEngineNameForSpecificAlgorithm(exaremeAlgorithmDTO.get()); + else throw new BadRequestException("Algorithm: " + algorithmName + " does not exist."); + } + + private String getEngineNameForSpecificAlgorithm(ExaremeAlgorithmDTO algorithmDTO){ + switch (algorithmDTO.getType()) { + case "mipengine": + return "MIP-Engine"; + case "workflow": + return "Galaxy"; + default: + return "Exareme"; + } + } + + /** + * This method gets all the available exareme algorithms and + * + * @return a list of AlgorithmDTOs or null if something fails + */ + public ArrayList getExaremeAlgorithms(Logger logger) { + ArrayList algorithms; + // Get exareme algorithms + try { + StringBuilder response = new StringBuilder(); + HTTPUtil.sendGet(exaremeAlgorithmsUrl, response); + algorithms = gson.fromJson( + response.toString(), + new TypeToken>() { + }.getType() + ); + } catch (Exception e) { + logger.LogUserAction("An exception occurred: " + e.getMessage()); + return null; + } + + logger.LogUserAction("Completed, returned " + algorithms.size() + " Exareme algorithms."); + return algorithms; + } + + /** + * This method gets all the available mipengine algorithms and + * + * @return a list of AlgorithmDTOs or null if something fails + */ + public ArrayList getMIPEngineAlgorithms(Logger logger) { + ArrayList mipEngineAlgorithms; + // Get MIPEngine algorithms + try { + StringBuilder response = new StringBuilder(); + HTTPUtil.sendGet(mipengineAlgorithmsUrl, response); + mipEngineAlgorithms = gson.fromJson( + response.toString(), + new TypeToken>() { + }.getType() + ); + } catch (Exception e) { + logger.LogUserAction("An exception occurred: " + e.getMessage()); + return null; + } + + ArrayList algorithms = new ArrayList<>(); + mipEngineAlgorithms.forEach(mipEngineAlgorithm -> algorithms.add(new ExaremeAlgorithmDTO(mipEngineAlgorithm))); + + logger.LogUserAction("Completed, returned " + algorithms.size() + " Exareme2 algorithms."); + return algorithms; + } + + /** + * This method gets all the available galaxy workflows, converts them into algorithms and + * + * @return a list of AlgorithmDTOs or null if something fails + */ + public ArrayList getGalaxyWorkflows(Logger logger) { + List workflowList; + try { + // Get all the workflows with the galaxy client + final GalaxyInstance instance = GalaxyInstanceFactory.get(galaxyUrl, galaxyApiKey); + final WorkflowsClient workflowsClient = instance.getWorkflowsClient(); + + workflowList = new ArrayList<>(workflowsClient.getWorkflows()); + } catch (Exception e) { + logger.LogUserAction("Error when calling list galaxy workflows: " + e.getMessage()); + return null; + } + + // Get the workflow details with the custom client to receive them as a WorkflowDTO + List workflows = new ArrayList<>(); + // Create the request client + RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class); + for (Workflow workflow : workflowList) { + // Call Galaxy to run the workflow + Call call = service.getWorkflowFromGalaxy(workflow.getId(), galaxyApiKey); + try { + Response response = call.execute(); + + if (response.code() == 200) { // Call succeeded + workflows.add(response.body()); + + } else { // Something unexpected happened + String msgErr = gson.toJson(response.errorBody()); + logger.LogUserAction("Error Response: " + msgErr); + return null; + } + } catch (Exception e) { + logger.LogUserAction("An exception occurred: " + e.getMessage()); + return null; + } + } + logger.LogUserAction("Workflows fetched: " + workflows.size()); + + // Convert the workflows to algorithms + ArrayList algorithms = new ArrayList<>(); + for (WorkflowDTO workflow : workflows) { + logger.LogUserAction("Converting workflow: " + workflow); + + algorithms.add(workflow.convertToAlgorithmDTO()); + + logger.LogUserAction("Converted algorithm: " + algorithms.get(algorithms.size() - 1)); + } + + logger.LogUserAction("Completed!"); + return algorithms; + } + + private final CustomResourceLoader resourceLoader; + + /** + * Fetches the disabled algorithms from a .json file + * + * @return a list with their names + * @throws IOException when the file could not be loaded + */ + List getDisabledAlgorithms() throws IOException { + + Resource resource = resourceLoader.getResource(disabledAlgorithmsFilePath); + + return gson.fromJson(convertInputStreamToString( + resource.getInputStream()), + new TypeToken>() { + }.getType() + ); + } +} diff --git a/src/main/java/eu/hbp/mip/services/ExperimentService.java b/src/main/java/eu/hbp/mip/services/ExperimentService.java index a1c16a54..5aa6b09c 100644 --- a/src/main/java/eu/hbp/mip/services/ExperimentService.java +++ b/src/main/java/eu/hbp/mip/services/ExperimentService.java @@ -41,10 +41,12 @@ public class ExperimentService { private static final Gson gson = new Gson(); private final ActiveUserService activeUserService; + private final AlgorithmService algorithmService; private final GalaxyService galaxyService; private final ExperimentRepository experimentRepository; - public ExperimentService(ActiveUserService activeUserService, GalaxyService galaxyService, ExperimentRepository experimentRepository) { + public ExperimentService(ActiveUserService activeUserService, AlgorithmService algorithmService, GalaxyService galaxyService, ExperimentRepository experimentRepository) { + this.algorithmService = algorithmService; this.activeUserService = activeUserService; this.galaxyService = galaxyService; this.experimentRepository = experimentRepository; @@ -58,7 +60,7 @@ public ExperimentService(ActiveUserService activeUserService, GalaxyService gala * @param shared is optional, in case it is required to filter the experiments by shared * @param viewed is optional, in case it is required to filter the experiments by viewed * @param includeShared is optional, in case it is required to retrieve the experiment that is shared - * @param page is the page that is required to be retrieve + * @param page is the page that is required to be retrieved * @param size is the size of each page * @param orderBy is the column that is required to ordered by * @param descending is a boolean to determine if the experiments will be order by descending or ascending @@ -152,13 +154,10 @@ public ExperimentDTO createExperiment(Authentication authentication, ExperimentD //Checking if check (POST) /experiments has proper input. checkPostExperimentProperInput(experimentDTO, logger); - // Get the type of algorithm - String algorithmType = experimentDTO.getAlgorithm().getType(); - if (algorithmType == null) { - logger.LogUserAction("Please provide algorithm type."); - throw new BadRequestException("Please provide algorithm type."); - } + // Get the engine name from algorithmService + String engineName = algorithmService.getEngineName(logger, experimentDTO.getAlgorithm().getName().toUpperCase()); + logger.LogUserAction("Algorithm runs on " + engineName + "."); algorithmParametersLogging(experimentDTO, logger); @@ -168,12 +167,10 @@ public ExperimentDTO createExperiment(Authentication authentication, ExperimentD } // Run with the appropriate engine - if (algorithmType.equals("workflow")) { - logger.LogUserAction("Algorithm runs on Galaxy."); + if (engineName.equals("Galaxy")) { return galaxyService.createGalaxyExperiment(experimentDTO, logger); } else { - logger.LogUserAction("Algorithm runs on Exareme."); - return createSynchronousExperiment(experimentDTO, logger); + return createSynchronousExperiment(experimentDTO, engineName, logger); } } @@ -190,12 +187,13 @@ public ExperimentDTO runTransientExperiment(Authentication authentication, Exper //Checking if check (POST) /experiments has proper input. checkPostExperimentProperInput(experimentDTO, logger); - // Get the type of algorithm - String algorithmType = experimentDTO.getAlgorithm().getType(); + // Get the engine name from algorithmService + String engineName = algorithmService.getEngineName(logger, experimentDTO.getAlgorithm().getName().toUpperCase()); + experimentDTO.setUuid(UUID.randomUUID()); - if (algorithmType.equals("workflow")) { + if (engineName.equals("Galaxy")) { logger.LogUserAction("You can not run workflow algorithms transiently."); throw new BadRequestException("You can not run workflow algorithms transiently."); } @@ -209,7 +207,7 @@ public ExperimentDTO runTransientExperiment(Authentication authentication, Exper logger.LogUserAction("Completed, returning: " + experimentDTO); - ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(experimentDTO, logger); + ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(experimentDTO, engineName, logger); logger.LogUserAction( "Experiment with uuid: " + experimentDTO.getUuid() @@ -258,7 +256,7 @@ public ExperimentDTO updateExperiment(String uuid, ExperimentDTO experimentDTO, try { experimentRepository.save(experimentDAO); } catch (Exception e) { - logger.LogUserAction("Attempted to save changes to database but an error ocurred : " + e.getMessage() + "."); + logger.LogUserAction("Attempted to save changes to database but an error occurred : " + e.getMessage() + "."); throw new InternalServerError(e.getMessage()); } @@ -287,7 +285,7 @@ public void deleteExperiment(String uuid, Logger logger) { try { experimentRepository.delete(experimentDAO); } catch (Exception e) { - logger.LogUserAction("Attempted to delete an experiment to database but an error ocurred : " + e.getMessage() + "."); + logger.LogUserAction("Attempted to delete an experiment to database but an error occurred : " + e.getMessage() + "."); throw new InternalServerError(e.getMessage()); } @@ -400,7 +398,7 @@ private String getDatasetFromExperimentParameters(ExperimentDTO experimentDTO, L * @param logger contains username and the endpoint. * @return the experiment information that was retrieved from exareme */ - private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, Logger logger) { + private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, String engineName, Logger logger) { logger.LogUserAction("Running the algorithm..."); @@ -413,7 +411,7 @@ private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, L new Thread(() -> { try { - ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(finalExperimentDTO, logger); + ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(finalExperimentDTO, engineName, logger); logger.LogUserAction( "Experiment with uuid: " + experimentDAO.getUuid() @@ -444,9 +442,8 @@ private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, L * @param experimentDTO is the request with the experiment information * @return the result of experiment as well as the http status that was retrieved */ - private ExaremeAlgorithmResultDTO runSynchronousExperiment(ExperimentDTO experimentDTO, Logger logger) { - String algorithmType = experimentDTO.getAlgorithm().getType(); - if (algorithmType.equals("mipengine")) { + private ExaremeAlgorithmResultDTO runSynchronousExperiment(ExperimentDTO experimentDTO, String engineName, Logger logger) { + if (engineName.equals("MIP-Engine")) { return runMIPEngineExperiment(experimentDTO, logger); } else { return runExaremeExperiment(experimentDTO, logger); @@ -485,9 +482,9 @@ private ExaremeAlgorithmResultDTO runExaremeExperiment(ExperimentDTO experimentD logger.LogUserAction("Exareme algorithm execution. Body: " + algorithmBody); StringBuilder requestResponseBody = new StringBuilder(); - int requestReponseCode; + int requestResponseCode; try { - requestReponseCode = HTTPUtil.sendPost(algorithmEndpoint, algorithmBody, requestResponseBody); + requestResponseCode = HTTPUtil.sendPost(algorithmEndpoint, algorithmBody, requestResponseBody); } catch (Exception e) { throw new InternalServerError("Error occurred : " + e.getMessage()); } @@ -496,7 +493,7 @@ private ExaremeAlgorithmResultDTO runExaremeExperiment(ExperimentDTO experimentD ExaremeAlgorithmResultDTO exaremeResult = JsonConverters.convertJsonStringToObject( String.valueOf(requestResponseBody), ExaremeAlgorithmResultDTO.class ); - exaremeResult.setCode(requestReponseCode); + exaremeResult.setCode(requestResponseCode); return exaremeResult; } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e301494d..07f86b5d 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -34,6 +34,7 @@ spring: ### EXTERNAL SERVICES ### services: + algorithmsUpdateInterval: 10 mipengine: algorithmsUrl: "http://127.0.0.1:5000/algorithms" attributesUrl: "http://127.0.0.1:5000/data_models_attributes" From f76fb02be9c2f3e256c9e611c1266229a2da71c3 Mon Sep 17 00:00:00 2001 From: kfilippopolitis Date: Mon, 28 Nov 2022 23:02:12 +0200 Subject: [PATCH 2/2] Now the algorithms are loaded in a cache by a schedule task --- config/pathologies.json | 2400 ----------------- .../eu/hbp/mip/controllers/AlgorithmsAPI.java | 6 +- .../eu/hbp/mip/services/AlgorithmService.java | 49 +- .../hbp/mip/services/ExperimentService.java | 22 +- src/main/resources/application.yml | 3 +- 5 files changed, 47 insertions(+), 2433 deletions(-) delete mode 100644 config/pathologies.json diff --git a/config/pathologies.json b/config/pathologies.json deleted file mode 100644 index ba42d5b9..00000000 --- a/config/pathologies.json +++ /dev/null @@ -1,2400 +0,0 @@ -[ - { - "code": "neurodegenerativediseases", - "label": "Neurodegenerative diseases", - "datasets": [ - { - "code": "adni", - "label": "ADNI" - }, - { - "code": "ppmi", - "label": "PPMI" - }, - { - "code": "edsd", - "label": "EDSD" - } - ], - "hierarchy": { - "code": "root", - "label": "/", - "groups": [ - { - "code": "genetic", - "groups": [ - { - "code": "polymorphism", - "label": "polymorphism", - "variables": [ - { - "code": "apoe4", - "description": "Apolipoprotein E (APOE) e4 allele: is the strongest risk factor for Late Onset Alzheimer Disease (LOAD). At least one copy of APOE-e4 ", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "ApoE4", - "methodology": "adni-merge", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs3818361_t", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs3818361_T", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs744373_c", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs744373_C", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs190982_g", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs190982_G", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs1476679_c", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs1476679_C", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs11767557_c", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs11767557_C", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs11136000_t", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs11136000_T", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs610932_a", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs610932_A", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs3851179_a", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs3851179_A", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs17125944_c", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs17125944_C", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs10498633_t", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs10498633_T", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs3764650_g", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs3764650_G", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs3865444_t", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs3865444_T", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - }, - { - "code": "rs2718058_g", - "description": "", - "enumerations": [ - { - "code": 0, - "label": 0 - }, - { - "code": 1, - "label": 1 - }, - { - "code": 2, - "label": 2 - } - ], - "label": "rs2718058_G", - "methodology": "lren-nmm-volumes", - "sql_type": "int", - "type": "polynominal" - } - ] - } - ], - "label": "Genetic" - }, - { - "code": "pet", - "label": "PET - Positron Emission Tomography", - "variables": [ - { - "code": "fdg", - "description": " Average FDG-PET of angular, temporal, and posterior cingulate. Most important hypometabolic regions that are indicative of pathological metabolic change in MCI and AD.", - "label": "FDG-PET", - "methodology": "adni-merge", - "type": "real" - }, - { - "code": "pib", - "description": "Average PIB SUVR of frontal cortex, anterior cingulate, precuneus cortex, and parietal cortex.", - "label": "PIB", - "methodology": "adni-merge", - "type": "real" - }, - { - "code": "av45", - "description": "AV45 Average AV45 SUVR of frontal, anterior cingulate, precuneus, and parietal cortex relative to the cerebellum", - "label": "AV45", - "methodology": "adni-merge", - "type": "real" - } - ] - }, - { - "code": "proteome", - "description": "Protein biology as detected using routine lab chemistries in blood and cerebrospinal fluid specimens as well as in biopsy, measurement of protein-protein interactions, level of antibodies, auto-antibodies, etc.", - "groups": [ - { - "code": "csf_proteome", - "description": "Protein content of the cerebrospinal fluid", - "label": "Cerebrospinal fluid", - "variables": [ - { - "code": "ab1_42", - "description": "A\u03b2 is the main component of amyloid plaques (extracellular deposits found in the brains of patients with Alzheimer''s disease). Similar plaques appear in some variants of Lewy body dementia and in inclusion body myositis (a muscle disease), while A\u03b2 can also form the aggregates that coat cerebral blood vessels in cerebral amyloid angiopathy. The plaques are composed of a tangle of regularly ordered fibrillar aggregates called amyloid fibers, a protein fold shared by other peptides such as the prions associated with protein misfolding diseases.", - "label": "Level of amyloid beta 1-42 peptides in cerebrospinal fluid", - "methodology": "mip-cde", - "type": "real", - "units": "" - }, - { - "code": "ab1_40", - "description": "A\u03b2 is the main component of amyloid plaques (extracellular deposits found in the brains of patients with Alzheimer''s disease). Similar plaques appear in some variants of Lewy body dementia and in inclusion body myositis (a muscle disease), while A\u03b2 can also form the aggregates that coat cerebral blood vessels in cerebral amyloid angiopathy. The plaques are composed of a tangle of regularly ordered fibrillar aggregates called amyloid fibers, a protein fold shared by other peptides such as the prions associated with protein misfolding diseases.", - "label": "Level od amyloid beta 1-40 peptides ion cerebrospinal fluid", - "methodology": "mip-cde", - "type": "real", - "units": "" - }, - { - "code": "t_tau", - "description": "Tau proteins (or \u03c4 proteins) are proteins that stabilize microtubules. They are abundant in neurons of the central nervous system and are less common elsewhere, but are also expressed at very low levels in CNS astrocytes and oligodendrocytes. Pathologies and dementias of the nervous system such as Alzheimer''s disease and Parkinson''s disease are associated with tau proteins that have become defective and no longer stabilize microtubules properly.", - "label": "Total level of tau proteins in cerebrospinal fluid", - "methodology": "mip-cde", - "type": "real", - "units": "" - }, - { - "code": "p_tau", - "description": "Hyperphosphorylation of the tau protein (tau inclusions, pTau) can result in the self-assembly of tangles of paired helical filaments and straight filaments, which are involved in the pathogenesis of Alzheimer''s disease, frontotemporal dementia, and other tauopathies.", - "label": "Level of phosphorylated tau proteins in cerebrospinal fluid ", - "methodology": "mip-cde", - "type": "real", - "units": "" - } - ] - } - ], - "label": "Entire set of proteins expressed by the patient''s organism at the time of the medical workup" - }, - { - "code": "brain_anatomy", - "groups": [ - { - "code": "csf_volume", - "label": "CSF volume", - "variables": [ - { - "code": "rightinflatvent", - "description": "", - "label": "Right inferior lateral ventricle", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftinflatvent", - "description": "", - "label": "Left inferior lateral ventricle", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightlateralventricle", - "description": "", - "label": "Right lateral ventricle", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftlateralventricle", - "description": "", - "label": "Left lateral ventricle", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "_3rdventricle", - "description": "", - "label": "3rd Ventricle", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "_4thventricle", - "description": "", - "label": "4th Ventricle", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "csfglobal", - "description": "", - "label": "CSF global", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "white_matter_volume", - "label": "White matter volume", - "variables": [ - { - "code": "rightcerebellumwhitematter", - "description": "", - "label": "Right Cerebellum White Matter", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftcerebellumwhitematter", - "description": "", - "label": "Left Cerebellum White Matter", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightcerebralwhitematter", - "description": "", - "label": "Right Cerebral White Matter", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftcerebralwhitematter", - "description": "", - "label": "Left Cerebral White Matter", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "opticchiasm", - "description": "", - "label": "Optic chiasm", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "grey_matter_volume", - "groups": [ - { - "code": "cerebellum", - "label": "Cerebellum", - "variables": [ - { - "code": "cerebellarvermallobulesviiix", - "description": "", - "label": "Cerebellar Vermal Lobules VIII-X", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "cerebellarvermallobulesvivii", - "description": "", - "label": "Cerebellar Vermal Lobules VI-VII", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "cerebellarvermallobulesiv", - "description": "", - "label": "Cerebellar Vermal Lobules I-V", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftcerebellumexterior", - "description": "", - "label": "Left Cerebellum Exterior", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightcerebellumexterior", - "description": "", - "label": "Right Cerebellum Exterior", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "cerebral_nuclei", - "groups": [ - { - "code": "basal_ganglia", - "label": "Basal Ganglia", - "variables": [ - { - "code": "rightbasalforebrain", - "description": "", - "label": "Right Basal Forebrain", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftbasalforebrain", - "description": "", - "label": "Left Basal Forebrain", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightaccumbensarea", - "description": "", - "label": "Right Accumbens Area", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftaccumbensarea", - "description": "", - "label": "Left Accumbens Area", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightcaudate", - "description": "", - "label": "Right Caudate", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftcaudate", - "description": "", - "label": "Left Caudate", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightpallidum", - "description": "", - "label": "Right Pallidum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftpallidum", - "description": "", - "label": "Left Pallidum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightputamen", - "description": "", - "label": "Right Putamen", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftputamen", - "description": "", - "label": "Left Putamen", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "amygdala", - "label": "Amygdala", - "variables": [ - { - "code": "rightamygdala", - "description": "", - "label": "Right Amygdala", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftamygdala", - "description": "", - "label": "Left Amygdala", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - } - ], - "label": "Cerebral nuclei" - }, - { - "code": "limbic", - "label": "Limbic", - "variables": [ - { - "code": "righthippocampus", - "description": "", - "label": "Right Hippocampus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "lefthippocampus", - "description": "", - "label": "Left Hippocampus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightthalamusproper", - "description": "", - "label": "Right Thalamus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftthalamusproper", - "description": "", - "label": "Left Thalamus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightacgganteriorcingulategyrus", - "description": "", - "label": "Right anterior cingulate gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftacgganteriorcingulategyrus", - "description": "", - "label": "Left anterior cingulate gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightententorhinalarea", - "description": "", - "label": "Right entorhinal area", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftententorhinalarea", - "description": "", - "label": "Left entorhinal area", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmcggmiddlecingulategyrus", - "description": "", - "label": "Right middle cingulate gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmcggmiddlecingulategyrus", - "description": "", - "label": "Left middle cingulate gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightpcggposteriorcingulategyrus", - "description": "", - "label": "Right posterior cingulate gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftpcggposteriorcingulategyrus", - "description": "", - "label": "Left posterior cingulate gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightphgparahippocampalgyrus", - "description": "", - "label": "Right parahippocampal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftphgparahippocampalgyrus", - "description": "", - "label": "Left parahippocampal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "temporal", - "label": "Temporal", - "variables": [ - { - "code": "rightfugfusiformgyrus", - "description": "", - "label": "Right fusiform gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftfugfusiformgyrus", - "description": "", - "label": "Left fusiform gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightitginferiortemporalgyrus", - "description": "", - "label": "Right inferior temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftitginferiortemporalgyrus", - "description": "", - "label": "Left inferior temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmtgmiddletemporalgyrus", - "description": "", - "label": "Right middle temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmtgmiddletemporalgyrus", - "description": "", - "label": "Left middle temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightppplanumpolare", - "description": "", - "label": "Right planum polare", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftppplanumpolare", - "description": "", - "label": "Left planum polare", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightptplanumtemporale", - "description": "", - "label": "Right planum temporale", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftptplanumtemporale", - "description": "", - "label": "Left planum temporale", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightstgsuperiortemporalgyrus", - "description": "", - "label": "Right superior temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftstgsuperiortemporalgyrus", - "description": "", - "label": "Left superior temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "righttmptemporalpole", - "description": "", - "label": "Right temporal pole", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "lefttmptemporalpole", - "description": "", - "label": "Left temporal pole", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightttgtransversetemporalgyrus", - "description": "", - "label": "Right transverse temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftttgtransversetemporalgyrus", - "description": "", - "label": "Left transverse temporal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "occipital", - "label": "Occipital", - "variables": [ - { - "code": "rightcalccalcarinecortex", - "description": "", - "label": "Right calcarine cortex", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftcalccalcarinecortex", - "description": "", - "label": "Left calcarine cortex", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightcuncuneus", - "description": "", - "label": "Right cuneus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftcuncuneus", - "description": "", - "label": "Left cuneus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightioginferioroccipitalgyrus", - "description": "", - "label": "Right inferior occipital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftioginferioroccipitalgyrus", - "description": "", - "label": "Left inferior occipital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightliglingualgyrus", - "description": "", - "label": "Right lingual gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftliglingualgyrus", - "description": "", - "label": "Left lingual gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmogmiddleoccipitalgyrus", - "description": "", - "label": "Right middle occipital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmogmiddleoccipitalgyrus", - "description": "", - "label": "Left middle occipital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightocpoccipitalpole", - "description": "", - "label": "Right occipital pole", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftocpoccipitalpole", - "description": "", - "label": "Left occipital pole", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightofugoccipitalfusiformgyrus", - "description": "", - "label": "Right occipital fusiform gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftofugoccipitalfusiformgyrus", - "description": "", - "label": "Left occipital fusiform gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightsogsuperioroccipitalgyrus", - "description": "", - "label": "Right superior occipital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftsogsuperioroccipitalgyrus", - "description": "", - "label": "Left superior occipital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "parietal", - "label": "Parietal", - "variables": [ - { - "code": "rightangangulargyrus", - "description": "", - "label": "Right angular gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftangangulargyrus", - "description": "", - "label": "Left angular gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmpogpostcentralgyrusmedialsegment", - "description": "", - "label": "Right postcentral gyrus medial segment", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmpogpostcentralgyrusmedialsegment", - "description": "", - "label": "Left postcentral gyrus medial segment", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightpcuprecuneus", - "description": "", - "label": "Right precuneus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftpcuprecuneus", - "description": "", - "label": "Left precuneus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightpogpostcentralgyrus", - "description": "", - "label": "Right postcentral gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftpogpostcentralgyrus", - "description": "", - "label": "Left postcentral gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightsmgsupramarginalgyrus", - "description": "", - "label": "Right supramarginal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftsmgsupramarginalgyrus", - "description": "", - "label": "Left supramarginal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightsplsuperiorparietallobule", - "description": "", - "label": "Right superior parietal lobule", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftsplsuperiorparietallobule", - "description": "", - "label": "Left superior parietal lobule", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "frontal", - "label": "Frontal", - "variables": [ - { - "code": "rightaorganteriororbitalgyrus", - "description": "", - "label": "Right anterior orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftaorganteriororbitalgyrus", - "description": "", - "label": "Left anterior orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightcocentraloperculum", - "description": "", - "label": "Right central operculum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftcocentraloperculum", - "description": "", - "label": "Left central operculum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightfofrontaloperculum", - "description": "", - "label": "Right frontal operculum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftfofrontaloperculum", - "description": "", - "label": "Left frontal operculum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightfrpfrontalpole", - "description": "", - "label": "Right frontal pole", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftfrpfrontalpole", - "description": "", - "label": "Left frontal pole", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightgregyrusrectus", - "description": "", - "label": "Right gyrus rectus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftgregyrusrectus", - "description": "", - "label": "Left gyrus rectus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightlorglateralorbitalgyrus", - "description": "", - "label": "Right lateral orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftlorglateralorbitalgyrus", - "description": "", - "label": "Left lateral orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmfcmedialfrontalcortex", - "description": "", - "label": "Right medial frontal cortex", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmfcmedialfrontalcortex", - "description": "", - "label": "Left medial frontal cortex", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmfgmiddlefrontalgyrus", - "description": "", - "label": "Right middle frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmfgmiddlefrontalgyrus", - "description": "", - "label": "Left middle frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmorgmedialorbitalgyrus", - "description": "", - "label": "Right medial orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmorgmedialorbitalgyrus", - "description": "", - "label": "Left medial orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmprgprecentralgyrusmedialsegment", - "description": "", - "label": "Right precentral gyrus medial segment", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmprgprecentralgyrusmedialsegment", - "description": "", - "label": "Left precentral gyrus medial segment", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightmsfgsuperiorfrontalgyrusmedialsegment", - "description": "", - "label": "Right superior frontal gyrus medial segment", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftmsfgsuperiorfrontalgyrusmedialsegment", - "description": "", - "label": "Left superior frontal gyrus medial segment", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightopifgopercularpartoftheinferiorfrontalgyrus", - "description": "", - "label": "Right opercular part of the inferior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftopifgopercularpartoftheinferiorfrontalgyrus", - "description": "", - "label": "Left opercular part of the inferior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightorifgorbitalpartoftheinferiorfrontalgyrus", - "description": "", - "label": "Right orbital part of the inferior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftorifgorbitalpartoftheinferiorfrontalgyrus", - "description": "", - "label": "Left orbital part of the inferior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightpoparietaloperculum", - "description": "", - "label": "Right parietal operculum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftpoparietaloperculum", - "description": "", - "label": "Left parietal operculum", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightporgposteriororbitalgyrus", - "description": "", - "label": "Right posterior orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftporgposteriororbitalgyrus", - "description": "", - "label": "Left posterior orbital gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightprgprecentralgyrus", - "description": "", - "label": "Right precentral gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftprgprecentralgyrus", - "description": "", - "label": "Left precentral gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightscasubcallosalarea", - "description": "", - "label": "Right subcallosal area", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftscasubcallosalarea", - "description": "", - "label": "Left subcallosal area", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightsfgsuperiorfrontalgyrus", - "description": "", - "label": "Right superior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftsfgsuperiorfrontalgyrus", - "description": "", - "label": "Left superior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightsmcsupplementarymotorcortex", - "description": "", - "label": "Right supplementary motor cortex", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftsmcsupplementarymotorcortex", - "description": "", - "label": "Left supplementary motor cortex", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "righttrifgtriangularpartoftheinferiorfrontalgyrus", - "description": "", - "label": "Right triangular part of the inferior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "lefttrifgtriangularpartoftheinferiorfrontalgyrus", - "description": "", - "label": "Left triangular part of the inferior frontal gyrus", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "insula", - "label": "Insula", - "variables": [ - { - "code": "rightainsanteriorinsula", - "description": "", - "label": "Right anterior insula", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftainsanteriorinsula", - "description": "", - "label": "Left anterior insula", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "rightpinsposteriorinsula", - "description": "", - "label": "Right posterior insula", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftpinsposteriorinsula", - "description": "", - "label": "Left posterior insula", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "diencephalon", - "label": "Diencephalon", - "variables": [ - { - "code": "rightventraldc", - "description": "", - "label": "Right Ventral DC", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "leftventraldc", - "description": "", - "label": "Left Ventral DC", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - } - ], - "label": "Grey matter volume" - } - ], - "label": "Brain Anatomy", - "variables": [ - { - "code": "tiv", - "description": "Total intra-cranial volume", - "label": "TIV", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - }, - { - "code": "brainstem", - "description": "Brainstem volume", - "label": "Brainstem", - "methodology": "lren-nmm-volumes", - "type": "real", - "units": "cm3" - } - ] - }, - { - "code": "demographics", - "label": "Demographics", - "variables": [ - { - "code": "subjectageyears", - "description": "Subject age in years.", - "label": "Age Years", - "length": 3, - "maxValue": 130, - "methodology": "mip-cde", - "minValue": 0, - "type": "integer", - "units": "years" - }, - { - "code": "subjectage", - "description": "Exact age of the subject, for datasets that allow such precision.", - "label": "Exact age", - "length": 2, - "maxValue": 11, - "methodology": "mip-cde", - "minValue": 0, - "type": "real", - "units": "months" - }, - { - "code": "agegroup", - "description": "Age Group", - "enumerations": [ - { - "code": "-50y", - "label": "-50y" - }, - { - "code": "50-59y", - "label": "50-59y" - }, - { - "code": "60-69y", - "label": "60-69y" - }, - { - "code": "70-79y", - "label": "70-79y" - }, - { - "code": "+80y", - "label": "+80y" - } - ], - "label": "Age Group", - "methodology": "mip-cde", - "type": "polynominal" - }, - { - "code": "gender", - "description": "Gender of the patient - Sex assigned at birth", - "enumerations": [ - { - "code": "M", - "label": "Male" - }, - { - "code": "F", - "label": "Female" - } - ], - "label": "Gender", - "length": 1, - "methodology": "mip-cde", - "type": "binominal" - }, - { - "code": "handedness", - "description": "Describes the tendency of the patient to use either the right or the left hand more naturally than the other.", - "enumerations": [ - { - "code": "R", - "label": "Right" - }, - { - "code": "L", - "label": "Left" - }, - { - "code": "A", - "label": "Ambidextrous" - } - ], - "label": "Handedness", - "length": 1, - "methodology": "mip-cde", - "type": "polynominal" - } - ] - }, - { - "code": "neuropsychology", - "groups": [ - { - "code": "updrs", - "label": "UPDRS", - "variables": [ - { - "code": "updrstotal", - "description": "The unified Parkinson''s disease rating scale (UPDRS) is used to follow the longitudinal course of Parkinson''s disease. The UPD rating scale is the most commonly used scale in the clinical study of Parkinson''s disease.", - "label": "UPDRS - Unified Parkinson Disease Rating Scale", - "maxValue": 172, - "methodology": "mip-cde", - "minValue": 0, - "type": "integer" - }, - { - "code": "updrshy", - "description": "The Hoehn and Yahr scale (HY) is a widely used clinical rating scale, which defines broad categories of motor function in Parkinson''s disease (PD). It captures typical patterns of progressive motor impairment.", - "label": "UPDRS HY - Hoehn and Yahr scale", - "maxValue": 5, - "methodology": "mip-cde", - "minValue": 0, - "type": "integer" - } - ] - } - ], - "label": "Neuropsychology", - "variables": [ - { - "code": "minimentalstate", - "description": "The Mini-Mental State Examination (MMSE) or Folstein test is a 30-point questionnaire that is used extensively in clinical and research settings to measure cognitive impairment. It is commonly used to screen for dementia.", - "label": "MMSE - Mini Mental State Examination", - "maxValue": 30, - "methodology": "mip-cde", - "minValue": 0, - "type": "integer" - }, - { - "code": "montrealcognitiveassessment", - "description": "The Montreal Cognitive Assessment (MoCA) was designed as a rapid screening instrument for mild cognitive dysfunction. It assesses different cognitive domains: attention and concentration, executive functions, memory, language, visuoconstructional skills, conceptual thinking, calculations, and orientation. MoCA Total Scores refer to the final count obtained by patients after the complete test is performed.", - "label": "MoCA - Montreal Cognitive Assessment", - "maxValue": 30, - "methodology": "mip-cde", - "minValue": 0, - "type": "integer" - } - ] - }, - { - "code": "diagnosis", - "groups": [ - { - "code": "dataset_specific_diagnosis", - "label": "Dataset Specific Diagnosis", - "variables": [ - { - "code": "adnicategory", - "description": "Terms aggregating illnesses into classes. Note that the diagnosis in this categories are given only for the ADNI data set.", - "enumerations": [ - { - "code": "AD", - "label": "Alzheimer''s Disease" - }, - { - "code": "MCI", - "label": "Mild Cognitive Impairment" - }, - { - "code": "CN", - "label": "Cognitively Normal" - } - ], - "label": "ADNI category", - "methodology": "mip-cde", - "type": "polynominal" - }, - { - "code": "edsdcategory", - "description": "Terms aggregating illnesses into classes. Note that the diagnosis in this categories are given only for the EDSD data set.", - "enumerations": [ - { - "code": "AD", - "label": "Alzheimer''s Disease" - }, - { - "code": "MCI", - "label": "Mild Cognitive Impairment" - }, - { - "code": "CN", - "label": "Cognitively Normal" - } - ], - "label": "EDSD category", - "methodology": "mip-cde", - "type": "polynominal" - }, - { - "code": "ppmicategory", - "description": "Terms aggregating the Parkinson''s diseases into classes. For this instance the diagnosis given at enrollment is taken as the clinical diagnosis. Note that the diagnosis in this categories are given only for the PPMI data set.", - "enumerations": [ - { - "code": "PD", - "label": "Parkinson disease" - }, - { - "code": "HC", - "label": "Healthy controls" - }, - { - "code": "PRODROMA", - "label": "Prodromal" - }, - { - "code": "GENPD", - "label": "Genetic PD patients with a mutation (LRRK2, GBA or SNCA)" - }, - { - "code": "REGUN", - "label": "Genetic Unaffected patients with a mutation (LRRK2, GBA or SNCA)" - }, - { - "code": "REGPD", - "label": "Genetic registry PD subjects with a mutation (LRRK2, GBA, or SNCA)" - }, - { - "code": "REGUN", - "label": "Genetic registry unaffected subjects with a mutation (LRRK2, GBA, or SNCA)" - } - ], - "label": "PPMI category", - "methodology": "mip-cde", - "type": "polynominal" - } - ] - } - ], - "label": "Diagnosis", - "variables": [ - { - "code": "alzheimerbroadcategory", - "description": "There will be two broad categories taken into account. Alzheimer''s disease (AD) in which the diagnostic is 100% certain and \"Other\" comprising the rest of Alzheimer''s related categories. The \"Other\" category refers to Alzheimer''s related diagnosis which origin can be traced to other pathology eg. vascular. In this category MCI diagnosis can also be found. In summary, all Alzheimer''s related diagnosis that are not pure.", - "enumerations": [ - { - "code": "AD", - "label": "Alzheimer''s disease" - }, - { - "code": "CN", - "label": "Cognitively Normal" - }, - { - "code": "Other", - "label": "Other" - }, - { - "code": "MCI", - "label": "Mild cognitive impairment" - } - ], - "label": "Alzheimer Broad Category", - "methodology": "mip-cde", - "type": "polynominal" - }, - { - "code": "parkinsonbroadcategory", - "description": "There will be two broad categories taken into account. Parkinson''s disease without disability or light disability: Without fluctuation of the effect. Dementia in Parkinson''s disease", - "enumerations": [ - { - "code": "PD", - "label": "Dementia in Parkinson''s disease" - }, - { - "code": "CN", - "label": "Healthy control" - }, - { - "code": "Other", - "label": "Parkinson''s disease without disability or light disability: Without fluctuation of the effect" - } - ], - "label": "Parkinson Broad Category", - "methodology": "mip-cde", - "type": "polynominal" - }, - { - "code": "neurodegenerativescategories", - "description": "There will be two broad categories taken into account. Parkinson''s disease without disability or light disability: Without fluctuation of the effect. Dementia in Parkinson''s disease", - "enumerations": [ - { - "code": "PD", - "label": "Parkinson''s disease" - }, - { - "code": "AD", - "label": "Alzheimer''s disease" - }, - { - "code": "HD", - "label": "Huntington''s disease" - }, - { - "code": "ALS", - "label": "Amyotrophic lateral sclerosis" - }, - { - "code": "BD", - "label": "Batten disease" - }, - { - "code": "MCI", - "label": "MCI" - }, - { - "code": "LBD", - "label": "Lewy body dementia" - }, - { - "code": "CJD", - "label": "Creutzfeldt\u2013Jakob disease" - }, - { - "code": "FTD", - "label": "Frontotemporal dementia" - }, - { - "code": "MS", - "label": "Multiple sclerosis" - }, - { - "code": "CN", - "label": "Cognitively normal" - } - ], - "label": "Neurodegeneratives categories", - "methodology": "mip-cde", - "type": "polynominal" - } - ] - } - ], - "variables": [] - } - }, - { - "code": "tbi", - "hierarchy": { - "code": "root", - "label": "/", - "groups": [], - "variables": [ - { - "code": "gcsonadmission_eyes", - "enumerations": [ - { - "code": "1", - "label": "None (1)" - }, - { - "code": "2", - "label": "To pain (2)" - }, - { - "code": "3", - "label": "To speech (3)" - }, - { - "code": "4", - "label": "Spontaneously (4)" - }, - { - "code": "notEvaluable", - "label": "Not Evaluable" - } - ], - "label": "GCS: Best eyes response", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "gcsonadmission_motor", - "enumerations": [ - { - "code": "1", - "label": "None (1)" - }, - { - "code": "2", - "label": "Extension to pain (2)" - }, - { - "code": "3", - "label": "Flexion (abnormal) to pain (3)" - }, - { - "code": "4", - "label": "Withdraws to pain (4)" - }, - { - "code": "5", - "label": "Localizes pain (5)" - }, - { - "code": "6", - "label": "Obeys commands (6)" - }, - { - "code": "notEvaluable", - "label": "Not Evaluable" - } - ], - "label": "GCS: Best motor response", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "gcsonadmission_verbal", - "enumerations": [ - { - "code": "1", - "label": "None (1)" - }, - { - "code": "2", - "label": "Incomprehensible sounds (2)" - }, - { - "code": "3", - "label": "Inappropriate words (3)" - }, - { - "code": "4", - "label": "Confused (4)" - }, - { - "code": "5", - "label": "Orientated (5)" - }, - { - "code": "notEvaluable", - "label": "Not Evaluable" - } - ], - "label": "GCS Best verbal response", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "gcsonadmission", - "enumerations": [ - { - "code": "notEvaluable", - "label": "not Evaluable" - }, - { - "code": "1", - "label": "1" - }, - { - "code": "2", - "label": "2" - }, - { - "code": "3", - "label": "3" - }, - { - "code": "4", - "label": "4" - }, - { - "code": "5", - "label": "5" - }, - { - "code": "6", - "label": "6" - }, - { - "code": "7", - "label": "7" - }, - { - "code": "8", - "label": "8" - }, - { - "code": "9", - "label": "9" - }, - { - "code": "10", - "label": "10" - }, - { - "code": "11", - "label": "11" - }, - { - "code": "12", - "label": "12" - }, - { - "code": "13", - "label": "13" - }, - { - "code": "14", - "label": "14" - }, - { - "code": "15", - "label": "15" - } - ], - "label": "GCS total score", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "pupilsonadmission", - "enumerations": [ - { - "code": "notEvaluable", - "label": "not Evaluable" - }, - { - "code": "BiDiallPupil", - "label": "Bilaterally dilated and non-reactive" - }, - { - "code": "UniDiallPupil", - "label": "Unilaterally dilated and non-reactive" - }, - { - "code": "bilalPupil", - "label": "Reattive bilateralmente e/o miotiche" - } - ], - "label": "Pupils on admission", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "extracranialtrauma", - "label": "Extracranial Trauma", - "methodology": "creactive", - "sql_type": "int", - "type": "integer" - }, - { - "code": "petechiae", - "enumerations": [ - { - "code": "No", - "label": "No" - }, - { - "code": "Yes", - "label": "Yes" - } - ], - "label": "Petechiae", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "cistern", - "enumerations": [ - { - "code": "Normal", - "label": "Normal" - }, - { - "code": "Absent", - "label": "Absent" - }, - { - "code": "Compressed/Distorted", - "label": "Compressed/Distorted" - } - ], - "label": "Cistern", - "methodology": "creactive", - "toolTip": "Le cisterne perimesencefaliche sono gli spazi liquorali che circondano il mesencefalo.", - "type": "polynominal" - }, - { - "code": "shift", - "enumerations": [ - { - "code": "No", - "label": "No" - }, - { - "code": "Yes", - "label": "Yes" - } - ], - "label": "shift", - "methodology": "creactive", - "toolTip": "Midline shift refers to a the shift of the brain past the imaginary centre line dividing the brain into its two hemispheres.", - "type": "polynominal" - }, - { - "code": "marshall", - "enumerations": [ - { - "code": "I", - "label": "(D-I) Diffuse injury I" - }, - { - "code": "II", - "label": "(D-II) Diffuse injury II" - }, - { - "code": "III", - "label": "(D-III) Diffuse injury III" - }, - { - "code": "IV", - "label": "(D-IV) Diffuse injury IV" - }, - { - "code": "V", - "label": "(5-EML) Evacuated mass lesion" - }, - { - "code": "VI", - "label": "(6-NEML) Not Evacuated mass lesion" - } - ], - "label": "Marshall", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "notevacuatedhematoma", - "enumerations": [ - { - "code": "No", - "label": "No" - }, - { - "code": "Yes", - "label": "Yes" - } - ], - "label": "Not Evacuated Hematoma", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "traumaticsubarachnoidhemorr", - "enumerations": [ - { - "code": "No", - "label": "No" - }, - { - "code": "Yes", - "label": "Yes" - } - ], - "label": "Traumatic subarachnoid haemorrhage", - "methodology": "creactive", - "toolTip": "tSAH is blood distributed in the subarachnoid space. Its location can be very limited for example in the interpeduncular space or over the tentorium. Otherwise it can be found in the cortical sulcus or on the brain vault.", - "type": "polynominal" - }, - { - "code": "epiduralhematoma", - "enumerations": [ - { - "code": "No", - "label": "No" - }, - { - "code": "Yes", - "label": "Yes" - } - ], - "label": "Epidural Hematoma", - "methodology": "creactive", - "toolTip": "Collection of blood between the dura mater and cranial theca, caused by fractures that can injure the middle meningeal artery or one of its branches. It may be associated with intracranial hypertension and cause coma, usually after a lucid interval. If promptly operated the prognosis is favourable.", - "type": "polynominal" - }, - { - "code": "hypoxia", - "enumerations": [ - { - "code": "No", - "label": "No" - }, - { - "code": "Yes", - "label": "Yes" - }, - { - "code": "NotAvailable", - "label": "Not Available" - } - ], - "label": "Hypoxia", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "hypotension", - "enumerations": [ - { - "code": "NotAvailable", - "label": "Not Available" - }, - { - "code": "No", - "label": "No" - }, - { - "code": "Yes", - "label": "Yes" - } - ], - "label": "Hypotension", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "glucose", - "label": "Blood glucose at ER (mg/dl)", - "methodology": "creactive", - "toolTip": "The first blood glucose value before ICU admission", - "type": "real" - }, - { - "code": "hb", - "label": "Hemoglobin ER (gr/dl)", - "methodology": "creactive", - "toolTip": "The lowest hemoglobin value available before ICU admission", - "type": "real" - }, - { - "code": "gose", - "enumerations": [ - { - "code": "ModerateDisabUpper", - "label": "Moderate disability UPPER LEVEL" - }, - { - "code": "ModerateDisabLower", - "label": "Moderate disability LOWER LEVEL" - }, - { - "code": "Vegetative", - "label": "Vegetative state" - }, - { - "code": "Deceased", - "label": "Deceased" - }, - { - "code": "GoodRecoveryUpper", - "label": "Good recovery UPPER LEVEL" - }, - { - "code": "SevereDisabLower", - "label": "Severe disability LOWER LEVEL" - }, - { - "code": "GoodRecoveryLower", - "label": "Good recovery LOWER LEVEL" - }, - { - "code": "SevereDisabUpper", - "label": "Severe disability UPPER LEVEL" - } - ], - "label": "Glasgow Outcome Scale Extended", - "methodology": "creactive", - "type": "polynominal" - }, - { - "code": "impact_prob_core_mortality", - "label": "Temporary Impact Probability", - "methodology": "creactive", - "type": "real" - }, - { - "code": "Mortality", - "label": "Six Month Mortality", - "methodology": "creactive", - "sql_type": "int", - "type": "integer" - } - ] - }, - - "label": "Traumatic brain injury", - "datasets": [ - { - "code": "nida", - "label": "NIDA" - }, - { - "code": "mipp", - "label": "MIPP" - }, - { - "code": "sded", - "label": "SDED" - } - ] - } - ] - \ No newline at end of file diff --git a/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java index 8addb863..093a735e 100644 --- a/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java +++ b/src/main/java/eu/hbp/mip/controllers/AlgorithmsAPI.java @@ -32,9 +32,9 @@ public AlgorithmsAPI(ActiveUserService activeUserService, AlgorithmService algor public ResponseEntity> getAlgorithms() { Logger logger = new Logger(activeUserService.getActiveUser().getUsername(), "(GET) /algorithms"); logger.LogUserAction("Executing..."); - List allowedAlgorithms = algorithmService.getAlgorithms(logger); + List algorithms = algorithmService.getAlgorithms(); - logger.LogUserAction("Successfully listed " + allowedAlgorithms.size() + " algorithms"); - return ResponseEntity.ok(allowedAlgorithms); + logger.LogUserAction("Successfully listed " + algorithms.size() + " algorithms"); + return ResponseEntity.ok(algorithms); } } diff --git a/src/main/java/eu/hbp/mip/services/AlgorithmService.java b/src/main/java/eu/hbp/mip/services/AlgorithmService.java index 5388b8d5..bfc2b7c7 100644 --- a/src/main/java/eu/hbp/mip/services/AlgorithmService.java +++ b/src/main/java/eu/hbp/mip/services/AlgorithmService.java @@ -17,6 +17,10 @@ import eu.hbp.mip.utils.Logger; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import retrofit2.Call; import retrofit2.Response; @@ -26,16 +30,13 @@ import static eu.hbp.mip.utils.InputStreamConverter.convertInputStreamToString; +@EnableScheduling @Service public class AlgorithmService { private static final Gson gson = new Gson(); - private long algorithmsUpdated = 0; - private List algorithmDTOS = new ArrayList<>(); - - @Value("#{'${services.algorithmsUpdateInterval}'}") - private int algorithmsUpdateInterval; + private ArrayList algorithmDTOS = new ArrayList<>(); @Value("#{'${services.mipengine.algorithmsUrl}'}") private String mipengineAlgorithmsUrl; @@ -55,8 +56,12 @@ public class AlgorithmService { public AlgorithmService(CustomResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } + public ArrayList getAlgorithms() { + + return this.algorithmDTOS; + } - public ArrayList getAlgorithms(Logger logger) { + public void update(Logger logger) { ArrayList mipengineAlgorithms = getMIPEngineAlgorithms(logger); ArrayList exaremeAlgorithms = getExaremeAlgorithms(logger); ArrayList galaxyAlgorithms = getGalaxyWorkflows(logger); @@ -107,27 +112,37 @@ public ArrayList getAlgorithms(Logger logger) { } } - logger.LogUserAction("Removed "+ (algorithms.size() - allowedAlgorithms.size()) +" disabled algorithms"); + int algorithmsRemoved = algorithms.size() - allowedAlgorithms.size(); + if (algorithmsRemoved > 0){ + logger.LogUserAction("Removed "+ (algorithmsRemoved) +" disabled algorithms"); + } - this.algorithmsUpdated = System.currentTimeMillis(); this.algorithmDTOS = allowedAlgorithms; - - return allowedAlgorithms; } - private boolean areAlgorithmsOutDated (){ - if (this.algorithmsUpdated == 0) return true; - return (int)((System.currentTimeMillis() - this.algorithmsUpdated) / 1000) > algorithmsUpdateInterval; + + @EnableAsync + public static class AlgorithmAggregator { + + private final AlgorithmService algorithmService; + + public AlgorithmAggregator(AlgorithmService algorithmService){ + this.algorithmService = algorithmService; + } + @Async + @Scheduled(fixedDelayString = "${services.algorithmsUpdateInterval}000") + public void scheduleFixedRateTaskAsync() throws InterruptedException { + algorithmService.update(new Logger("AlgorithmAggregator","(GET) /algorithms")); + } } - public String getEngineName(Logger logger, String algorithmName){ - if(areAlgorithmsOutDated()) getAlgorithms(logger); + public String getAlgorithmEngineType(String algorithmName){ Optional exaremeAlgorithmDTO = this.algorithmDTOS.stream().filter(algorithmDTO -> algorithmDTO.getName().equals(algorithmName)).findAny(); - if (exaremeAlgorithmDTO.isPresent()) return getEngineNameForSpecificAlgorithm(exaremeAlgorithmDTO.get()); + if (exaremeAlgorithmDTO.isPresent()) return getAlgorithmEngineType(exaremeAlgorithmDTO.get()); else throw new BadRequestException("Algorithm: " + algorithmName + " does not exist."); } - private String getEngineNameForSpecificAlgorithm(ExaremeAlgorithmDTO algorithmDTO){ + private String getAlgorithmEngineType(ExaremeAlgorithmDTO algorithmDTO){ switch (algorithmDTO.getType()) { case "mipengine": return "MIP-Engine"; diff --git a/src/main/java/eu/hbp/mip/services/ExperimentService.java b/src/main/java/eu/hbp/mip/services/ExperimentService.java index 5aa6b09c..b7e88d26 100644 --- a/src/main/java/eu/hbp/mip/services/ExperimentService.java +++ b/src/main/java/eu/hbp/mip/services/ExperimentService.java @@ -156,8 +156,8 @@ public ExperimentDTO createExperiment(Authentication authentication, ExperimentD // Get the engine name from algorithmService - String engineName = algorithmService.getEngineName(logger, experimentDTO.getAlgorithm().getName().toUpperCase()); - logger.LogUserAction("Algorithm runs on " + engineName + "."); + String algorithmEngineName = algorithmService.getAlgorithmEngineType(experimentDTO.getAlgorithm().getName().toUpperCase()); + logger.LogUserAction("Algorithm runs on " + algorithmEngineName + "."); algorithmParametersLogging(experimentDTO, logger); @@ -167,10 +167,10 @@ public ExperimentDTO createExperiment(Authentication authentication, ExperimentD } // Run with the appropriate engine - if (engineName.equals("Galaxy")) { + if (algorithmEngineName.equals("Galaxy")) { return galaxyService.createGalaxyExperiment(experimentDTO, logger); } else { - return createSynchronousExperiment(experimentDTO, engineName, logger); + return createSynchronousExperiment(experimentDTO, algorithmEngineName, logger); } } @@ -188,12 +188,12 @@ public ExperimentDTO runTransientExperiment(Authentication authentication, Exper checkPostExperimentProperInput(experimentDTO, logger); // Get the engine name from algorithmService - String engineName = algorithmService.getEngineName(logger, experimentDTO.getAlgorithm().getName().toUpperCase()); + String algorithmEngineName = algorithmService.getAlgorithmEngineType(experimentDTO.getAlgorithm().getName().toUpperCase()); experimentDTO.setUuid(UUID.randomUUID()); - if (engineName.equals("Galaxy")) { + if (algorithmEngineName.equals("Galaxy")) { logger.LogUserAction("You can not run workflow algorithms transiently."); throw new BadRequestException("You can not run workflow algorithms transiently."); } @@ -207,7 +207,7 @@ public ExperimentDTO runTransientExperiment(Authentication authentication, Exper logger.LogUserAction("Completed, returning: " + experimentDTO); - ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(experimentDTO, engineName, logger); + ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(experimentDTO, algorithmEngineName, logger); logger.LogUserAction( "Experiment with uuid: " + experimentDTO.getUuid() @@ -398,7 +398,7 @@ private String getDatasetFromExperimentParameters(ExperimentDTO experimentDTO, L * @param logger contains username and the endpoint. * @return the experiment information that was retrieved from exareme */ - private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, String engineName, Logger logger) { + private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, String algorithmEngineName, Logger logger) { logger.LogUserAction("Running the algorithm..."); @@ -411,7 +411,7 @@ private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, S new Thread(() -> { try { - ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(finalExperimentDTO, engineName, logger); + ExaremeAlgorithmResultDTO exaremeAlgorithmResultDTO = runSynchronousExperiment(finalExperimentDTO, algorithmEngineName, logger); logger.LogUserAction( "Experiment with uuid: " + experimentDAO.getUuid() @@ -442,8 +442,8 @@ private ExperimentDTO createSynchronousExperiment(ExperimentDTO experimentDTO, S * @param experimentDTO is the request with the experiment information * @return the result of experiment as well as the http status that was retrieved */ - private ExaremeAlgorithmResultDTO runSynchronousExperiment(ExperimentDTO experimentDTO, String engineName, Logger logger) { - if (engineName.equals("MIP-Engine")) { + private ExaremeAlgorithmResultDTO runSynchronousExperiment(ExperimentDTO experimentDTO, String algorithmEngineName, Logger logger) { + if (algorithmEngineName.equals("MIP-Engine")) { return runMIPEngineExperiment(experimentDTO, logger); } else { return runExaremeExperiment(experimentDTO, logger); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 07f86b5d..6d59ce9c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -34,7 +34,7 @@ spring: ### EXTERNAL SERVICES ### services: - algorithmsUpdateInterval: 10 + algorithmsUpdateInterval: 100 mipengine: algorithmsUrl: "http://127.0.0.1:5000/algorithms" attributesUrl: "http://127.0.0.1:5000/data_models_attributes" @@ -66,7 +66,6 @@ keycloak: ### EXTERNAL FILES ### # Files are loaded from the resources files: - pathologies_json: "classPath:/pathologies.json" disabledAlgorithms_json: "classPath:/disabledAlgorithms.json"