Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
dexamundsen committed Jan 28, 2025
1 parent 0adb9c5 commit 685620a
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
import bio.terra.tanagra.generated.model.ApiCohortCloneInfo;
import bio.terra.tanagra.generated.model.ApiCohortCountQuery;
import bio.terra.tanagra.generated.model.ApiCohortCreateInfo;
import bio.terra.tanagra.generated.model.ApiCohortIdVisualizationsBody;
import bio.terra.tanagra.generated.model.ApiCohortList;
import bio.terra.tanagra.generated.model.ApiCohortUpdateInfo;
import bio.terra.tanagra.generated.model.ApiInstanceCountList;
import bio.terra.tanagra.generated.model.ApiVisualization;
import bio.terra.tanagra.generated.model.ApiVisualizationList;
import bio.terra.tanagra.service.UnderlayService;
import bio.terra.tanagra.service.accesscontrol.AccessControlService;
import bio.terra.tanagra.service.accesscontrol.Permissions;
Expand All @@ -37,6 +40,7 @@
import bio.terra.tanagra.underlay.entitymodel.Entity;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -220,4 +224,34 @@ public ResponseEntity<ApiInstanceCountList> queryCohortCounts(
body.getPageSize());
return ResponseEntity.ok(ToApiUtils.toApiObject(countQueryResult));
}

@Override
public ResponseEntity<ApiVisualizationList> visualizeCohortCounts(
String studyId, String cohortId, ApiCohortIdVisualizationsBody body) {
accessControlService.checkReadAccess(studyId, List.of(cohortId), List.of());
Cohort cohort = cohortService.getCohort(studyId, cohortId);

accessControlService.throwIfUnauthorized(
SpringAuthentication.getCurrentUser(),
Permissions.forActions(UNDERLAY, READ),
ResourceId.forUnderlay(cohort.getUnderlay()));

EntityFilter cohortFilter =
filterBuilderService.buildFilterForCohortRevision(
cohort.getUnderlay(), cohort.getMostRecentRevision());

if (cohortFilter != null) {
// TODO(BENCH-4945): add support for charts
throw new NotImplementedException(
"visualizeCohortCounts not implemented yet for cohorts with filters");
}

Underlay underlay = underlayService.getUnderlay(cohort.getUnderlay());
List<ApiVisualization> vizList =
body.getVisualizationNames().parallelStream()
.map(id -> ToApiUtils.toApiObject(underlay.getPrecomputedVisualization(id)))
.toList();

return ResponseEntity.ok(new ApiVisualizationList().visualizations(vizList));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@
import bio.terra.tanagra.generated.model.ApiStudy;
import bio.terra.tanagra.generated.model.ApiUnderlaySummary;
import bio.terra.tanagra.generated.model.ApiValueDisplay;
import bio.terra.tanagra.generated.model.ApiVisualization;
import bio.terra.tanagra.generated.model.ApiVisualizationData;
import bio.terra.tanagra.generated.model.ApiVisualizationDataKey;
import bio.terra.tanagra.generated.model.ApiVisualizationDataValue;
import bio.terra.tanagra.service.artifact.model.AnnotationValue;
import bio.terra.tanagra.service.artifact.model.Cohort;
import bio.terra.tanagra.service.artifact.model.CohortRevision;
import bio.terra.tanagra.service.artifact.model.Criteria;
import bio.terra.tanagra.service.artifact.model.Study;
import bio.terra.tanagra.underlay.Underlay;
import bio.terra.tanagra.underlay.entitymodel.Attribute;
import bio.terra.tanagra.underlay.visualization.Visualization;
import bio.terra.tanagra.underlay.visualization.VisualizationData;
import bio.terra.tanagra.utils.SqlFormatter;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -322,4 +328,31 @@ public static ApiUnderlaySummary toApiObject(Underlay underlay) {
.description(underlay.getDescription())
.primaryEntity(underlay.getPrimaryEntity().getName());
}

private static ApiVisualizationData toApiObject(VisualizationData vizData) {
return new ApiVisualizationData()
.keys(
vizData.getKeys().stream()
.map(
k ->
new ApiVisualizationDataKey()
.name(k.name())
.numericId(k.numericId())
.stringId(k.stringId()))
.toList())
.values(
vizData.getValues().stream()
.map(
v ->
new ApiVisualizationDataValue()
.numeric(v.numeric())
.quartiles(v.quartiles()))
.toList());
}

public static ApiVisualization toApiObject(Visualization visualization) {
return new ApiVisualization()
.name(visualization.getName())
.vizDataList(visualization.getVizDataList().stream().map(ToApiUtils::toApiObject).toList());
}
}
106 changes: 106 additions & 0 deletions service/src/main/resources/api/service_openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,40 @@ paths:
500:
$ref: "#/components/responses/ServerError"

"/v2/studies/{studyId}/cohorts/{cohortId}/visualizations":
parameters:
- $ref: "#/components/parameters/ParamStudyId"
- $ref: "#/components/parameters/ParamCohortId"
post:
summary: Return visualizations for a cohort
operationId: visualizeCohortCounts
tags: [Cohorts]
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
visualizationNames:
type: array
description: Names (IDs) of requested visualizations
items:
$ref: "#/components/schemas/VisualizationName"
required:
- visualizationNames
responses:
200:
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/VisualizationList"
404:
$ref: "#/components/responses/NotFound"
500:
$ref: "#/components/responses/ServerError"

# --------------- Studies: Reviews ---------------

"/v2/studies/{studyId}/cohorts/{cohortId}/reviews":
Expand Down Expand Up @@ -2122,6 +2156,16 @@ components:
numRowsAcrossAllPages:
$ref: "#/components/schemas/NumRowsAcrossAllPages"


VisualizationList:
type: object
description: List of cohort visualizations
properties:
visualizations:
type: array
items:
$ref: "#/components/schemas/Visualization"

DisplayHint:
type: object
description: Display hint for entity attribute
Expand Down Expand Up @@ -2364,6 +2408,68 @@ components:
type: string
description: Description of the cohort

Visualization:
type: object
description: Description of the Visualization
properties:
name:
$ref: "#/components/schemas/VisualizationName"
title:
type: string
description: Visualization title
vizDataList:
type: array
items:
$ref: "#/components/schemas/VisualizationData"
required:
- name
- title
- vizDataList

VisualizationName:
type: string
description: Name (ID) of the visualization, immutable

VisualizationData:
type: object
description: Visualization data for a cohort
properties:
keys:
type: array
items:
$ref: "#/components/schemas/VisualizationDataKey"
values:
type: array
items:
$ref: "#/components/schemas/VisualizationDataValue"
required:
- keys
- values

VisualizationDataKey:
type: object
description: Visualization data key
properties:
name:
type: string
numericId:
type: integer
stringId:
type: string
required:
- name

VisualizationDataValue:
type: object
description: Visualization data value
properties:
numeric:
type: integer
quartiles:
type: array
items:
type: integer

FeatureSet:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import com.google.common.collect.ImmutableMap;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.annotation.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -455,4 +457,14 @@ private static Pair<String, String> parseTwoPartPath(String path) {
public static DataType deserializeDataType(@Nullable SZDataType szDataType) {
return szDataType == null ? null : DataType.valueOf(szDataType.name());
}

public static <T> T deserializeStringToObj(String str, Class<T> clazz) {
try {
return JacksonMapper.readFileIntoJavaObject(
new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8)), clazz);
} catch (IOException e) {
throw new InvalidConfigException(
"Error deserializing string to class: " + clazz.getSimpleName(), e);
}
}
}
Loading

0 comments on commit 685620a

Please sign in to comment.