추론 수정

This commit is contained in:
2026-02-26 23:18:31 +09:00
parent 046f4f06d3
commit 8904de0e3d
8 changed files with 853 additions and 454 deletions

View File

@@ -1,7 +1,5 @@
package com.kamco.cd.kamcoback.inference;
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.Scene;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultShpDto;
import com.kamco.cd.kamcoback.inference.service.InferenceResultShpService;
@@ -12,15 +10,11 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -62,29 +56,4 @@ public class InferenceResultShpApiController {
inferenceResultShpService.createShp(uuid);
return ApiResponseDto.createOK(null);
}
@Operation(summary = "추론실행에 필요한 geojson 파일 생성", description = "추론실행에 필요한 geojson 파일 생성")
@PostMapping("/geojson/{yyyy}/{mapSheetScope}/{detectOption}")
public ApiResponseDto<Scene> createGeojson(
@Schema(description = "년도") @PathVariable String yyyy,
@Schema(description = "전체(ALL),부분(PART)", example = "PART") @PathVariable
String mapSheetScope,
@Schema(description = "추론제외(EXCL),이전 년도 도엽 사용(PREV)", example = "EXCL") @PathVariable
String detectOption,
@Schema(description = "5k도엽번호", example = MAP_ID) @RequestBody Map<String, Object> body) {
Object raw = body.get("mapIds");
if (raw == null) {
throw new CustomApiException("BAD_REQUEST", HttpStatus.BAD_REQUEST);
}
@SuppressWarnings("unchecked")
List<String> mapIds = (List<String>) raw;
Scene scene =
inferenceResultShpService.createGeojson(yyyy, mapSheetScope, detectOption, mapIds);
return ApiResponseDto.createOK(scene);
}
}

View File

@@ -1,9 +1,11 @@
package com.kamco.cd.kamcoback.inference.service;
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter;
import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.ImageFeature;
import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.Scene;
import com.kamco.cd.kamcoback.common.inference.service.InferenceCommonService;
import com.kamco.cd.kamcoback.common.inference.utils.GeoJsonValidator;
import com.kamco.cd.kamcoback.common.utils.UserUtil;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient;
import com.kamco.cd.kamcoback.config.resttemplate.ExternalHttpClient.ExternalCallResult;
@@ -19,7 +21,7 @@ import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.DetectOption;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceLearnDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceServerStatusDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheetFallbackYearDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheetScope;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.SaveInferenceAiDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Status;
@@ -37,6 +39,8 @@ import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService;
import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService;
import com.kamco.cd.kamcoback.postgres.core.ModelMngCoreService;
import jakarta.validation.constraints.NotNull;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.ZonedDateTime;
@@ -87,6 +91,12 @@ public class InferenceResultService {
@Value("${file.dataset-dir}")
private String datasetDir;
@Value("${spring.profiles.active}")
private String activeEnv;
@Value("${inference.geojson-dir}")
private String inferenceDir;
/**
* 추론관리 목록
*
@@ -119,11 +129,11 @@ public class InferenceResultService {
@Transactional
public UUID run(InferenceResultDto.RegReq req) {
if (req.getDetectOption().equals(DetectOption.EXCL.getId())) {
// 추론 제외 일때
// 추론 제외 일때 EXCL
return runExcl(req);
}
// 이전연도 도엽 사용 일때
// 이전연도 도엽 사용 일때 PREV
return runPrev(req);
}
@@ -134,46 +144,70 @@ public class InferenceResultService {
* @return
*/
public UUID runExcl(InferenceResultDto.RegReq req) {
// target 도엽 조회
List<MngListDto> targetDtoList = mapSheetMngCoreService.getHstMapSheetList(req);
// 기준연도 실행가능 도엽 조회
List<MngListDto> mngList =
mapSheetMngCoreService.findExecutableSheets(
req.getCompareYyyy(),
req.getTargetYyyy(),
req.getMapSheetScope(),
req.getMapSheetNum());
if (targetDtoList == null || targetDtoList.isEmpty()) {
throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND, "기준년도 추론가능한 도엽이 없습니다.");
if (mngList == null || mngList.isEmpty()) {
throw new CustomApiException("NOT_FOUND_MAP_SHEET_NUM", HttpStatus.NOT_FOUND);
}
// target 리스트 추출 (null 제거 + 중복 제거)
List<String> targetList =
targetDtoList.stream()
// 비교 연도 도엽번호를 꺼내와서 최종 추론 대상 도엽번호를 담기
List<String> mapSheetNums =
mngList.stream()
.map(MngListDto::getMapSheetNum)
.filter(Objects::nonNull)
.distinct()
.toList();
.collect(Collectors.toList());
// compare 도엽번호 리스트 조회 (null 제거 + 중복 제거), 기준연도와 비교하여 실행하므로 부분, 전체 조건 걸지 않음
List<String> compareList =
mapSheetMngCoreService.getMapSheetNumByHst(req.getCompareYyyy()).stream()
.filter(Objects::nonNull)
.distinct()
.toList();
// 기준연도 추론 실행가능 도엽 count
int targetTotal =
mapSheetMngCoreService.countExecutableSheetsDistinct(
req.getTargetYyyy(), req.getMapSheetScope(), mapSheetNums);
// 비교연도 추론 실행가능 도엽 count
int compareTotal =
mapSheetMngCoreService.countExecutableSheetsDistinct(
req.getCompareYyyy(), req.getMapSheetScope(), mapSheetNums);
int intersection = mapSheetNums.size();
// compare 기준
Set<String> compareSet = new HashSet<>(compareList);
// ===== MapSheet Year Comparison =====
// target Total : 기준연도 실행가능 전체 도엽 수
// compare Total : 비교연도 실행가능 전체 도엽 수
// Intersection : 양 연도에 모두 존재하는 도엽 수 (최종 추론 대상)
// target Only (Excluded) : 기준연도에만 존재하고 비교연도에는 없는 도엽 수
// compare Only : 비교연도에만 존재하고 기준연도에는 없는 도엽 수
// ====================================
// target 기준으로 compare에 존재하는 도엽만 필터링
List<String> filteredTargetList = targetList.stream().filter(compareSet::contains).toList();
log.info(
"""
===== MapSheet Year Comparison =====
target Total: {}
compare Total: {}
Intersection: {}
target Only (Excluded): {}
compare Only: {}
====================================
""",
targetTotal,
compareTotal,
intersection,
targetTotal - intersection,
compareTotal - intersection);
// 도엽 비교 로그 출력
logYearComparison(targetList, compareList, filteredTargetList);
if (filteredTargetList == null || filteredTargetList.isEmpty()) {
throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND, "추론 가능한 도엽을 확인해 주세요.");
if (mapSheetNums.isEmpty()) {
// 추론 가능한 도엽이 없습니다.
throw new CustomApiException("NOT_FOUND_MAP_SHEET_NUM", HttpStatus.NOT_FOUND);
}
// compare geojson 파일 생성
Scene compareScene =
getSceneInference(
req.getCompareYyyy().toString(), // 기준년도
filteredTargetList, // 교집합 도엽
mapSheetNums, // 최종 추론 대상
req.getMapSheetScope(), // ALL / 부분
req.getDetectOption()); // EXCL / PREV
@@ -181,15 +215,20 @@ public class InferenceResultService {
Scene targetScene =
getSceneInference(
req.getTargetYyyy().toString(), // 대상년도
filteredTargetList, // 교집합 도엽
mapSheetNums, // 최종 추론 대상
req.getMapSheetScope(),
req.getDetectOption());
log.info("비교년도 geojson 파일 validation ===== {}", compareScene.getFilePath());
GeoJsonValidator.validateWithRequested(compareScene.getFilePath(), mapSheetNums);
log.info("기준년도 geojson 파일 validation ===== {}", targetScene.getFilePath());
GeoJsonValidator.validateWithRequested(targetScene.getFilePath(), mapSheetNums);
// 추론 실행
return executeInference(
req,
targetDtoList, // 전체 target 목록
filteredTargetList, // 최종 추론 대상
mngList, // 전체 target 목록
mapSheetNums, // 최종 추론 대상
compareScene, // compare geojson
targetScene // target geojson
);
@@ -203,99 +242,100 @@ public class InferenceResultService {
*/
@Transactional
public UUID runPrev(InferenceResultDto.RegReq req) {
// target 목록 조회
List<MngListDto> targetDtoList = mapSheetMngCoreService.getHstMapSheetList(req);
if (targetDtoList == null || targetDtoList.isEmpty()) {
throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND, "기준년도 추론가능한 도엽이 없습니다.");
// 기준연도 실행가능 도엽 조회
List<MngListDto> targetMngList =
mapSheetMngCoreService.getMapSheetMngHst(
req.getTargetYyyy(), req.getMapSheetScope(), req.getMapSheetNum());
if (targetMngList == null || targetMngList.isEmpty()) {
throw new CustomApiException("NOT_FOUND_TARGET_YEAR", HttpStatus.NOT_FOUND);
}
// target 도엽번호 리스트 추출 중복 제거
List<String> targetList =
targetDtoList.stream()
// 비교연도 실행가능 도엽 조회
List<MngListDto> compareMngList =
mapSheetMngCoreService.getMapSheetMngHst(
req.getCompareYyyy(), req.getMapSheetScope(), req.getMapSheetNum());
if (compareMngList == null || compareMngList.isEmpty()) {
throw new CustomApiException("NOT_FOUND_COMPARE_YEAR", HttpStatus.NOT_FOUND);
}
// 로그용 원본 카운트 (fallback 추가 전)
int targetTotal = targetMngList.size();
int compareTotalBeforeFallback = compareMngList.size();
// target - compare 구해서 이전년도로 compare 보완
List<String> compareNums0 =
compareMngList.stream().map(MngListDto::getMapSheetNum).filter(Objects::nonNull).toList();
// 기준연도에 없는 도엽을 비교년도 이전 도엽에서 찾아서 추가하기
List<String> targetOnlyMapSheetNums =
targetMngList.stream()
.map(MngListDto::getMapSheetNum)
.filter(Objects::nonNull)
.distinct()
.filter(num -> !compareNums0.contains(num))
.toList();
// compare 목록 조회
List<MapSheetFallbackYearDto> compareDtoList =
new ArrayList<>(mapSheetMngCoreService.getMapSheetNumDtoByHst(req.getCompareYyyy()));
// compare 도엽번호 Set 구성
Set<String> compareSet =
compareDtoList.stream()
.map(MapSheetFallbackYearDto::getMapSheetNum)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// target에는 있으나 compare에는 없는 도엽 추출
List<String> remainingTargetList =
targetList.stream().filter(s -> !compareSet.contains(s)).toList();
// compare에 없을때 이전 년도 사용 가능여부 조회
List<MapSheetFallbackYearDto> fallbackYearDtoList =
// 이전년도(fallback) 추가
compareMngList.addAll(
mapSheetMngCoreService.findFallbackCompareYearByMapSheets(
req.getTargetYyyy(), // 대상년도 기준
remainingTargetList // compare에 없는 도엽들
);
req.getCompareYyyy(), targetOnlyMapSheetNums));
// 기존 compare , 사용가능 이전년도 정보 합치기
compareDtoList.addAll(fallbackYearDtoList);
// 이전연도 추가 후 compare 총 개수
int compareTotalAfterFallback = compareMngList.size();
// 중복제거하여 사용할 compare 도엽 목록
Set<String> availableCompareSheets =
compareDtoList.stream()
.map(MapSheetFallbackYearDto::getMapSheetNum)
// 교집합 도엽번호(mapSheetNums) 교집합 생성
List<String> compareNums1 =
compareMngList.stream().map(MngListDto::getMapSheetNum).filter(Objects::nonNull).toList();
// 기준연도 교집합
List<String> mapSheetNums =
targetMngList.stream()
.map(MngListDto::getMapSheetNum)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 최종 추론 대상 도엽
// target 기준으로 compare 에 존재하는 도엽만 추출
List<String> filteredTargetList =
targetList.stream().filter(availableCompareSheets::contains).toList();
// compareDtoList도 최종 기준으로 필터
Set<String> filteredTargetSet = new HashSet<>(filteredTargetList);
List<MapSheetFallbackYearDto> filteredCompareDtoList =
compareDtoList.stream()
.filter(d -> d.getMapSheetNum() != null)
.filter(d -> filteredTargetSet.contains(d.getMapSheetNum()))
.filter(compareNums1::contains)
.toList();
// compare only 계산 (target에는 없는 compare 도엽 수) log 용
long compareOnlyCount =
compareDtoList.stream()
.map(MapSheetFallbackYearDto::getMapSheetNum)
.filter(s -> s != null && !targetList.contains(s))
.count();
int intersection = mapSheetNums.size();
// 서로 같은 것만 남기기: compare 모두 교집합
compareMngList =
compareMngList.stream()
.filter(c -> c.getMapSheetNum() != null)
.filter(c -> mapSheetNums.contains(c.getMapSheetNum()))
.toList();
// 로그
int targetOnlyExcluded = targetTotal - intersection;
int compareOnly = compareTotalAfterFallback - intersection;
// 연도별 도엽 비교 로그 출력
log.info(
"""
===== MapSheet Year Comparison =====
target Total: {}
compare Total: {}
Intersection: {}
target Only (Excluded): {}
compare Only: {}
====================================
""",
targetList.size(), // target count
compareDtoList.size(), // compare count
filteredTargetList.size(), // target 기준으로 compare 비교하여 최종 추론할 도엽 count
targetList.size() - filteredTargetList.size(), // compare에 존재하지 않는 target 도엽 수
compareOnlyCount); // target 에 존재하지 않는 compare 도엽수
===== MapSheet Year Comparison =====
target Total: {}
compare Total(before fallback): {}
compare Total(after fallback): {}
Intersection: {}
target Only (Excluded): {}
compare Only: {}
====================================
""",
targetTotal,
compareTotalBeforeFallback,
compareTotalAfterFallback,
intersection,
targetOnlyExcluded,
compareOnly);
if (filteredTargetList == null || filteredTargetList.isEmpty()) {
throw new CustomApiException("NOT_FOUND", HttpStatus.NOT_FOUND, "추론 가능한 도엽을 확인해 주세요.");
if (mapSheetNums.isEmpty()) {
throw new CustomApiException("NOT_FOUND_MAP_SHEET_NUM", HttpStatus.NOT_FOUND);
}
// compare 기준 geojson 생성 (년도 fallback 반영)
// compare 기준 geojson 생성
Scene compareScene =
getSceneInference(
filteredCompareDtoList,
compareMngList,
req.getCompareYyyy().toString(),
req.getMapSheetScope(),
req.getDetectOption());
@@ -304,12 +344,18 @@ public class InferenceResultService {
Scene targetScene =
getSceneInference(
req.getTargetYyyy().toString(),
filteredTargetList,
mapSheetNums,
req.getMapSheetScope(),
req.getDetectOption());
// AI 추론 실행
return executeInference(req, targetDtoList, filteredTargetList, compareScene, targetScene);
log.info("비교년도 geojson 파일 validation ===== {}", compareScene.getFilePath());
GeoJsonValidator.validateWithRequested(compareScene.getFilePath(), mapSheetNums);
log.info("기준년도 geojson 파일 validation ===== {}", targetScene.getFilePath());
GeoJsonValidator.validateWithRequested(targetScene.getFilePath(), mapSheetNums);
// 추론 실행
return executeInference(req, targetMngList, mapSheetNums, compareScene, targetScene);
}
/**
@@ -371,36 +417,6 @@ public class InferenceResultService {
return uuid;
}
/**
* EXCL 로그
*
* @param targetList
* @param compareList
* @param filteredTargetList
*/
private void logYearComparison(
List<String> targetList, List<String> compareList, List<String> filteredTargetList) {
Set<String> targetSet = new HashSet<>(targetList);
long compareOnlyCount = compareList.stream().filter(s -> !targetSet.contains(s)).count();
log.info(
"""
===== MapSheet Year Comparison =====
target Total: {}
compare Total: {}
Intersection: {}
target Only (Excluded): {}
compare Only: {}
====================================
""",
targetList.size(), // target count
compareList.size(), // compare count
filteredTargetList.size(), // target 기준으로 compare 비교하여 최종 추론할 도엽 count
targetList.size() - filteredTargetList.size(), // compare에 존재하지 않는 target 도엽 수
compareOnlyCount); // target 에 존재하지 않는 compare 도엽수
}
/**
* 변화탐지 실행 정보 생성 TODO 미사용, 새로운 추론실행 로직 테스트후 삭제 해야합니다.
*
@@ -410,7 +426,7 @@ public class InferenceResultService {
public UUID saveInferenceInfo(InferenceResultDto.RegReq req) {
// 변화탐지 실행 가능 기준 년도 조회
List<MngListDto> targetList = mapSheetMngCoreService.getHstMapSheetList(req);
List<MngListDto> targetList = null; // mapSheetMngCoreService.getHstMapSheetList(req);
if (targetList.isEmpty()) {
throw new CustomApiException("NOT_FOUND_TARGET_YEAR", HttpStatus.NOT_FOUND);
@@ -607,25 +623,36 @@ public class InferenceResultService {
*/
private Scene getSceneInference(
String yyyy, List<String> mapSheetNums, String mapSheetScope, String detectOption) {
return mapSheetMngCoreService.getSceneInference(
yyyy, mapSheetNums, mapSheetScope, detectOption);
// geojson 생성시 필요한 영상파일 정보 조회
List<ImageFeature> features =
mapSheetMngCoreService.loadSceneInferenceBySheets(yyyy, mapSheetNums);
if (features == null || features.isEmpty()) {
log.warn(
"NOT_FOUND_MAP_SHEET_NUM : yyyy={}, scenesSize={}",
yyyy,
mapSheetNums == null ? 0 : mapSheetNums.size());
throw new CustomApiException("NOT_FOUND_MAP_SHEET_NUM", HttpStatus.NOT_FOUND);
}
return writeSceneGeoJson(yyyy, mapSheetScope, detectOption, features);
}
/**
* 년도 별로 조회하여 geojson 파일 생성
*
* @param yearDtos
* @param year
* @param yyyy
* @param mapSheetScope
* @param detectOption
* @return
*/
private Scene getSceneInference(
List<MapSheetFallbackYearDto> yearDtos,
String year,
String mapSheetScope,
String detectOption) {
return mapSheetMngCoreService.getSceneInference(yearDtos, year, mapSheetScope, detectOption);
List<MngListDto> yearDtos, String yyyy, String mapSheetScope, String detectOption) {
List<ImageFeature> features =
mapSheetMngCoreService.loadSceneInferenceByFallbackYears(yearDtos);
return writeSceneGeoJson(yyyy, mapSheetScope, detectOption, features);
}
/**
@@ -865,4 +892,69 @@ public class InferenceResultService {
public List<String> getInferenceRunMapId(UUID uuid) {
return inferenceResultCoreService.getInferenceRunMapId(uuid);
}
/**
* 파일 경로/이름 , 파일 생성 , 도엽번호 반환
*
* @param yyyy
* @param mapSheetScope
* @param detectOption
* @param sceneInference
* @return Scene
*/
private Scene writeSceneGeoJson(
String yyyy, String mapSheetScope, String detectOption, List<ImageFeature> sceneInference) {
boolean isAll = MapSheetScope.ALL.getId().equals(mapSheetScope);
String optionSuffix = buildOptionSuffix(detectOption);
String targetDir =
"local".equals(activeEnv) ? System.getProperty("user.home") + "/geojson" : inferenceDir;
// 파일명 생성
String filename =
isAll
? String.format("%s_%s_ALL%s.geojson", yyyy, activeEnv, optionSuffix)
: String.format("%s_%s%s.geojson", yyyy, activeEnv, optionSuffix);
Path outputPath = Paths.get(targetDir, filename);
try {
log.info("create Directories outputPath: {}", outputPath);
log.info(
"activeEnv={}, inferenceDir={}, targetDir={}, filename={}",
activeEnv,
inferenceDir,
targetDir,
filename);
log.info("outputPath={}, parent={}", outputPath.toAbsolutePath(), outputPath.getParent());
Files.createDirectories(outputPath.getParent());
new GeoJsonFileWriter()
.exportToFile(sceneInference, "scene_inference_" + yyyy, 5186, outputPath.toString());
Scene scene = new Scene();
scene.setFeatures(sceneInference);
scene.setFilePath(outputPath.toString());
return scene;
} catch (IOException e) {
log.error(
"FAIL_CREATE_MAP_SHEET_FILE: yyyy={}, isAll={}, path={}", yyyy, isAll, outputPath, e);
throw new CustomApiException("INTERNAL_SERVER_ERROR", HttpStatus.INTERNAL_SERVER_ERROR, e);
}
}
/**
* geojson 파일명 Suffix
*
* @param detectOption
* @return
*/
private String buildOptionSuffix(String detectOption) {
if (DetectOption.EXCL.getId().equals(detectOption)) return "_EXCL";
if (DetectOption.PREV.getId().equals(detectOption)) return "_PREV";
return "";
}
}

View File

@@ -1,13 +1,11 @@
package com.kamco.cd.kamcoback.inference.service;
import com.kamco.cd.kamcoback.common.geometry.GeoJsonFileWriter.Scene;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceLearnDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultShpDto;
import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService;
import com.kamco.cd.kamcoback.postgres.core.InferenceResultShpCoreService;
import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService;
import com.kamco.cd.kamcoback.scheduler.service.ShpPipelineService;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -66,21 +64,4 @@ public class InferenceResultShpService {
// shp 파일 비동기 생성
shpPipelineService.runPipeline(jarPath, datasetDir, batchId, dto.getUid());
}
/**
* 추론 실행전 geojson 파일 생성
*
* @param yyyy
* @param mapSheetScope
* @param detectOption
* @param mapIds
* @return
*/
public Scene createGeojson(
String yyyy, String mapSheetScope, String detectOption, List<String> mapIds) {
Scene getSceneInference =
mapSheetMngCoreService.getSceneInference(yyyy, mapIds, mapSheetScope, detectOption);
log.info("getSceneInference: {}", getSceneInference);
return getSceneInference;
}
}