Skip to content

Commit

Permalink
Add an api to retrieve filter options in sensi results (#36)
Browse files Browse the repository at this point in the history
Signed-off-by: Seddik Yengui <[email protected]>
  • Loading branch information
YenguiSeddik authored Sep 28, 2023
1 parent 8787171 commit e50bb8b
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityAnalysisInputData;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityAnalysisStatus;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityResultFilterOptions;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityRunQueryResult;
import org.gridsuite.sensitivityanalysis.server.service.SensitivityAnalysisRunContext;
import org.gridsuite.sensitivityanalysis.server.service.SensitivityAnalysisService;
Expand Down Expand Up @@ -54,6 +55,13 @@ private static List<UUID> getNonNullOtherNetworkUuids(List<UUID> otherNetworkUui
return otherNetworkUuids != null ? otherNetworkUuids : Collections.emptyList();
}

private static ResultsSelector getSelector(String selectorJson) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return selectorJson == null ?
ResultsSelector.builder().functionType(SensitivityFunctionType.BRANCH_ACTIVE_POWER_1).isJustBefore(false).build() :
mapper.readValue(selectorJson, ResultsSelector.class);
}

@PostMapping(value = "/networks/{networkUuid}/run", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
@Operation(summary = "Run a sensitivity analysis on a network")
@ApiResponses(value = {@ApiResponse(responseCode = "200",
Expand Down Expand Up @@ -99,21 +107,30 @@ public ResponseEntity<SensitivityRunQueryResult> getResult(@Parameter(descriptio
@PathVariable("resultUuid") UUID resultUuid,
@RequestParam(name = "selector", required = false) String selectorJson) {

ObjectMapper mapper = new ObjectMapper();
ResultsSelector selector;
if (selectorJson == null) {
selector = ResultsSelector.builder().functionType(SensitivityFunctionType.BRANCH_ACTIVE_POWER_1).isJustBefore(false).build();
} else {
try {
selector = mapper.readValue(selectorJson, ResultsSelector.class);
} catch (JsonProcessingException e) {
return ResponseEntity.badRequest().build();
}
try {
ResultsSelector selector = getSelector(selectorJson);
SensitivityRunQueryResult result = service.getRunResult(resultUuid, selector);
return result != null ? ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(result)
: ResponseEntity.notFound().build();
} catch (JsonProcessingException e) {
return ResponseEntity.badRequest().build();
}
}

SensitivityRunQueryResult result = service.getRunResult(resultUuid, selector);
return result != null ? ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(result)
: ResponseEntity.notFound().build();
@GetMapping(value = "/results/{resultUuid}/filter-options", produces = APPLICATION_JSON_VALUE)
@Operation(summary = "Get all filter options of sensitivity analysis results")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The sensitivity analysis result filter options"),
@ApiResponse(responseCode = "404", description = "Sensitivity analysis result has not been found")})
public ResponseEntity<SensitivityResultFilterOptions> getResultFilerOptions(@Parameter(description = "Result UUID") @PathVariable("resultUuid") UUID resultUuid,
@RequestParam(name = "selector", required = false) String selectorJson) {
try {
ResultsSelector selector = getSelector(selectorJson);
SensitivityResultFilterOptions result = service.getSensitivityResultOptions(resultUuid, selector);
return result != null ? ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(result)
: ResponseEntity.notFound().build();
} catch (JsonProcessingException e) {
return ResponseEntity.badRequest().build();
}
}

@DeleteMapping(value = "/results/{resultUuid}", produces = APPLICATION_JSON_VALUE)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Copyright (c) 2023, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

package org.gridsuite.sensitivityanalysis.server.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

/**
* @author Seddik Yengui <seddik.yengui at rte-france.com>
*/

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
public class SensitivityResultFilterOptions {
List<String> allContingencyIds;
List<String> allFunctionIds;
List<String> allVariableIds;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,4 @@ public class SensitivityRunQueryResult {

@NonNull
List<? extends SensitivityOfTo> sensitivities;

List<String> allContingencyIds;
List<String> allFunctionIds;
List<String> allVariableIds;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.sensitivity.SensitivityValue;
import org.gridsuite.sensitivityanalysis.server.ResultsSelector;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityOfTo;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityResultFilterOptions;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityRunQueryResult;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityWithContingency;
import org.gridsuite.sensitivityanalysis.server.entities.AnalysisResultEntity;
Expand All @@ -28,13 +29,10 @@
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.function.Supplier;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -145,6 +143,28 @@ public String findStatus(UUID resultUuid) {
}
}

@Transactional(readOnly = true)
public SensitivityResultFilterOptions getSensitivityResultFilterOptions(UUID resultUuid, ResultsSelector selector) {
AnalysisResultEntity sas = analysisResultRepository.findByResultUuid(resultUuid);
if (sas == null) {
return null;
}

SensitivityResultFilterOptions.SensitivityResultFilterOptionsBuilder sensitivityResultOptionsBuilder = SensitivityResultFilterOptions.builder()
.allFunctionIds(sensitivityRepository.findFunctionByResultResultUuidAndFactorFunctionType(sas.getResultUuid(), selector.getFunctionType()))
.allVariableIds(sensitivityRepository.findVariableByResultResultUuidAndFactorFunctionType(sas.getResultUuid(), selector.getFunctionType()));

if (!selector.getIsJustBefore()) {
sensitivityResultOptionsBuilder.allContingencyIds(sensitivityRepository.findContingencyByResultResultUuidAndFactorFunctionType(sas.getResultUuid(), selector.getFunctionType())
.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList()))
.build();
}

return sensitivityResultOptionsBuilder.build();
}

@Transactional(readOnly = true)
public SensitivityRunQueryResult getRunResult(UUID resultUuid, ResultsSelector selector) {
AnalysisResultEntity sas = analysisResultRepository.findByResultUuid(resultUuid);
Expand Down Expand Up @@ -213,10 +233,6 @@ private SensitivityRunQueryResult getSensitivityRunQueryResult(ResultsSelector s
return retBuilder.build();
}

Set<String> allFunctionIds = new TreeSet<>();
Set<String> allVariableIds = new TreeSet<>();
Set<String> allContingencyIds = new TreeSet<>();

var totalSensitivitiesCountSpec = SensitivityRepository.getSpecification(sas,
selector.getFunctionType(),
null,
Expand All @@ -229,8 +245,6 @@ private SensitivityRunQueryResult getSensitivityRunQueryResult(ResultsSelector s
List<SensitivityOfTo> befores = new ArrayList<>();
sensitivityEntities.forEach(sensitivityEntity -> {
SensitivityFactorEmbeddable factorEmbeddable = sensitivityEntity.getFactor();
allFunctionIds.add(factorEmbeddable.getFunctionId());
allVariableIds.add(factorEmbeddable.getVariableId());
befores.add(SensitivityOfTo.builder()
.funcId(factorEmbeddable.getFunctionId())
.varId(factorEmbeddable.getVariableId())
Expand All @@ -239,16 +253,11 @@ private SensitivityRunQueryResult getSensitivityRunQueryResult(ResultsSelector s
.functionReference(sensitivityEntity.getFunctionReference())
.build());
});
complete(retBuilder, allFunctionIds, allVariableIds, null, filteredSensitivitiesCount, count, befores);
complete(retBuilder, filteredSensitivitiesCount, count, befores);
} else {
List<SensitivityWithContingency> after = new ArrayList<>();
sensitivityEntities.forEach(sensitivityEntity -> {
SensitivityFactorEmbeddable factorEmbeddable = sensitivityEntity.getFactor();
allFunctionIds.add(factorEmbeddable.getFunctionId());
allVariableIds.add(factorEmbeddable.getVariableId());
if (factorEmbeddable.getContingencyContextId() != null) {
allContingencyIds.add(factorEmbeddable.getContingencyContextId());
}
SensitivityWithContingency r = SensitivityWithContingency.builder()
.funcId(factorEmbeddable.getFunctionId())
.varId(factorEmbeddable.getVariableId())
Expand All @@ -262,25 +271,17 @@ private SensitivityRunQueryResult getSensitivityRunQueryResult(ResultsSelector s

after.add(r);
});
complete(retBuilder, allFunctionIds, allVariableIds, allContingencyIds, filteredSensitivitiesCount, count, after);
complete(retBuilder, filteredSensitivitiesCount, count, after);
}
return retBuilder.build();
}

private void complete(SensitivityRunQueryResult.SensitivityRunQueryResultBuilder retBuilder,
Collection<String> allFunctionIds,
Collection<String> allVariableIds,
Collection<String> allContingencyIds,
long filteredSensitivitiesCount,
long count,
List<? extends SensitivityOfTo> filtered

) {
retBuilder.allFunctionIds(allFunctionIds.stream().sorted().collect(Collectors.toList()));
retBuilder.allVariableIds(allVariableIds.stream().sorted().collect(Collectors.toList()));
if (allContingencyIds != null) {
retBuilder.allContingencyIds(allContingencyIds.stream().sorted().collect(Collectors.toList()));
}
retBuilder.filteredSensitivitiesCount(filteredSensitivitiesCount);
retBuilder.sensitivities(filtered);
retBuilder.totalSensitivitiesCount(count);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.util.CollectionUtils;

import jakarta.persistence.criteria.CriteriaBuilder;
Expand All @@ -37,6 +38,15 @@ public interface SensitivityRepository extends JpaRepository<SensitivityEntity,

Page<SensitivityEntity> findAll(Specification<SensitivityEntity> specification, Pageable pageable);

@Query(value = "SELECT distinct s.factor.functionId from SensitivityEntity as s")
List<String> findFunctionByResultResultUuidAndFactorFunctionType(UUID resultUuid, SensitivityFunctionType sensitivityFunctionType);

@Query(value = "SELECT distinct s.factor.variableId from SensitivityEntity as s")
List<String> findVariableByResultResultUuidAndFactorFunctionType(UUID resultUuid, SensitivityFunctionType sensitivityFunctionType);

@Query(value = "SELECT distinct s.contingency.contingencyId from SensitivityEntity as s")
List<String> findContingencyByResultResultUuidAndFactorFunctionType(UUID resultUuid, SensitivityFunctionType sensitivityFunctionType);

static Specification<SensitivityEntity> getSpecification(AnalysisResultEntity sas,
SensitivityFunctionType functionType,
Collection<String> functionIds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.sensitivity.SensitivityAnalysisProvider;
import org.gridsuite.sensitivityanalysis.server.ResultsSelector;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityAnalysisStatus;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityResultFilterOptions;
import org.gridsuite.sensitivityanalysis.server.dto.SensitivityRunQueryResult;
import org.gridsuite.sensitivityanalysis.server.repositories.SensitivityAnalysisResultRepository;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -63,6 +64,10 @@ public SensitivityRunQueryResult getRunResult(UUID resultUuid, ResultsSelector s
return resultRepository.getRunResult(resultUuid, selector);
}

public SensitivityResultFilterOptions getSensitivityResultOptions(UUID resultUuid, ResultsSelector selector) {
return resultRepository.getSensitivityResultFilterOptions(resultUuid, selector);
}

public void deleteResult(UUID resultUuid) {
resultRepository.delete(resultUuid);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import static org.gridsuite.sensitivityanalysis.server.service.NotificationService.FAIL_MESSAGE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
Expand Down Expand Up @@ -615,6 +616,30 @@ public void runAndSaveTest() throws Exception {
assertEquals(6, (long) resNK.getTotalSensitivitiesCount());
assertEquals(2, resNK.getSensitivities().size());

ResultsSelector filterOptionsSelector = ResultsSelector.builder().isJustBefore(false)
.functionType(SensitivityFunctionType.BRANCH_ACTIVE_POWER_1).build();
result = mockMvc.perform(get("/" + VERSION + "/results/{resultUuid}/filter-options?selector={selector}", RESULT_UUID,
mapper.writeValueAsString(filterOptionsSelector)))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
SensitivityResultFilterOptions filterOptions = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference<>() { });
assertEquals(3, filterOptions.getAllContingencyIds().size());
assertEquals(3, filterOptions.getAllFunctionIds().size());
assertEquals(2, filterOptions.getAllVariableIds().size());

ResultsSelector filterOptionsSelector2 = ResultsSelector.builder().isJustBefore(true)
.functionType(SensitivityFunctionType.BRANCH_ACTIVE_POWER_2).build();
result = mockMvc.perform(get("/" + VERSION + "/results/{resultUuid}/filter-options?selector={selector}", RESULT_UUID,
mapper.writeValueAsString(filterOptionsSelector2)))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
SensitivityResultFilterOptions filterOptions2 = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference<>() { });
assertNull(filterOptions2.getAllContingencyIds());
assertEquals(3, filterOptions2.getAllFunctionIds().size());
assertEquals(2, filterOptions2.getAllVariableIds().size());

// check that a request for not present contingency does not crash and just brings nothing
ResultsSelector selectorNKz1 = ResultsSelector.builder().isJustBefore(false)
.functionType(SensitivityFunctionType.BRANCH_ACTIVE_POWER_1).contingencyIds(List.of("unfoundable")).build();
Expand Down

0 comments on commit e50bb8b

Please sign in to comment.