package org.ohdsi.webapi.service; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.PostConstruct; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.apache.commons.collections.CollectionUtils; import org.ohdsi.sql.SqlRender; import org.ohdsi.sql.SqlTranslate; import org.ohdsi.webapi.cohortanalysis.CohortAnalysis; import org.ohdsi.webapi.cohortanalysis.CohortAnalysisTask; import org.ohdsi.webapi.cohortanalysis.CohortSummary; import org.ohdsi.webapi.cohortresults.CohortBreakdown; import org.ohdsi.webapi.cohortresults.CohortConditionDrilldown; import org.ohdsi.webapi.cohortresults.CohortConditionEraDrilldown; import org.ohdsi.webapi.cohortresults.CohortDashboard; import org.ohdsi.webapi.cohortresults.CohortDataDensity; import org.ohdsi.webapi.cohortresults.CohortDeathData; import org.ohdsi.webapi.cohortresults.CohortDrugDrilldown; import org.ohdsi.webapi.cohortresults.CohortDrugEraDrilldown; import org.ohdsi.webapi.cohortresults.CohortMeasurementDrilldown; import org.ohdsi.webapi.cohortresults.CohortObservationDrilldown; import org.ohdsi.webapi.cohortresults.CohortObservationPeriod; import org.ohdsi.webapi.cohortresults.CohortPersonSummary; import org.ohdsi.webapi.cohortresults.CohortProceduresDrillDown; import org.ohdsi.webapi.cohortresults.CohortResultsAnalysisRunner; import org.ohdsi.webapi.cohortresults.CohortSpecificSummary; import org.ohdsi.webapi.cohortresults.CohortSpecificTreemap; import org.ohdsi.webapi.cohortresults.CohortVisitsDrilldown; import org.ohdsi.webapi.cohortresults.HierarchicalConceptRecord; import org.ohdsi.webapi.cohortresults.ScatterplotRecord; import org.ohdsi.webapi.cohortresults.VisualizationData; import org.ohdsi.webapi.cohortresults.VisualizationDataRepository; import org.ohdsi.webapi.helper.ResourceHelper; import org.ohdsi.webapi.model.results.Analysis; import org.ohdsi.webapi.source.Source; import org.ohdsi.webapi.source.SourceDaimon; import org.ohdsi.webapi.util.SessionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.sql.ResultSetMetaData; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.ws.rs.core.Response; import org.ohdsi.webapi.cohortresults.ExposureCohortResult; import org.ohdsi.webapi.cohortresults.ExposureCohortSearch; import org.ohdsi.webapi.cohortresults.PredictorResult; import org.ohdsi.webapi.cohortresults.TimeToEventResult; import org.ohdsi.webapi.person.CohortPerson; import org.ohdsi.webapi.service.CohortDefinitionService.CohortDefinitionDTO; /** * * Services related to cohort level analysis results * */ @Path("/cohortresults") @Component public class CohortResultsService extends AbstractDaoService { public static final String MIN_COVARIATE_PERSON_COUNT = "10"; public static final String MIN_INTERVAL_PERSON_COUNT = "10"; public static final String BASE_SQL_PATH = "/resources/cohortresults/sql"; @Autowired private VisualizationDataRepository visualizationDataRepository; @Autowired private CohortDefinitionService cohortDefinitionService; private ObjectMapper mapper = new ObjectMapper(); private CohortResultsAnalysisRunner queryRunner = null; @PostConstruct public void init() { queryRunner = new CohortResultsAnalysisRunner(this.getSourceDialect(), this.visualizationDataRepository); } /** * Queries for cohort analysis results for the given cohort definition id * * @param id cohort_defintion id * @param analysisGroup Name of the analysisGrouping under the * /resources/cohortresults/sql/ directory * @param analysisName Name of the analysis, currently the same name as the * sql file under analysisGroup * @param sourceKey the source to retrieve results * @return List of key, value pairs */ @GET @Path("{sourceKey}/{id}/raw/{analysis_group}/{analysis_name}") @Produces(MediaType.APPLICATION_JSON) public List<Map<String, String>> getCohortResultsRaw(@PathParam("id") final int id, @PathParam("analysis_group") final String analysisGroup, @PathParam("analysis_name") final String analysisName, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") String sourceKey) { List<Map<String, String>> results = null; String sql = null; Source source = getSourceRepository().findBySourceKey(sourceKey); String vocabularyTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Vocabulary); String resultsTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); try { sql = ResourceHelper.GetResourceAsString(BASE_SQL_PATH + "/" + analysisGroup + "/" + analysisName + ".sql"); sql = SqlRender.renderSql(sql, new String[]{"cdm_database_schema", "ohdsi_database_schema", "cohortDefinitionId", "minCovariatePersonCount", "minIntervalPersonCount"}, new String[]{vocabularyTableQualifier, resultsTableQualifier, String.valueOf(id), minCovariatePersonCountParam == null ? MIN_COVARIATE_PERSON_COUNT : minCovariatePersonCountParam, minIntervalPersonCountParam == null ? MIN_INTERVAL_PERSON_COUNT : minIntervalPersonCountParam}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect()); } catch (Exception e) { log.error(String.format("Unable to translate sql for analysis %s", analysisName), e); } if (sql != null) { results = genericResultSetLoader(sql, source); } return results; } @GET @Path("{sourceKey}/{id}/export.zip") @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response exportCohortResults(@PathParam("id") int id, @PathParam("sourceKey") String sourceKey) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos); try { Source source = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); String sql = null; final StringBuilder resultData = new StringBuilder(); final StringBuilder resultDistributionData = new StringBuilder(); // results export sql = ResourceHelper.GetResourceAsString(BASE_SQL_PATH + "/raw/getAllResults.sql"); sql = SqlRender.renderSql(sql, new String[]{"tableQualifier", "cohortDefinitionId"}, new String[]{resultsTableQualifier, String.valueOf(id)}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect()); getSourceJdbcTemplate(source).query(sql, new RowMapper<Void>() { @Override public Void mapRow(ResultSet rs, int arg1) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); int colCount = metaData.getColumnCount(); for (int i = 1; i <= colCount; i++) { if (i > 1) { resultData.append("\t"); } resultData.append(String.valueOf(rs.getObject(i))); } resultData.append("\r\n"); return null; } }); ZipEntry resultsEntry = new ZipEntry("cohort_" + String.valueOf(id) + "_results.tsv"); zos.putNextEntry(resultsEntry); zos.write(resultData.toString().getBytes()); zos.closeEntry(); // result distribution export sql = ResourceHelper.GetResourceAsString(BASE_SQL_PATH + "/raw/getAllResultDistributions.sql"); sql = SqlRender.renderSql(sql, new String[]{"tableQualifier", "cohortDefinitionId"}, new String[]{resultsTableQualifier, String.valueOf(id)}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect()); getSourceJdbcTemplate(source).query(sql, new RowMapper<Void>() { @Override public Void mapRow(ResultSet rs, int arg1) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); int colCount = metaData.getColumnCount(); for (int i = 1; i <= colCount; i++) { if (i > 1) { resultDistributionData.append("\t"); } resultDistributionData.append(String.valueOf(rs.getObject(i))); } resultDistributionData.append("\r\n"); return null; } }); ZipEntry resultsDistEntry = new ZipEntry("cohort_" + String.valueOf(id) + "_results_dist.tsv"); zos.putNextEntry(resultsDistEntry); zos.write(resultDistributionData.toString().getBytes()); zos.closeEntry(); // include cohort definition in export CohortDefinitionDTO cohortDefinition = cohortDefinitionService.getCohortDefinition(id); ByteArrayOutputStream cohortDefinitionStream = new ByteArrayOutputStream(); mapper.writeValue(cohortDefinitionStream, cohortDefinition); cohortDefinitionStream.flush(); ZipEntry cohortDefinitionEntry = new ZipEntry("cohort_" + String.valueOf(id) + "_definition.json"); zos.putNextEntry(cohortDefinitionEntry); zos.write(cohortDefinitionStream.toByteArray()); zos.closeEntry(); zos.close(); baos.flush(); baos.close(); } catch (Exception ex) { throw new RuntimeException(ex); } Response response = Response .ok(baos) .type(MediaType.APPLICATION_OCTET_STREAM) .build(); return response; } @POST @Path("{id}/warmup") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public int warmUpVisualizationData(CohortAnalysisTask task) { return this.queryRunner.warmupData(this.getSourceJdbcTemplate(task.getSource()), task); } @GET @Path("{sourceKey}/{id}/completed") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Collection<String> getCompletedVisualiztion(@PathParam("id") final int id, @PathParam("sourceKey") final String sourceKey) { Source source = getSourceRepository().findBySourceKey(sourceKey); List<VisualizationData> vizData = this.visualizationDataRepository.findByCohortDefinitionIdAndSourceId(id, source.getSourceId()); Set<String> completed = new HashSet<String>(); if (CollectionUtils.isNotEmpty(vizData)) { for (VisualizationData viz : vizData) { completed.add(viz.getVisualizationKey()); } } return completed; } /** * Queries for cohort analysis dashboard for the given cohort definition id * * @param id cohort_defintion id * @param minCovariatePersonCountParam * @param minIntervalPersonCountParam * @param demographicsOnly only render gender and age * @return CohortDashboard */ @GET @Path("{sourceKey}/{id}/dashboard") @Produces(MediaType.APPLICATION_JSON) public CohortDashboard getDashboard(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @QueryParam("demographics_only") final boolean demographicsOnly, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { final String key = CohortResultsAnalysisRunner.DASHBOARD; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); CohortDashboard dashboard = null; if (refresh || data == null) { dashboard = queryRunner.getDashboard(getSourceJdbcTemplate(source), id, source, minCovariatePersonCountParam, minIntervalPersonCountParam, demographicsOnly, true); } else { try { dashboard = mapper.readValue(data.getData(), CohortDashboard.class); } catch (Exception e) { log.error(e); } } return dashboard; } /** * Queries for cohort analysis condition treemap results for the given cohort * definition id * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/condition/") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getConditionTreemap(@PathParam("sourceKey") String sourceKey, @PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.CONDITION; List<HierarchicalConceptRecord> res = null; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { res = this.queryRunner.getConditionTreemap(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } @GET @Path("{sourceKey}/{id}/distinctPersonCount/") @Produces(MediaType.APPLICATION_JSON) public Integer getRawDistinctPersonCount(@PathParam("sourceKey") String sourceKey, @PathParam("id") String id, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { Source source = getSourceRepository().findBySourceKey(sourceKey); String tableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); String sql = ResourceHelper.GetResourceAsString(BASE_SQL_PATH + "/raw/getTotalDistinctPeople.sql"); sql = SqlRender.renderSql(sql, new String[]{"tableQualifier", "id"}, new String[]{tableQualifier, id}); sql = SqlTranslate.translateSql(sql, "sql server", source.getSourceDialect()); Integer result = getSourceJdbcTemplate(source).queryForObject(sql, Integer.class); return result; } /** * Queries for cohort analysis condition drilldown results for the given * cohort definition id and condition id * * @param id cohort_defintion id * @param conditionId condition_id (from concept) * @return CohortConditionDrilldown */ @GET @Path("{sourceKey}/{id}/condition/{conditionId}") @Produces(MediaType.APPLICATION_JSON) public CohortConditionDrilldown getConditionResults(@PathParam("sourceKey") String sourceKey, @PathParam("id") final int id, @PathParam("conditionId") final int conditionId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortConditionDrilldown drilldown = null; final String key = CohortResultsAnalysisRunner.CONDITION_DRILLDOWN; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conditionId); if (refresh || data == null) { drilldown = this.queryRunner.getConditionResults(this.getSourceJdbcTemplate(source), id, conditionId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortConditionDrilldown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Queries for cohort analysis condition era treemap results for the given * cohort definition id * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/conditionera/") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getConditionEraTreemap(@PathParam("sourceKey") final String sourceKey, @PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.CONDITION_ERA; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); List<HierarchicalConceptRecord> res = null; if (data == null || refresh) { res = this.queryRunner.getConditionEraTreemap(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } @GET @Path("{sourceKey}/{id}/analyses") @Produces(MediaType.APPLICATION_JSON) public List<Integer> getCompletedAnalyses(@PathParam("sourceKey") String sourceKey, @PathParam("id") String id) { Source source = getSourceRepository().findBySourceKey(sourceKey); String tableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); String sql = ResourceHelper.GetResourceAsString(BASE_SQL_PATH + "/raw/getCompletedAnalyses.sql"); sql = SqlRender.renderSql(sql, new String[]{"tableQualifier", "id"}, new String[]{tableQualifier, id}); sql = SqlTranslate.translateSql(sql, "sql server", source.getSourceDialect()); return getSourceJdbcTemplate(source).queryForList(sql, Integer.class); } /** * Queries for cohort analysis condition era drilldown results for the given * cohort definition id and condition id * * @param id cohort_defintion id * @param conditionId condition_id (from concept) * @return CohortConditionEraDrilldown */ @GET @Path("{sourceKey}/{id}/conditionera/{conditionId}") @Produces(MediaType.APPLICATION_JSON) public CohortConditionEraDrilldown getConditionEraDrilldown(@PathParam("id") final int id, @PathParam("conditionId") final int conditionId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortConditionEraDrilldown drilldown = null; final String key = CohortResultsAnalysisRunner.CONDITION_ERA_DRILLDOWN; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository .findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conditionId); if (refresh || data == null) { drilldown = this.queryRunner.getConditionEraDrilldown(this.getSourceJdbcTemplate(source), id, conditionId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortConditionEraDrilldown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Queries for drug analysis condition treemap results for the given cohort * definition id * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/drug/") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getDrugTreemap(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.DRUG; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); List<HierarchicalConceptRecord> res = null; if (refresh || data == null) { res = this.queryRunner.getDrugTreemap(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } /** * Queries for cohort analysis drug drilldown results for the given cohort * definition id and condition id * * @param id cohort_defintion id * @param drugId drug_id (from concept) * @return CohortDrugDrilldown */ @GET @Path("{sourceKey}/{id}/drug/{drugId}") @Produces(MediaType.APPLICATION_JSON) public CohortDrugDrilldown getDrugResults(@PathParam("id") final int id, @PathParam("drugId") final int drugId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortDrugDrilldown drilldown = null; final String key = CohortResultsAnalysisRunner.DRUG_DRILLDOWN; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, drugId); if (refresh || data == null) { drilldown = this.queryRunner.getDrugResults(this.getSourceJdbcTemplate(source), id, drugId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortDrugDrilldown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Queries for cohort analysis drug era treemap results for the given cohort * definition id * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/drugera/") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getDrugEraTreemap(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { Source source = getSourceRepository().findBySourceKey(sourceKey); List<HierarchicalConceptRecord> res = null; final String key = CohortResultsAnalysisRunner.DRUG_ERA; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { res = this.queryRunner.getDrugEraTreemap(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } /** * Queries for cohort analysis drug era drilldown results for the given cohort * definition id and condition id * * @param id cohort_defintion id * @param drugId drug_id (from concept) * @return CohortDrugEraDrilldown */ @GET @Path("{sourceKey}/{id}/drugera/{drugId}") @Produces(MediaType.APPLICATION_JSON) public CohortDrugEraDrilldown getDrugEraResults(@PathParam("id") final int id, @PathParam("drugId") final int drugId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortDrugEraDrilldown drilldown = null; Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.DRUG_ERA_DRILLDOWN; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, drugId); if (refresh || data == null) { drilldown = this.queryRunner.getDrugEraResults(this.getSourceJdbcTemplate(source), id, drugId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortDrugEraDrilldown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Queries for cohort analysis person results for the given cohort definition * id * * @param id cohort_defintion id * @return CohortPersonSummary */ @GET @Path("{sourceKey}/{id}/person") @Produces(MediaType.APPLICATION_JSON) public CohortPersonSummary getPersonResults(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortPersonSummary person = null; final String key = CohortResultsAnalysisRunner.PERSON; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { person = this.queryRunner.getPersonResults(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { person = mapper.readValue(data.getData(), CohortPersonSummary.class); } catch (Exception e) { log.error(e); } } return person; } /** * Queries for cohort analysis cohort specific results for the given cohort * definition id * * @param id cohort_defintion id * @return CohortSpecificSummary */ @GET @Path("{sourceKey}/{id}/cohortspecific") @Produces(MediaType.APPLICATION_JSON) public CohortSpecificSummary getCohortSpecificResults(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortSpecificSummary summary = null; Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.COHORT_SPECIFIC; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { summary = queryRunner.getCohortSpecificSummary(getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { summary = mapper.readValue(data.getData(), CohortSpecificSummary.class); } catch (Exception e) { log.error(e); } } return summary; } /** * Queries for cohort analysis cohort specific treemap results for the given * cohort definition id * * @param id cohort_definition id * @return CohortSpecificSummary */ @GET @Path("{sourceKey}/{id}/cohortspecifictreemap") @Produces(MediaType.APPLICATION_JSON) public CohortSpecificTreemap getCohortSpecificTreemapResults(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortSpecificTreemap summary = null; final String key = CohortResultsAnalysisRunner.COHORT_SPECIFIC_TREEMAP; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { summary = queryRunner.getCohortSpecificTreemapResults(getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { summary = mapper.readValue(data.getData(), CohortSpecificTreemap.class); } catch (Exception e) { log.error(e); } } return summary; } /** * Queries for cohort analysis procedure drilldown results for the given * cohort definition id and concept id * * @param id cohort_definition id * @param conceptId conceptId (from concept) * @return List<ScatterplotRecord> */ @GET @Path("{sourceKey}/{id}/cohortspecificprocedure/{conceptId}") @Produces(MediaType.APPLICATION_JSON) public List<ScatterplotRecord> getCohortProcedureDrilldown(@PathParam("id") final int id, @PathParam("conceptId") final int conceptId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { List<ScatterplotRecord> records = new ArrayList<ScatterplotRecord>(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.COHORT_SPECIFIC_PROCEDURE_DRILLDOWN; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conceptId); if (refresh || data == null) { records = this.queryRunner.getCohortProcedureDrilldown(this.getSourceJdbcTemplate(source), id, conceptId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { records = mapper.readValue(data.getData(), new TypeReference<List<ScatterplotRecord>>() { }); } catch (Exception e) { log.error(e); } } return records; } /** * Queries for cohort analysis drug drilldown results for the given cohort * definition id and concept id * * @param id cohort_definition id * @param conceptId conceptId (from concept) * @return List<ScatterplotRecord> */ @GET @Path("{sourceKey}/{id}/cohortspecificdrug/{conceptId}") @Produces(MediaType.APPLICATION_JSON) public List<ScatterplotRecord> getCohortDrugDrilldown(@PathParam("id") final int id, @PathParam("conceptId") final int conceptId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { List<ScatterplotRecord> records = new ArrayList<ScatterplotRecord>(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.COHORT_SPECIFIC_DRUG_DRILLDOWN; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conceptId); if (refresh || data == null) { records = this.queryRunner.getCohortDrugDrilldown(this.getSourceJdbcTemplate(source), id, conceptId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { records = mapper.readValue(data.getData(), new TypeReference<List<ScatterplotRecord>>() { }); } catch (Exception e) { log.error(e); } } return records; } /** * Queries for cohort analysis condition drilldown results for the given * cohort definition id and concept id * * @param id cohort_defintion id * @param conceptId conceptId (from concept) * @return List<ScatterplotRecord> */ @GET @Path("{sourceKey}/{id}/cohortspecificcondition/{conceptId}") @Produces(MediaType.APPLICATION_JSON) public List<ScatterplotRecord> getCohortConditionDrilldown(@PathParam("id") final int id, @PathParam("conceptId") final int conceptId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { List<ScatterplotRecord> records = null; final String key = CohortResultsAnalysisRunner.COHORT_SPECIFIC_CONDITION_DRILLDOWN; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository .findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conceptId); if (refresh || data == null) { records = this.queryRunner.getCohortConditionDrilldown(this.getSourceJdbcTemplate(source), id, conceptId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { records = mapper.readValue(data.getData(), new TypeReference<List<ScatterplotRecord>>() { }); } catch (Exception e) { log.error(e); } } return records; } /** * Queries for cohort analysis for observation treemap * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/observation") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getCohortObservationResults(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { List<HierarchicalConceptRecord> res = null; Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.OBSERVATION; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { res = this.queryRunner.getCohortObservationResults(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } /** * Queries for cohort analysis observation drilldown results for the given * cohort definition id and condition id * * @param id cohort_defintion id * @param conceptId conceptId (from concept) * @return CohortObservationDrilldown */ @GET @Path("{sourceKey}/{id}/observation/{conceptId}") @Produces(MediaType.APPLICATION_JSON) public CohortObservationDrilldown getCohortObservationResultsDrilldown(@PathParam("id") final int id, @PathParam("conceptId") final int conceptId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortObservationDrilldown drilldown = new CohortObservationDrilldown(); final String key = CohortResultsAnalysisRunner.OBSERVATION_DRILLDOWN; Source source = getSourceRepository().findBySourceKey(sourceKey); VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conceptId); if (refresh || data == null) { drilldown = this.queryRunner.getCohortObservationResultsDrilldown(this.getSourceJdbcTemplate(source), id, conceptId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortObservationDrilldown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Queries for cohort analysis for measurement treemap * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/measurement") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getCohortMeasurementResults(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { List<HierarchicalConceptRecord> res = null; Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.MEASUREMENT; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { res = this.queryRunner.getCohortMeasurementResults(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } /** * Queries for cohort analysis measurement drilldown results for the given * cohort definition id and condition id * * @param id cohort_defintion id * @param conceptId conceptId (from concept) * @return CohortMeasurementDrilldown */ @GET @Path("{sourceKey}/{id}/measurement/{conceptId}") @Produces(MediaType.APPLICATION_JSON) public CohortMeasurementDrilldown getCohortMeasurementResultsDrilldown(@PathParam("id") final int id, @PathParam("conceptId") final int conceptId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortMeasurementDrilldown drilldown = new CohortMeasurementDrilldown(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.MEASUREMENT_DRILLDOWN; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conceptId); if (refresh || data == null) { drilldown = this.queryRunner.getCohortMeasurementResultsDrilldown(this.getSourceJdbcTemplate(source), id, conceptId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortMeasurementDrilldown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Queries for cohort analysis observation period for the given cohort * definition id * * @param id cohort_defintion id * @param minCovariatePersonCountParam * @param minIntervalPersonCountParam * @return CohortObservationPeriod */ @GET @Path("{sourceKey}/{id}/observationperiod") @Produces(MediaType.APPLICATION_JSON) public CohortObservationPeriod getCohortObservationPeriod(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortObservationPeriod obsPeriod = new CohortObservationPeriod(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.OBSERVATION_PERIOD; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { obsPeriod = this.queryRunner.getCohortObservationPeriod(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { obsPeriod = mapper.readValue(data.getData(), CohortObservationPeriod.class); } catch (Exception e) { log.error(e); } } return obsPeriod; } /** * Queries for cohort analysis data density for the given cohort definition id * * @param id cohort_defintion id * @param minCovariatePersonCountParam * @param minIntervalPersonCountParam * @return CohortDataDensity */ @GET @Path("{sourceKey}/{id}/datadensity") @Produces(MediaType.APPLICATION_JSON) public CohortDataDensity getCohortDataDensity(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortDataDensity data = new CohortDataDensity(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.DATA_DENSITY; VisualizationData vizData = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || vizData == null) { data = this.queryRunner.getCohortDataDensity(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { data = mapper.readValue(vizData.getData(), CohortDataDensity.class); } catch (Exception e) { log.error(e); } } return data; } /** * Queries for cohort analysis procedure treemap results for the given cohort * definition id * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/procedure/") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getProcedureTreemap(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { List<HierarchicalConceptRecord> res = null; Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.PROCEDURE; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { res = this.queryRunner.getProcedureTreemap(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } /** * Queries for cohort analysis procedures for the given cohort definition id * and concept id * * @param id cohort_defintion id * @param minCovariatePersonCountParam * @param minIntervalPersonCountParam * @return CohortProceduresDrillDown */ @GET @Path("{sourceKey}/{id}/procedure/{conceptId}") @Produces(MediaType.APPLICATION_JSON) public CohortProceduresDrillDown getCohortProceduresDrilldown(@PathParam("id") final int id, @PathParam("conceptId") final int conceptId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortProceduresDrillDown drilldown = new CohortProceduresDrillDown(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.PROCEDURE_DRILLDOWN; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conceptId); if (refresh || data == null) { drilldown = this.queryRunner.getCohortProceduresDrilldown(this.getSourceJdbcTemplate(source), id, conceptId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortProceduresDrillDown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Queries for cohort analysis visit treemap results for the given cohort * definition id * * @param id cohort_defintion id * @return List<HierarchicalConceptRecord> */ @GET @Path("{sourceKey}/{id}/visit/") @Produces(MediaType.APPLICATION_JSON) public List<HierarchicalConceptRecord> getVisitTreemap(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { List<HierarchicalConceptRecord> res = null; Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.VISIT; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || data == null) { res = queryRunner.getVisitTreemap(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { res = mapper.readValue(data.getData(), new TypeReference<List<HierarchicalConceptRecord>>() { }); } catch (Exception e) { log.error(e); } } return res; } /** * Queries for cohort analysis visits for the given cohort definition id and * concept id * * @param id cohort_defintion id * @param minCovariatePersonCountParam * @param minIntervalPersonCountParam * @return CohortVisitsDrilldown */ @GET @Path("{sourceKey}/{id}/visit/{conceptId}") @Produces(MediaType.APPLICATION_JSON) public CohortVisitsDrilldown getCohortVisitsDrilldown(@PathParam("id") final int id, @PathParam("conceptId") final int conceptId, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortVisitsDrilldown drilldown = new CohortVisitsDrilldown(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.VISIT_DRILLDOWN; VisualizationData data = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKeyAndDrilldownId(id, source.getSourceId(), key, conceptId); if (refresh || data == null) { drilldown = this.queryRunner.getCohortVisitsDrilldown(this.getSourceJdbcTemplate(source), id, conceptId, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { drilldown = mapper.readValue(data.getData(), CohortVisitsDrilldown.class); } catch (Exception e) { log.error(e); } } return drilldown; } /** * Returns the summary for the cohort * * @param id - the cohort_defintion id * @return Summary data including top summary visualization data this cohort * */ @GET @Path("{sourceKey}/{id}/summarydata") @Produces(MediaType.APPLICATION_JSON) public CohortSummary getCohortSummaryData(@PathParam("id") final int id, @PathParam("sourceKey") String sourceKey) { CohortSummary summary = new CohortSummary(); try { // total patients Integer persons = this.getRawDistinctPersonCount(sourceKey, String.valueOf(id), false); summary.setTotalPatients(String.valueOf(persons)); // median age CohortSpecificSummary cohortSpecific = this.getCohortSpecificResults(id, null, null, sourceKey, false); if (cohortSpecific != null && cohortSpecific.getAgeAtIndexDistribution() != null && cohortSpecific.getAgeAtIndexDistribution().size() > 0) { summary.setMeanAge(String.valueOf(cohortSpecific.getAgeAtIndexDistribution().get(0).getMedianValue())); } // TODO mean obs period CohortDashboard dashboard = this.getDashboard(id, null, null, true, sourceKey, false); if (dashboard != null) { summary.setGenderDistribution(dashboard.getGender()); summary.setAgeDistribution(dashboard.getAgeAtFirstObservation()); } } catch (Exception e) { log.error(e); } return summary; } /** * Queries for cohort analysis death data for the given cohort definition id * * @param id cohort_defintion id * @param minCovariatePersonCountParam * @param minIntervalPersonCountParam * @return CohortDeathData */ @GET @Path("{sourceKey}/{id}/death") @Produces(MediaType.APPLICATION_JSON) public CohortDeathData getCohortDeathData(@PathParam("id") final int id, @QueryParam("min_covariate_person_count") final String minCovariatePersonCountParam, @QueryParam("min_interval_person_count") final String minIntervalPersonCountParam, @PathParam("sourceKey") final String sourceKey, @DefaultValue("false") @QueryParam("refresh") boolean refresh) { CohortDeathData data = new CohortDeathData(); Source source = getSourceRepository().findBySourceKey(sourceKey); final String key = CohortResultsAnalysisRunner.DEATH; VisualizationData vizData = refresh ? null : this.visualizationDataRepository.findByCohortDefinitionIdAndSourceIdAndVisualizationKey(id, source.getSourceId(), key); if (refresh || vizData == null) { data = this.queryRunner.getCohortDeathData(this.getSourceJdbcTemplate(source), id, minCovariatePersonCountParam, minIntervalPersonCountParam, source, true); } else { try { data = mapper.readValue(vizData.getData(), CohortDeathData.class); } catch (Exception e) { log.error(e); } } return data; } /** * Returns the summary for the cohort * * @param id - the cohort_defintion id * @return Summary which includes analyses with complete time */ @GET @Path("{sourceKey}/{id}/summaryanalyses") @Produces(MediaType.APPLICATION_JSON) public CohortSummary getCohortSummaryAnalyses(@PathParam("id") final int id, @PathParam("sourceKey") String sourceKey) { CohortSummary summary = new CohortSummary(); try { summary.setAnalyses(getCohortAnalysesForCohortDefinition(id, sourceKey, true)); } catch (Exception e) { log.error("unable to get cohort summary", e); } return summary; } /** * Returns the person identifiers of all members of a generated cohort * definition identifier * * @param id * @param sourceKey * @param min * @param max * @return List of all members of a generated cohort definition identifier */ @GET @Path("{sourceKey}/{id}/members/{min}-{max}") @Produces(MediaType.APPLICATION_JSON) public Collection<CohortPerson> getCohortMembers(@PathParam("id") final int id, @PathParam("sourceKey") String sourceKey, @PathParam("min") final int min, @PathParam("max") final int max) { Source source = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.CDM); String sql = ResourceHelper.GetResourceAsString("/resources/cohortresults/sql/raw/getMembers.sql"); sql = SqlRender.renderSql(sql, new String[]{"tableQualifier", "cohortDefinitionId","min","max"}, new String[]{ resultsTableQualifier, String.valueOf(id), String.valueOf(min), String.valueOf(max)}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect(), SessionUtils.sessionId(), resultsTableQualifier); return getSourceJdbcTemplate(source).query(sql, this.cohortMemberMapper); } /** * Returns breakdown with counts about people in cohort * * @param id * @param sourceKey * @return List of all members of a generated cohort definition identifier */ @GET @Path("{sourceKey}/{id}/breakdown") @Produces(MediaType.APPLICATION_JSON) public Collection<CohortBreakdown> getCohortBreakdown(@PathParam("id") final int id, @PathParam("sourceKey") String sourceKey) { Source source = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); String cdmTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.CDM); String sql = ResourceHelper.GetResourceAsString("/resources/cohortresults/sql/raw/getCohortBreakdown.sql"); sql = SqlRender.renderSql(sql, new String[]{"tableQualifier","resultsTableQualifier", "cohortDefinitionId"}, new String[]{ cdmTableQualifier, resultsTableQualifier, String.valueOf(id)}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect(), SessionUtils.sessionId(), resultsTableQualifier); return getSourceJdbcTemplate(source).query(sql, this.cohortBreakdownMapper); } /** * Returns the person identifiers of all members of a cohort breakdown from above * * @param id * @param sourceKey * @param gender * @param age * @param conditions * @param drugs * @param rows * @return List of all members of a generated cohort definition identifier */ @GET @Path("{sourceKey}/{id}/breakdown/{gender}/{age}/{conditions}/{drugs}/{rows}") @Produces(MediaType.APPLICATION_JSON) public Collection<CohortPerson> getCohortMembers( @PathParam("id") final int id, @PathParam("sourceKey") String sourceKey, @PathParam("gender") String gender, @PathParam("age") String age, @PathParam("conditions") String conditions, @PathParam("drugs") String drugs, @PathParam("rows") final int rows) { List<String> params = new ArrayList<>(); List<String> wherecols = new ArrayList<>(); int groups = 1; if (gender.length() > 0 && !gender.equals("''")) { params.add(" gender in (@gender) "); wherecols.add("gender"); groups = groups * gender.split(",").length; } if (age.length() > 0 && !age.equals("''")) { params.add(" age in (@age) "); wherecols.add("age"); groups = groups * age.split(",").length; } if (conditions.length() > 0 && !conditions.equals("''")) { params.add(" conditions in (@conditions) "); wherecols.add("conditions"); groups = groups * conditions.split(",").length; } if (drugs.length() > 0 && !drugs.equals("''")) { params.add(" drugs in (@drugs) "); wherecols.add("drugs"); groups = groups * drugs.split(",").length; } String clause = " where 1=1\n"; for (String param: params) { clause += (" and " + param + "\n"); } Source source = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); String cdmTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.CDM); String sql = ResourceHelper.GetResourceAsString("/resources/cohortresults/sql/raw/getCohortBreakdownPeople.sql"); sql = sql.replace("/*whereclause*/", clause); String wherecolsStr = ""; if (wherecols.isEmpty()) { sql = sql.replace("partition by", ""); } else { wherecolsStr += wherecols.get(0); for (int i=1; i < wherecols.size(); i++) { wherecolsStr += (',' + wherecols.get(i)); } } sql = SqlRender.renderSql(sql, new String[]{"tableQualifier", "resultsTableQualifier", "cohortDefinitionId","gender", "age", "conditions", "drugs", "rows","wherecols","groups"}, new String[]{cdmTableQualifier, resultsTableQualifier, String.valueOf(id), String.valueOf(gender), String.valueOf(age), String.valueOf(conditions), String.valueOf(drugs), String.valueOf(rows), String.valueOf(wherecolsStr), String.valueOf(groups)}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect(), SessionUtils.sessionId(), resultsTableQualifier); return getSourceJdbcTemplate(source).query(sql, this.cohortMemberMapper); } /** * Returns the person identifiers of all members of a generated cohort * definition identifier * * @param id * @param sourceKey * @return List of all members of a generated cohort definition identifier */ @GET @Path("{sourceKey}/{id}/members/count") @Produces(MediaType.APPLICATION_JSON) public Long getCohortMemberCount(@PathParam("id") final int id, @PathParam("sourceKey") String sourceKey) { Source source = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); String sql = ResourceHelper.GetResourceAsString("/resources/cohortresults/sql/raw/getMemberCount.sql"); sql = SqlRender.renderSql(sql, new String[]{"tableQualifier", "cohortDefinitionId"}, new String[]{ resultsTableQualifier, String.valueOf(id)}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect(), SessionUtils.sessionId(), resultsTableQualifier); return getSourceJdbcTemplate(source).queryForObject(sql, Long.class); } /** * Returns all cohort analyses in the results/OHDSI schema for the given * cohort_definition_id * * @param sourceKey * @return List of all cohort analyses and their statuses for the given * cohort_defintion_id */ @GET @Path("{sourceKey}/{id}") @Produces(MediaType.APPLICATION_JSON) public List<CohortAnalysis> getCohortAnalysesForCohortDefinition(@PathParam("id") final int id, @PathParam("sourceKey") String sourceKey, @DefaultValue("true") @QueryParam("fullDetail") boolean retrieveFullDetail) { String sql = null; if (retrieveFullDetail) { sql = ResourceHelper.GetResourceAsString("/resources/cohortanalysis/sql/getCohortAnalysesForCohortFull.sql"); } else { sql = ResourceHelper.GetResourceAsString("/resources/cohortanalysis/sql/getCohortAnalysesForCohort.sql"); } Source source = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = source.getTableQualifier(SourceDaimon.DaimonType.Results); sql = SqlRender.renderSql(sql, new String[]{"ohdsi_database_schema", "cohortDefinitionId"}, new String[]{ resultsTableQualifier, String.valueOf(id)}); sql = SqlTranslate.translateSql(sql, getSourceDialect(), source.getSourceDialect(), SessionUtils.sessionId(), resultsTableQualifier); return getSourceJdbcTemplate(source).query(sql, this.cohortAnalysisMapper); } @POST @Path("{sourceKey}/exposurecohortrates") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public List<ExposureCohortResult> getExposureOutcomeCohortRates(@PathParam("sourceKey") String sourceKey, ExposureCohortSearch search) { Source dbsource = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = dbsource.getTableQualifier(SourceDaimon.DaimonType.Results); String sql_statement = ResourceHelper.GetResourceAsString("/resources/cohortresults/sql/cohortSpecific/getExposureOutcomeCohortRates.sql"); String exposureCohortList = this.JoinArray(search.exposureCohortList); String outcomeCohortList = this.JoinArray(search.outcomeCohortList); sql_statement = SqlRender.renderSql(sql_statement, new String[]{"exposure_cohort_definition_id","outcome_cohort_definition_id","ohdsi_database_schema"}, new String[]{exposureCohortList, outcomeCohortList, resultsTableQualifier}); sql_statement = SqlTranslate.translateSql(sql_statement, "sql server", dbsource.getSourceDialect()); final List<ExposureCohortResult> results = new ArrayList<ExposureCohortResult>(); List<Map<String, Object>> rows = getSourceJdbcTemplate(dbsource).queryForList(sql_statement); for (Map rs : rows) { ExposureCohortResult e = new ExposureCohortResult(); e.exposureCohortDefinitionId = String.valueOf(rs.get("exposure_cohort_definition_id")); e.incidenceRate1000py = Float.valueOf(String.valueOf(rs.get("incidence_rate_1000py"))); e.numPersonsExposed = Long.valueOf(String.valueOf(rs.get("num_persons_exposed"))); e.numPersonsWithOutcomePostExposure = Long.valueOf(String.valueOf(rs.get("num_persons_w_outcome_post_exposure"))); e.numPersonsWithOutcomePreExposure = Long.valueOf(String.valueOf(rs.get("num_persons_w_outcome_pre_exposure"))); e.outcomeCohortDefinitionId = String.valueOf(rs.get("outcome_cohort_definition_id")); e.timeAtRisk = Float.valueOf(String.valueOf(rs.get("time_at_risk"))); results.add(e); } return results; } @POST @Path("{sourceKey}/timetoevent") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public List<TimeToEventResult> getTimeToEventDrilldown(@PathParam("sourceKey") String sourceKey, ExposureCohortSearch search) { Source dbsource = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = dbsource.getTableQualifier(SourceDaimon.DaimonType.Results); String sql_statement = ResourceHelper.GetResourceAsString("/resources/cohortresults/sql/cohortSpecific/getTimeToEventDrilldown.sql"); String exposureCohortList = this.JoinArray(search.exposureCohortList); String outcomeCohortList = this.JoinArray(search.outcomeCohortList); sql_statement = SqlRender.renderSql(sql_statement, new String[]{"exposure_cohort_definition_id","outcome_cohort_definition_id","ohdsi_database_schema"}, new String[]{exposureCohortList, outcomeCohortList, resultsTableQualifier}); sql_statement = SqlTranslate.translateSql(sql_statement, "sql server", dbsource.getSourceDialect()); final List<TimeToEventResult> results = new ArrayList<TimeToEventResult>(); List<Map<String, Object>> rows = getSourceJdbcTemplate(dbsource).queryForList(sql_statement); for (Map rs : rows) { TimeToEventResult e = new TimeToEventResult(); e.countValue = Long.valueOf(String.valueOf(rs.get("count_value"))); e.duration = Long.valueOf(String.valueOf(rs.get("duration"))); e.exposureCohortDefinitionId = String.valueOf(rs.get("exposure_cohort_definition_id")); e.outcomeCohortDefinitionId = String.valueOf(rs.get("outcome_cohort_definition_id")); e.pctPersons = Double.valueOf(String.valueOf(rs.get("pct_persons"))); e.recordType = String.valueOf(rs.get("record_type")); results.add(e); } return results; } @POST @Path("{sourceKey}/predictors") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public List<PredictorResult> getExposureOutcomeCohortPredictors(@PathParam("sourceKey") String sourceKey, ExposureCohortSearch search) { Source dbsource = getSourceRepository().findBySourceKey(sourceKey); String resultsTableQualifier = dbsource.getTableQualifier(SourceDaimon.DaimonType.Results); String cdmTableQualifier = dbsource.getTableQualifier(SourceDaimon.DaimonType.CDM); String sql_statement = ResourceHelper.GetResourceAsString("/resources/cohortresults/sql/cohortSpecific/getExposureOutcomePredictors.sql"); String exposureCohortList = this.JoinArray(search.exposureCohortList); String outcomeCohortList = this.JoinArray(search.outcomeCohortList); String minCellCount = String.valueOf(search.minCellCount); sql_statement = SqlRender.renderSql(sql_statement, new String[]{"exposure_cohort_definition_id","outcome_cohort_definition_id","minCellCount","ohdsi_database_schema", "cdm_schema"}, new String[]{exposureCohortList, outcomeCohortList, minCellCount, resultsTableQualifier, cdmTableQualifier}); sql_statement = SqlTranslate.translateSql(sql_statement, "sql server", dbsource.getSourceDialect()); final List<PredictorResult> results = new ArrayList<PredictorResult>(); List<Map<String, Object>> rows = getSourceJdbcTemplate(dbsource).queryForList(sql_statement); for (Map rs : rows) { PredictorResult e = new PredictorResult(); e.absStdDiff = String.valueOf(rs.get("abs_std_diff")); e.conceptId = String.valueOf(rs.get("concept_id")); e.conceptName = String.valueOf(rs.get("concept_name")); e.conceptWithOutcome = String.valueOf(rs.get("concept_w_outcome")); e.domainId = String.valueOf(rs.get("domain_id")); e.pctOutcomeWithConcept = String.valueOf(rs.get("pct_outcome_w_concept")); e.pctNoOutcomeWithConcept = String.valueOf(rs.get("pct_nooutcome_w_concept")); e.exposureCohortDefinitionId = String.valueOf(rs.get("exposure_cohort_definition_id")); e.outcomeCohortDefinitionId = String.valueOf(rs.get("outcome_cohort_definition_id")); results.add(e); } return results; } private String JoinArray(final String[] array) { String result = ""; for (int i = 0; i < array.length; i++) { if (i > 0) { result += ","; } result += "'" + array[i] + "'"; } return result; } private final RowMapper<CohortPerson> cohortMemberMapper = new RowMapper<CohortPerson>() { @Override public CohortPerson mapRow(final ResultSet rs, final int rowNum) throws SQLException { CohortPerson person = new CohortPerson(); person.personId = rs.getLong("subject_id"); person.startDate = rs.getTimestamp("cohort_start_date"); person.endDate = rs.getTimestamp("cohort_end_date"); return person; } }; private final RowMapper<CohortBreakdown> cohortBreakdownMapper = new RowMapper<CohortBreakdown>() { @Override public CohortBreakdown mapRow(final ResultSet rs, final int rowNum) throws SQLException { CohortBreakdown group = new CohortBreakdown(); group.people = rs.getLong("people"); group.gender = rs.getString("gender"); group.age = rs.getString("age"); group.conditions = rs.getLong("conditions"); group.drugs = rs.getLong("drugs"); return group; } }; private final RowMapper<CohortAnalysis> cohortAnalysisMapper = new RowMapper<CohortAnalysis>() { @Override public CohortAnalysis mapRow(final ResultSet rs, final int rowNum) throws SQLException { final CohortAnalysis cohortAnalysis = new CohortAnalysis(); mapAnalysis(cohortAnalysis, rs, rowNum); cohortAnalysis.setAnalysisComplete(rs.getInt(CohortAnalysis.ANALYSIS_COMPLETE) == 1); cohortAnalysis.setCohortDefinitionId(rs.getInt(CohortAnalysis.COHORT_DEFINITION_ID)); cohortAnalysis.setLastUpdateTime(rs.getTimestamp(CohortAnalysis.LAST_UPDATE_TIME)); return cohortAnalysis; } }; private void mapAnalysis(final Analysis analysis, final ResultSet rs, final int rowNum) throws SQLException { analysis.setAnalysisId(rs.getInt(Analysis.ANALYSIS_ID)); analysis.setAnalysisName(rs.getString(Analysis.ANALYSIS_NAME)); analysis.setStratum1Name(rs.getString(Analysis.STRATUM_1_NAME)); analysis.setStratum2Name(rs.getString(Analysis.STRATUM_2_NAME)); analysis.setStratum3Name(rs.getString(Analysis.STRATUM_3_NAME)); analysis.setStratum4Name(rs.getString(Analysis.STRATUM_4_NAME)); analysis.setStratum5Name(rs.getString(Analysis.STRATUM_5_NAME)); analysis.setAnalysisType(rs.getString(Analysis.ANALYSIS_TYPE)); } };