Skip to content

Commit

Permalink
#287: Add translation and transformer conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
benitsch committed Jul 12, 2024
1 parent 79f09ba commit 9efb911
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import io.redlink.more.studymanager.core.ui.DataViewRow;
import io.redlink.more.studymanager.core.ui.ViewConfig;

import java.util.List;
import java.util.Map;
import java.util.Optional;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
public interface DataViewInfo
{
String name();
String label();
String title();
String description();
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,23 @@ public PolarVerityObservation(MoreObservationSDK sdk, C properties) throws Confi
}

private enum DataViewInfoType implements DataViewInfo {
heart_rate("Heart rate", "Heart rate per participant over time.");
heart_rate("data.charts.polarVerity.avgHeartRate.label", "data.charts.polarVerity.avgHeartRate.title", "data.charts.polarVerity.avgHeartRate.description");

private final String label;
private final String title;
private final String description;

DataViewInfoType(String title, String description) {
DataViewInfoType(String label, String title, String description) {
this.label = label;
this.title = title;
this.description = description;
}

@Override
public String label() {
return this.label;
}

@Override
public String title() {
return this.title;
Expand Down Expand Up @@ -68,6 +75,31 @@ private DataView createHeartRateView(Integer studyGroupId, Integer participantId
);

DataViewData dataViewData = sdk.queryData(viewConfig, studyGroupId, participantId, timerange);

// var allParticipants = participantService.listParticipants(studyId);
//
// for (int i = 0; i < dataViewData.rows().size(); i++) {
// final int index = i;
// DataViewRow currentRow = dataViewData.rows().get(i);
// String label = currentRow.label();
// String[] parts = label.split("_");
// if (parts.length == 2 && parts[0].equals("participant")) {
// try {
// int participantIdFromLabel = Integer.parseInt(parts[1]);
// Optional<Participant> matchingParticipant = allParticipants.stream()
// .filter(participant -> participant.getParticipantId() == participantIdFromLabel)
// .findFirst();
//
// matchingParticipant.ifPresent(participant -> {
// dataView.data().rows().set(index, new DataViewRow(participant.getAlias(), currentRow.values()));
// });
// } catch (NumberFormatException e) {
// System.err.println("Invalid participant ID format in label: " + label);
// }
// }
// }


return new DataView(
DataViewInfoType.heart_rate,
DataView.ChartType.LINE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,25 @@ public QuestionObservation(MoreObservationSDK sdk, C properties) throws Configur
}

private enum DataViewInfoType implements DataViewInfo {
questions("Answers", "All answers summed up."),
answers_by_group("By Study group", "All answers summed by group."),
group_by_answers("By Answers", "All answers summed by answers.");
response_distribution("data.charts.simpleQuestion.responseDistribution.label", "data.charts.simpleQuestion.responseDistribution.title", "data.charts.simpleQuestion.responseDistribution.description"),
answers_by_group("data.charts.simpleQuestion.responseDistributionStudyGroup.label", "data.charts.simpleQuestion.responseDistributionStudyGroup.title", "data.charts.simpleQuestion.responseDistributionStudyGroup.description"),
group_by_answers("data.charts.simpleQuestion.responseDistributionResponse.label", "data.charts.simpleQuestion.responseDistributionResponse.title", "data.charts.simpleQuestion.responseDistributionResponse.description");

private final String label;
private final String title;
private final String description;

DataViewInfoType(String title, String description) {
DataViewInfoType(String label, String title, String description) {
this.label = label;
this.title = title;
this.description = description;
}

@Override
public String label() {
return this.label;
}

@Override
public String title() {
return this.title;
Expand All @@ -59,7 +66,7 @@ public Set<DataViewInfo> listViews() {
@Override
public DataView getView(String viewName, Integer studyGroupId, Integer participantId, TimeRange timerange) {
return switch (DataViewInfoType.valueOf(viewName)) {
case questions -> createQuestionsView(studyGroupId, participantId, timerange);
case response_distribution -> createQuestionsView(studyGroupId, participantId, timerange);
case answers_by_group -> createAnswersByGroupView(studyGroupId, participantId, timerange);
case group_by_answers -> createGroupByAnswersView(studyGroupId, participantId, timerange);
};
Expand All @@ -76,7 +83,7 @@ private DataView createQuestionsView(Integer studyGroupId, Integer participantId
DataViewData dataViewData = sdk.queryData(viewConfig, studyGroupId, participantId, timerange);

return new DataView(
DataViewInfoType.questions,
DataViewInfoType.response_distribution,
DataView.ChartType.PIE,
dataViewData
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,23 @@ public static IdTitleDTO toIdTitleDTO_V1(ParticipationData.NamedId idTitle){
}

public static ObservationDataViewDataDTO toObservationDataViewDataDTO(DataView dataView){
return new ObservationDataViewDataDTO()
var observationDataViewDataDTO = new ObservationDataViewDataDTO()
.view(toObservationDataViewDTO(dataView.viewInfo()))
.chartType(toChartTypeEnumDTO(dataView.chartType()))
.labels(dataView.data().labels())
.data(toObservationDataViewDataRowDTO(dataView.data().rows()));
.chartType(toChartTypeEnumDTO(dataView.chartType()));

if (dataView.data() != null) {
observationDataViewDataDTO
.labels(dataView.data().labels())
.data(toObservationDataViewDataRowDTO(dataView.data().rows()));
}

return observationDataViewDataDTO;
}

public static ObservationDataViewDTO toObservationDataViewDTO(DataViewInfo dataViewInfo) {
return new ObservationDataViewDTO()
.name(dataViewInfo.name())
.label(dataViewInfo.label())
.title(dataViewInfo.title())
.description(dataViewInfo.description());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.StringTermsBucket;
import co.elastic.clients.elasticsearch._types.aggregations.*;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.DeleteByQueryRequest;
import co.elastic.clients.elasticsearch.core.SearchRequest;
Expand All @@ -22,6 +22,7 @@
import co.elastic.clients.elasticsearch.indices.CloseIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.util.ObjectBuilder;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Iterables;
import io.redlink.more.studymanager.core.io.TimeRange;
Expand Down Expand Up @@ -341,10 +342,9 @@ private SearchRequest.Builder buildQuestionRequest(ViewConfig viewConfig, List<Q
)
)
.aggregations("question_answer",
a -> a.terms(
t -> t.field(String.format("data_%s.keyword", viewConfig.operation().field())))
a -> applyOperation(a, viewConfig.operation())
);
} else if (viewConfig.seriesAggregation() != null && viewConfig.rowAggregation() == null) {
} else if (viewConfig.rowAggregation() == null && viewConfig.seriesAggregation() != null) {
// "answersByGroup"
builder.index(getStudyIdString(studyId))
.size(0)
Expand Down Expand Up @@ -373,11 +373,50 @@ private SearchRequest.Builder buildQuestionRequest(ViewConfig viewConfig, List<Q
.size(1000)
.missing("Entire study")));

} else if (viewConfig.rowAggregation() != null && viewConfig.seriesAggregation() != null) {
// "avgHeartRateByParticipantOverTime"
builder.index(getStudyIdString(studyId))
.size(0)
.query(q -> q.bool(b -> b.filter(filters)))
.aggregations("average_heart_rate_by_participant_over_time",
a -> a.dateHistogram(
dh -> dh.field("effective_time_frame")
.calendarInterval(CalendarInterval.Minute)
.format("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.minDocCount(0)

).aggregations("participant",
ag -> ag.terms(t -> t.field("participant_id.keyword"))
.aggregations("average_heart_rate",
subAggs -> subAggs.avg(r -> r.field(String.format("data_%s", viewConfig.operation().field()))))
)
)
.aggregations("all_participants",
a -> a.terms(t -> t.field("participant_id.keyword")
.size(1000)
));
}

return builder;
}

private ObjectBuilder<Aggregation> applyOperation(Aggregation.Builder a, ViewConfig.Operation operation) {
switch (operation.operator()) {
case AVG:
return null;
case SUM:
return null;
case MIN:
return null;
case MAX:
return null;
case COUNT:
return a.terms(
t -> t.field(String.format("data_%s.keyword", operation.field())));
}
return null;
}

private DataViewData processQuestionResponse(ViewConfig viewConfig, SearchResponse<Map> searchResponse) {
List<String> dataViewLabels = new ArrayList<>();
List<DataViewRow> dataViewRows = new ArrayList<>();
Expand Down Expand Up @@ -480,6 +519,64 @@ private DataViewData processQuestionResponse(ViewConfig viewConfig, SearchRespon
dataViewRows.add(new DataViewRow(group, values));
}

} else if (viewConfig.rowAggregation() != null && viewConfig.seriesAggregation() != null) {
// "avgHeartRateByParticipantOverTime"
List<DateHistogramBucket> timeBuckets = searchResponse.aggregations()
.get("average_heart_rate_by_participant_over_time")
.dateHistogram()
.buckets()
.array();

List<String> allParticipantIds = searchResponse.aggregations()
.get("all_participants")
.sterms()
.buckets()
.array()
.stream()
.map(StringTermsBucket::key)
.map(FieldValue::stringValue)
.toList();

Map<String, List<Integer>> participantDataMap = new HashMap<>();

for (DateHistogramBucket timeBucket : timeBuckets) {
List<StringTermsBucket> participantBuckets = timeBucket.aggregations()
.get("participant")
.sterms()
.buckets()
.array();

if (participantBuckets.size() > 0) {
String timeLabel = timeBucket.keyAsString();
dataViewLabels.add(timeLabel);
}

for (StringTermsBucket participantBucket : participantBuckets) {
String participant = participantBucket.key().stringValue();
double avgHrValue = participantBucket.aggregations()
.get("average_heart_rate")
.avg()
.value();

participantDataMap.computeIfAbsent(participant, k -> new ArrayList<>());
participantDataMap.get(participant).add((int) Math.round(avgHrValue));
// Add default 0 value for all other participants, to ensure equal x/y axis assignment
if (participantBuckets.size() == 1) {
for (String id : allParticipantIds) {
if (!id.equals(participant)) {
participantDataMap.computeIfAbsent(id, k -> new ArrayList<>());
participantDataMap.get(id).add(null);
}
}
}
}
}

for (Map.Entry<String, List<Integer>> entry : participantDataMap.entrySet()) {
String participant = entry.getKey();
List<Integer> avgHrValues = entry.getValue();
dataViewRows.add(new DataViewRow(participant, avgHrValues));
}
}

return new DataViewData(dataViewLabels, dataViewRows);
Expand Down
2 changes: 2 additions & 0 deletions studymanager/src/main/resources/openapi/StudyManagerAPI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1730,6 +1730,8 @@ components:
properties:
name:
type: string
label:
type: string
title:
type: string
description:
Expand Down

0 comments on commit 9efb911

Please sign in to comment.