From 045404047755f0f63de242f1209156daff32c5b9 Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Sun, 20 Oct 2024 20:32:28 +0200 Subject: [PATCH 01/13] fetch only one estimator --- .../Results/EstimatorTab/EstimatorTab.tsx | 77 +++++++++ .../EstimatorsSelect/EstimatorsSelect.tsx | 111 +++++++++++++ .../components/Results/ResultsPanel.tsx | 147 ++++-------------- src/services/ShSimulatorService.tsx | 101 +++++++++++- src/types/RequestTypes.ts | 4 + src/types/ResponseTypes.ts | 5 +- 6 files changed, 327 insertions(+), 118 deletions(-) create mode 100644 src/WrapperApp/components/Results/EstimatorTab/EstimatorTab.tsx create mode 100644 src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx diff --git a/src/WrapperApp/components/Results/EstimatorTab/EstimatorTab.tsx b/src/WrapperApp/components/Results/EstimatorTab/EstimatorTab.tsx new file mode 100644 index 000000000..3643dfa9d --- /dev/null +++ b/src/WrapperApp/components/Results/EstimatorTab/EstimatorTab.tsx @@ -0,0 +1,77 @@ +import { Box, Card, CardContent, CircularProgress } from '@mui/material'; + +import { generateGraphs } from '../../../../JsRoot/GraphData'; +import { FullSimulationData } from '../../../../services/ShSimulatorService'; +import { TabPanel } from '../../Panels/TabPanel'; +import { EstimatorResults } from '../ResultsPanel'; +import TablePage0D from '../ResultsTable'; + +interface EstimatorTabProps { + estimator: EstimatorResults; + tabsValue: number; + resultsGeneratedFromProjectFile: boolean; + groupQuantities: boolean; + simulation: FullSimulationData; +} + +const EstimatorTab = ({ + estimator, + tabsValue, + resultsGeneratedFromProjectFile, + groupQuantities, + simulation +}: EstimatorTabProps) => { + return ( + + theme.palette.mode === 'dark' ? 'text.disabled' : 'background.paper', + '& .MuiCardContent-root div': { + bgcolor: 'transparent', + backgroundImage: 'none', + color: 'black' + } + }}> + {!estimator ? ( + + + + ) : ( + + + + {estimator.tablePages.length > 0 && ( + + )} + {generateGraphs( + estimator, + resultsGeneratedFromProjectFile && groupQuantities, + simulation?.jobId + )} + + + + )} + + ); +}; + +export default EstimatorTab; diff --git a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx new file mode 100644 index 000000000..ae3e7b440 --- /dev/null +++ b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx @@ -0,0 +1,111 @@ +import { Card, CardContent, Tab, Tabs } from '@mui/material'; +import { SyntheticEvent, useCallback, useState } from 'react'; + +import { FullSimulationData, useShSimulation } from '../../../../services/ShSimulatorService'; + +interface EstimatorsTabProps { + tabsValue: number; + setTabsValue: (value: number) => void; + simulation: FullSimulationData; + setResultsSimulationData: React.Dispatch>; + estimatorsTabData: string[]; +} + +const EstimatorsSelect = ({ + tabsValue, + setTabsValue, + simulation, + setResultsSimulationData, + estimatorsTabData +}: EstimatorsTabProps) => { + const [controller] = useState(new AbortController()); + + const { getJobResult } = useShSimulation(); + + const handleEstimatorTabChange = useCallback( + async (id: number) => { + const currentEstimatorData = simulation.estimators; + const estimatorExists = currentEstimatorData.some( + estimator => estimator.name === estimatorsTabData[id] + ); + + if (!estimatorExists) { + const simulationJobId = simulation.jobId; + + const estimatorData = await getJobResult( + { + jobId: simulationJobId, + estimatorName: estimatorsTabData[id] + '_' + }, + controller.signal, + true + ); + + const newEstimatorData = estimatorData?.estimators; + + if (newEstimatorData) { + const newSimulation = { + ...simulation, + estimators: [...currentEstimatorData, ...newEstimatorData] + }; + setResultsSimulationData(newSimulation); + } + } + }, + [controller.signal, estimatorsTabData, getJobResult, setResultsSimulationData, simulation] + ); + + const handleChange = (_event: SyntheticEvent, newValue: number) => { + setTabsValue(newValue); + }; + + return ( + + + theme.palette.mode === 'dark' ? 'secondary.contrastText' : 'secondary.dark' + }}> + + theme.palette.mode === 'dark' + ? 'secondary.contrastText' + : 'secondary.dark' + }, + '& .MuiButtonBase-root': { + fontWeight: 'bold' + } + }} + orientation='vertical' + variant='scrollable' + value={tabsValue} + onChange={handleChange}> + {estimatorsTabData.map((estimatorName, id) => { + return ( + handleEstimatorTabChange(id)} + /> + ); + })} + + + + ); +}; + +export default EstimatorsSelect; diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index d4a6aaacd..2157876a9 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -1,45 +1,40 @@ -import { - Box, - Button, - Card, - CardContent, - FormControlLabel, - Switch, - Tab, - Tabs, - Typography -} from '@mui/material'; -import { ChangeEvent, SyntheticEvent, useEffect, useState } from 'react'; +import { Box, Button, Card, FormControlLabel, Switch, Typography } from '@mui/material'; +import { ChangeEvent, useEffect, useState } from 'react'; -import { Estimator, generateGraphs, isPage0d, Page, Page0D } from '../../../JsRoot/GraphData'; +import { Estimator, isPage0d, Page, Page0D } from '../../../JsRoot/GraphData'; import { useDialog } from '../../../services/DialogService'; import { useStore } from '../../../services/StoreService'; import { InfoTooltip } from '../../../shared/components/tooltip/InfoTooltip'; import { titleToKebabCase } from '../../../ThreeEditor/components/Dialog/CustomDialog'; -import { TabPanel } from '../Panels/TabPanel'; -import TablePage0D from './ResultsTable'; +import EstimatorsSelect from './EstimatorsSelect/EstimatorsSelect'; +import EstimatorTab from './EstimatorTab/EstimatorTab'; export interface EstimatorResults extends Estimator { tablePages: Page0D[]; gridPages: Page[]; } +const estimatorsTabData: string[] = ['z_profile', 'yz_profile', 'entrance', 'peak']; + function ResultsPanel() { const { open: openSaveFileDialog } = useDialog('saveFile'); - const { yaptideEditor, resultsSimulationData: simulation } = useStore(); + const { + yaptideEditor, + resultsSimulationData: simulation, + setResultsSimulationData + } = useStore(); const [tabsValue, setTabsValue] = useState(0); const [estimatorsResults, setEstimatorsResults] = useState([]); const [groupQuantities, setGroupQuantities] = useState(false); useEffect(() => { - setTabsValue(0); setEstimatorsResults(parseEstimators(simulation?.estimators ?? [])); - }, [simulation]); - const handleChange = (_event: SyntheticEvent, newValue: number) => { - setTabsValue(newValue); - }; + if (simulation?.estimators.length === 1) { + setTabsValue(0); + } + }, [simulation]); const onClickSaveToFile = () => { if (yaptideEditor) @@ -64,6 +59,9 @@ function ResultsPanel() { }; const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; + const chosenEstimator = estimatorsResults.filter( + estimator => estimator.name === estimatorsTabData[tabsValue] + )[0]; return ( - {estimatorsResults.length > 0 && ( + {estimatorsResults.length > 0 && simulation && ( <> - - - theme.palette.mode === 'dark' - ? 'secondary.contrastText' - : 'secondary.dark' - }}> - - theme.palette.mode === 'dark' - ? 'secondary.contrastText' - : 'secondary.dark' - }, - '& .MuiButtonBase-root': { - fontWeight: 'bold' - } - }} - orientation='vertical' - variant='scrollable' - value={tabsValue} - onChange={handleChange}> - {estimatorsResults.map((estimator, idx) => { - return ( - - ); - })} - - - - - theme.palette.mode === 'dark' - ? 'text.disabled' - : 'background.paper', - '& .MuiCardContent-root div': { - bgcolor: 'transparent', - backgroundImage: 'none', - color: 'black' - } - }}> - - {estimatorsResults.map((estimator, idx) => { - return ( - - - {estimator.tablePages.length > 0 && ( - - )} - {generateGraphs( - estimator, - resultsGeneratedFromProjectFile && - groupQuantities, - simulation?.jobId - )} - - - ); - })} - - + + )} diff --git a/src/services/ShSimulatorService.tsx b/src/services/ShSimulatorService.tsx index 868d3fb65..4970967ab 100644 --- a/src/services/ShSimulatorService.tsx +++ b/src/services/ShSimulatorService.tsx @@ -1,3 +1,5 @@ +import { isPromise } from 'node:util/types'; + import { useCallback } from 'react'; import { Estimator } from '../JsRoot/GraphData'; @@ -10,6 +12,7 @@ import { RequestCancelJob, RequestGetJobInputs, RequestGetJobLogs, + RequestGetJobResult, RequestGetJobResults, RequestGetJobStatus, RequestGetPageContents, @@ -27,6 +30,7 @@ import { PlatformType, ResponseGetJobInputs, ResponseGetJobLogs, + ResponseGetJobResult, ResponseGetJobResults, ResponseGetJobStatus, ResponseGetPageContents, @@ -40,6 +44,7 @@ import { useCacheMap } from '../util/hooks/useCacheMap'; import { camelToSnakeCase } from '../util/Notation/Notation'; import { orderAccordingToList } from '../util/Sort'; import { ValidateShape } from '../util/Types'; +import { EstimatorResults } from '../WrapperApp/components/Results/ResultsPanel'; import { SimulationSourceType } from '../WrapperApp/components/Simulation/RunSimulationForm'; import { useAuth } from './AuthService'; import { createGenericContext, GenericContextProviderProps } from './GenericContext'; @@ -69,13 +74,15 @@ export interface RestSimulationContext { getJobStatus: (...args: RequestGetJobStatus) => Promise; getJobInputs: (...args: RequestGetJobInputs) => Promise; getJobResults: (...args: RequestGetJobResults) => Promise; + getJobResult: (...args: RequestGetJobResult) => Promise; getJobLogs: (...args: RequestGetJobLogs) => Promise; getPageContents: (...args: RequestGetPageContents) => Promise; getPageStatus: (...args: RequestGetPageStatus) => Promise; getFullSimulationData: ( jobStatus: JobStatusData, signal?: AbortSignal, - cache?: boolean + cache?: boolean, + givenEstimatorName?: string ) => Promise; } @@ -330,6 +337,77 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { [authKy, getJobInputs, resultsCache] ); + const getJobResult = useCallback( + async (...[info, signal, cache = true, beforeCacheWrite]: RequestGetJobResult) => { + const { jobId, estimatorName } = info; + + if (cache && resultsCache.has(jobId)) { + const data: Promise | JobResults | undefined = resultsCache.get(jobId); + + if (data instanceof Promise) { + return data.then(resolvedData => { + const estimators = resolvedData.estimators; + const estimatorExists = estimators.some( + estimator => estimator.name === estimatorName + ); + + if (estimatorExists) return Promise.resolve(resolvedData); + }); + } else if (data) { + const estimators = data.estimators; + const estimatorExists = estimators.some( + estimator => estimator.name === estimatorName + ); + + if (estimatorExists) return Promise.resolve(data); + } + } + + const cachePromise = resultsCache.createPromise( + async resolve => { + const response = await authKy + .get('results', { + signal, + searchParams: camelToSnakeCase({ + job_id: jobId, + estimator_name: estimatorName + }) + }) + .json(); + + const estimator: Estimator[] = [ + { + name: response.name, + metadata: response.metadata, + pages: response.pages + } + ]; + + updateEstimators(estimator); + + const jobInputs = await getJobInputs(info, signal, cache); + + const refsInResults = + jobInputs?.input.inputJson && + recreateRefsInResults(jobInputs.input.inputJson, estimator); + + const data: JobResults = { + ...response, + jobId, + estimators: refsInResults ?? estimator + }; + + resolve(data); + }, + jobId, + beforeCacheWrite + ); + + return await cachePromise; + }, + [authKy, getJobInputs, resultsCache] + ); + //TODO: fix backend responses and remove this function const validStatusToCache = (data: JobStatusCompleted | JobStatusFailed) => { if (data.jobState === StatusState.FAILED) return true; @@ -448,11 +526,25 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { ); const getFullSimulationData = useCallback( - async (jobStatus: JobStatusData, signal?: AbortSignal, cache = true) => { + async ( + jobStatus: JobStatusData, + signal?: AbortSignal, + cache = true, + givenEstimatorName?: string + ) => { const inputs: JobInputs | undefined = await getJobInputs(jobStatus, signal, cache); const results: JobResults | undefined = jobStatus.jobState === StatusState.COMPLETED - ? await getJobResults(jobStatus, signal, cache) + ? await getJobResult( + { + jobId: jobStatus.jobId, + estimatorName: givenEstimatorName + ? givenEstimatorName + : 'z_profile_' + }, + signal, + cache + ) : undefined; if (!inputs || !results) return undefined; @@ -469,7 +561,7 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { return simData; }, - [getJobInputs, getJobResults] + [getJobInputs, getJobResult] ); return ( @@ -487,6 +579,7 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { getPageStatus, getJobInputs, getJobResults, + getJobResult, getJobLogs, getFullSimulationData }}> diff --git a/src/types/RequestTypes.ts b/src/types/RequestTypes.ts index 05b985d15..a1273555b 100644 --- a/src/types/RequestTypes.ts +++ b/src/types/RequestTypes.ts @@ -100,4 +100,8 @@ export type RequestGetJobResults = Flatten< [[{ jobId: string }], RequestParam, CachedDataParams] >; +export type RequestGetJobResult = Flatten< + [[{ jobId: string; estimatorName: string }], RequestParam, CachedDataParams] +>; + /* ------------------------------------ */ diff --git a/src/types/ResponseTypes.ts b/src/types/ResponseTypes.ts index bcca956d1..384598386 100644 --- a/src/types/ResponseTypes.ts +++ b/src/types/ResponseTypes.ts @@ -1,5 +1,6 @@ -import { Estimator } from '../JsRoot/GraphData'; +import { Estimator, Page } from '../JsRoot/GraphData'; import { EditorJson } from '../ThreeEditor/js/EditorJson'; +import { ScoringOutputJSON } from '../ThreeEditor/Simulation/Scoring/ScoringOutput'; import { SimulationSourceType } from '../WrapperApp/components/Simulation/RunSimulationForm'; import { DataWithStatus, LookUp, TypeIdentifiedByKey } from './TypeTransformUtil'; @@ -341,6 +342,8 @@ export type ResponseGetJobResults = { estimators: Estimator[]; } & YaptideResponse; +export type ResponseGetJobResult = Estimator & YaptideResponse; + export type ResponseAuthStatus = AuthStatus; export type ResponseAuthRefresh = AuthData; From fa10e345d03920447a5bb4e54c4235bdab1fe2bd Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Mon, 21 Oct 2024 23:30:43 +0200 Subject: [PATCH 02/13] get state of estiamtors order --- .../Results/EstimatorsSelect/EstimatorsSelect.tsx | 6 +++++- src/WrapperApp/components/Results/ResultsPanel.tsx | 11 +++++++++-- src/services/ShSimulatorService.tsx | 7 +++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx index ae3e7b440..bc546959f 100644 --- a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx +++ b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx @@ -1,5 +1,5 @@ import { Card, CardContent, Tab, Tabs } from '@mui/material'; -import { SyntheticEvent, useCallback, useState } from 'react'; +import { SyntheticEvent, useCallback, useEffect, useState } from 'react'; import { FullSimulationData, useShSimulation } from '../../../../services/ShSimulatorService'; @@ -55,6 +55,10 @@ const EstimatorsSelect = ({ [controller.signal, estimatorsTabData, getJobResult, setResultsSimulationData, simulation] ); + useEffect(() => { + handleEstimatorTabChange(0); + }, [handleEstimatorTabChange]); + const handleChange = (_event: SyntheticEvent, newValue: number) => { setTabsValue(newValue); }; diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 2157876a9..63fffc4e0 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -14,8 +14,6 @@ export interface EstimatorResults extends Estimator { gridPages: Page[]; } -const estimatorsTabData: string[] = ['z_profile', 'yz_profile', 'entrance', 'peak']; - function ResultsPanel() { const { open: openSaveFileDialog } = useDialog('saveFile'); const { @@ -28,6 +26,11 @@ function ResultsPanel() { const [estimatorsResults, setEstimatorsResults] = useState([]); const [groupQuantities, setGroupQuantities] = useState(false); + const estimatorsTabData: string[] | undefined = + simulation?.input.inputJson?.scoringManager.outputs + .filter(output => output.name) + .map(output => output.name); + useEffect(() => { setEstimatorsResults(parseEstimators(simulation?.estimators ?? [])); @@ -58,6 +61,10 @@ function ResultsPanel() { return estimatorResults; }; + if (!estimatorsTabData) { + return null; + } + const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; const chosenEstimator = estimatorsResults.filter( estimator => estimator.name === estimatorsTabData[tabsValue] diff --git a/src/services/ShSimulatorService.tsx b/src/services/ShSimulatorService.tsx index 4970967ab..bbcd01d1b 100644 --- a/src/services/ShSimulatorService.tsx +++ b/src/services/ShSimulatorService.tsx @@ -533,14 +533,17 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { givenEstimatorName?: string ) => { const inputs: JobInputs | undefined = await getJobInputs(jobStatus, signal, cache); + const firstEstimatorName = + inputs?.input.inputJson?.scoringManager.outputs[0].name + '_'; + const results: JobResults | undefined = - jobStatus.jobState === StatusState.COMPLETED + jobStatus.jobState === StatusState.COMPLETED && firstEstimatorName ? await getJobResult( { jobId: jobStatus.jobId, estimatorName: givenEstimatorName ? givenEstimatorName - : 'z_profile_' + : firstEstimatorName }, signal, cache From 06769f42df3d9466e4ec775ce1a4e654448dbb30 Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Thu, 31 Oct 2024 16:41:54 +0100 Subject: [PATCH 03/13] some changes --- .../components/InputEditor/InputFilesEditor.tsx | 14 ++++++++++++++ src/services/ShSimulatorService.tsx | 5 ++--- src/types/ResponseTypes.ts | 5 ++++- src/util/Sort.ts | 2 -- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx b/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx index e9797ff58..2924d4670 100644 --- a/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx +++ b/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx @@ -37,6 +37,20 @@ export function InputFilesEditor(props: InputFilesEditorProps) { const largeFileSize = 100_000; const largeFileLinesLimit = 500; + // const estimatorNames = []; + // + // if (inputFiles) { + // const regex = /Filename\s+(\w+)\.bdo/g; + // let match; + // + // while ((match = regex.exec(inputFiles.)) !== null) { + // estimatorNames.push(match[1]); + // } + // } + // + // console.log(estimatorNames); + // + const canBeDeleted = (name: string) => { switch (props.simulator) { case SimulatorType.SHIELDHIT: diff --git a/src/services/ShSimulatorService.tsx b/src/services/ShSimulatorService.tsx index bbcd01d1b..c14314101 100644 --- a/src/services/ShSimulatorService.tsx +++ b/src/services/ShSimulatorService.tsx @@ -533,8 +533,7 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { givenEstimatorName?: string ) => { const inputs: JobInputs | undefined = await getJobInputs(jobStatus, signal, cache); - const firstEstimatorName = - inputs?.input.inputJson?.scoringManager.outputs[0].name + '_'; + const firstEstimatorName = inputs?.input.inputJson?.scoringManager.outputs[0].name; const results: JobResults | undefined = jobStatus.jobState === StatusState.COMPLETED && firstEstimatorName @@ -543,7 +542,7 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { jobId: jobStatus.jobId, estimatorName: givenEstimatorName ? givenEstimatorName - : firstEstimatorName + : firstEstimatorName + '_' }, signal, cache diff --git a/src/types/ResponseTypes.ts b/src/types/ResponseTypes.ts index 384598386..4a6c5ce44 100644 --- a/src/types/ResponseTypes.ts +++ b/src/types/ResponseTypes.ts @@ -61,7 +61,10 @@ export type InputFilesRecord; -type ShInputFilesRecord = InputFilesRecord; +export type ShInputFilesRecord = InputFilesRecord< + ShInputFilesNames, + 'info.json' | 'sobp.dat' | 'detect.dat' +>; type TopasInputFilesRecord = InputFilesRecord; type FlukaInputFilesRecord = InputFilesRecord; export type SimulationInputFiles = diff --git a/src/util/Sort.ts b/src/util/Sort.ts index 98f96c375..fcf283afd 100644 --- a/src/util/Sort.ts +++ b/src/util/Sort.ts @@ -14,8 +14,6 @@ export const orderAccordingToList = Date: Sun, 17 Nov 2024 22:40:35 +0100 Subject: [PATCH 04/13] use estimators name given from backend --- .../InputEditor/InputFilesEditor.tsx | 18 +---- .../components/Results/ResultsPanel.tsx | 9 +-- src/services/ShSimulatorService.tsx | 71 +++++++++++++++++-- src/types/ResponseTypes.ts | 6 ++ 4 files changed, 76 insertions(+), 28 deletions(-) diff --git a/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx b/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx index 2924d4670..ec2666f10 100644 --- a/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx +++ b/src/WrapperApp/components/InputEditor/InputFilesEditor.tsx @@ -37,27 +37,11 @@ export function InputFilesEditor(props: InputFilesEditorProps) { const largeFileSize = 100_000; const largeFileLinesLimit = 500; - // const estimatorNames = []; - // - // if (inputFiles) { - // const regex = /Filename\s+(\w+)\.bdo/g; - // let match; - // - // while ((match = regex.exec(inputFiles.)) !== null) { - // estimatorNames.push(match[1]); - // } - // } - // - // console.log(estimatorNames); - // - const canBeDeleted = (name: string) => { switch (props.simulator) { case SimulatorType.SHIELDHIT: return !(name in _defaultShInputFiles); - // Topas is not supported in current version of yaptide - // case SimulatorType.TOPAS: - // return !(name in _defaultTopasInputFiles); + case SimulatorType.FLUKA: return !(name in _defaultFlukaInputFiles); default: diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 63fffc4e0..6415941b7 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -26,10 +26,11 @@ function ResultsPanel() { const [estimatorsResults, setEstimatorsResults] = useState([]); const [groupQuantities, setGroupQuantities] = useState(false); - const estimatorsTabData: string[] | undefined = - simulation?.input.inputJson?.scoringManager.outputs - .filter(output => output.name) - .map(output => output.name); + const estimatorsTabData: string[] | undefined = simulation?.input.inputFilesEstimatorNames + ? simulation.input.inputFilesEstimatorNames.map(output => output.slice(0, -1)) + : simulation?.input.inputJson?.scoringManager.outputs + .filter(output => output.name) + .map(output => output.name); useEffect(() => { setEstimatorsResults(parseEstimators(simulation?.estimators ?? [])); diff --git a/src/services/ShSimulatorService.tsx b/src/services/ShSimulatorService.tsx index c14314101..f219f8d06 100644 --- a/src/services/ShSimulatorService.tsx +++ b/src/services/ShSimulatorService.tsx @@ -1,5 +1,3 @@ -import { isPromise } from 'node:util/types'; - import { useCallback } from 'react'; import { Estimator } from '../JsRoot/GraphData'; @@ -24,6 +22,7 @@ import { import { currentJobStatusData, currentTaskStatusData, + EstimatorNamesResponse, JobStatusCompleted, JobStatusData, JobStatusFailed, @@ -44,7 +43,6 @@ import { useCacheMap } from '../util/hooks/useCacheMap'; import { camelToSnakeCase } from '../util/Notation/Notation'; import { orderAccordingToList } from '../util/Sort'; import { ValidateShape } from '../util/Types'; -import { EstimatorResults } from '../WrapperApp/components/Results/ResultsPanel'; import { SimulationSourceType } from '../WrapperApp/components/Simulation/RunSimulationForm'; import { useAuth } from './AuthService'; import { createGenericContext, GenericContextProviderProps } from './GenericContext'; @@ -408,6 +406,23 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { [authKy, getJobInputs, resultsCache] ); + const getCurrentEstimators = useCallback( + async (job_id: string) => { + try { + return await authKy + .get('estimators', { + searchParams: { job_id } + }) + .json(); + } catch (error) { + console.error('Failed to fetch estimators:', error); + + return undefined; + } + }, + [authKy] + ); + //TODO: fix backend responses and remove this function const validStatusToCache = (data: JobStatusCompleted | JobStatusFailed) => { if (data.jobState === StatusState.FAILED) return true; @@ -525,6 +540,43 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { [getJobStatus] ); + const findFirstEstimatorName = useCallback( + async ( + jobStatus: JobStatusData, + inputs: JobInputs | undefined, + givenEstimatorName?: string + ) => { + const firstEstimatorName = inputs?.input.inputJson?.scoringManager.outputs[0].name; + + if ( + !givenEstimatorName && + !firstEstimatorName && + jobStatus.jobState === StatusState.COMPLETED + ) { + const estimators = await getCurrentEstimators(jobStatus.jobId); + + if (inputs) { + inputs.input.inputFilesEstimatorNames = estimators?.estimatorNames; + } + } + + const firstEstimatorInputFileName = inputs?.input.inputFilesEstimatorNames?.[0]; + + if (givenEstimatorName) { + return givenEstimatorName; + } + + if (firstEstimatorInputFileName) { + return firstEstimatorInputFileName; + } + + if (firstEstimatorName) { + return firstEstimatorName + '_'; + } + }, + [getCurrentEstimators] + ); + const getFullSimulationData = useCallback( async ( jobStatus: JobStatusData, @@ -533,16 +585,21 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { givenEstimatorName?: string ) => { const inputs: JobInputs | undefined = await getJobInputs(jobStatus, signal, cache); - const firstEstimatorName = inputs?.input.inputJson?.scoringManager.outputs[0].name; + + const firstEstimator = await findFirstEstimatorName( + jobStatus, + inputs, + givenEstimatorName + ); const results: JobResults | undefined = - jobStatus.jobState === StatusState.COMPLETED && firstEstimatorName + jobStatus.jobState === StatusState.COMPLETED && firstEstimator ? await getJobResult( { jobId: jobStatus.jobId, estimatorName: givenEstimatorName ? givenEstimatorName - : firstEstimatorName + '_' + : firstEstimator }, signal, cache @@ -563,7 +620,7 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { return simData; }, - [getJobInputs, getJobResult] + [findFirstEstimatorName, getJobInputs, getJobResult] ); return ( diff --git a/src/types/ResponseTypes.ts b/src/types/ResponseTypes.ts index 4a6c5ce44..166f92745 100644 --- a/src/types/ResponseTypes.ts +++ b/src/types/ResponseTypes.ts @@ -334,9 +334,15 @@ export type ResponseGetJobInputs = { inputFiles: SimulationInputFiles; inputJson?: EditorJson; inputType: SimulationSourceType; + inputFilesEstimatorNames?: string[]; }; } & YaptideResponse; +export type EstimatorNamesResponse = { + estimatorNames: string[]; + message: string; +}; + export type ResponseGetJobLogs = { logfiles: Record; } & YaptideResponse; From 601f505ca2feb0831e90e2a63e4f31f2e5180e94 Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Mon, 18 Nov 2024 15:40:30 +0100 Subject: [PATCH 05/13] little changes --- src/services/ShSimulatorService.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/ShSimulatorService.tsx b/src/services/ShSimulatorService.tsx index f219f8d06..be562349d 100644 --- a/src/services/ShSimulatorService.tsx +++ b/src/services/ShSimulatorService.tsx @@ -553,9 +553,9 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { !firstEstimatorName && jobStatus.jobState === StatusState.COMPLETED ) { - const estimators = await getCurrentEstimators(jobStatus.jobId); + if (inputs && !inputs.input.inputFilesEstimatorNames) { + const estimators = await getCurrentEstimators(jobStatus.jobId); - if (inputs) { inputs.input.inputFilesEstimatorNames = estimators?.estimatorNames; } } From 45f2ef0cddb0c0800593144093d2f5a2a9a57b81 Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Mon, 18 Nov 2024 18:17:18 +0100 Subject: [PATCH 06/13] fix some bug --- .../Results/EstimatorsSelect/EstimatorsSelect.tsx | 8 +++++--- src/WrapperApp/components/Results/ResultsPanel.tsx | 12 +++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx index bc546959f..42758bed5 100644 --- a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx +++ b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx @@ -11,6 +11,8 @@ interface EstimatorsTabProps { estimatorsTabData: string[]; } +const FLUKKA_EXMAPLE_ESTIMATOR_NAMES = ['AlongBeamAxis', 'SlabYZ']; + const EstimatorsSelect = ({ tabsValue, setTabsValue, @@ -25,9 +27,9 @@ const EstimatorsSelect = ({ const handleEstimatorTabChange = useCallback( async (id: number) => { const currentEstimatorData = simulation.estimators; - const estimatorExists = currentEstimatorData.some( - estimator => estimator.name === estimatorsTabData[id] - ); + const estimatorExists = + currentEstimatorData.some(estimator => estimator.name === estimatorsTabData[id]) || + estimatorsTabData[id] === FLUKKA_EXMAPLE_ESTIMATOR_NAMES[id]; if (!estimatorExists) { const simulationJobId = simulation.jobId; diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 6415941b7..5051eb567 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -14,6 +14,8 @@ export interface EstimatorResults extends Estimator { gridPages: Page[]; } +const FLUKKA_EXMAPLE_RESULTS_NAMES = ['21', '22']; + function ResultsPanel() { const { open: openSaveFileDialog } = useDialog('saveFile'); const { @@ -67,8 +69,16 @@ function ResultsPanel() { } const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; + const isFlukkaExample = estimatorsResults.some( + estimator => estimator.name === FLUKKA_EXMAPLE_RESULTS_NAMES[tabsValue] + ); + const chosenEstimator = estimatorsResults.filter( - estimator => estimator.name === estimatorsTabData[tabsValue] + estimator => + estimator.name === + (isFlukkaExample + ? FLUKKA_EXMAPLE_RESULTS_NAMES[tabsValue] + : estimatorsTabData[tabsValue]) )[0]; return ( From c79fb7187007114d7c229169b6a961b1c9640150 Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Tue, 19 Nov 2024 09:17:28 +0100 Subject: [PATCH 07/13] delete hard code --- .../EstimatorsSelect/EstimatorsSelect.tsx | 19 ++++++++++++++----- .../components/Results/ResultsPanel.tsx | 17 +++++------------ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx index 42758bed5..7671c46a4 100644 --- a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx +++ b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx @@ -9,16 +9,16 @@ interface EstimatorsTabProps { simulation: FullSimulationData; setResultsSimulationData: React.Dispatch>; estimatorsTabData: string[]; + isFlukaExample: boolean; } -const FLUKKA_EXMAPLE_ESTIMATOR_NAMES = ['AlongBeamAxis', 'SlabYZ']; - const EstimatorsSelect = ({ tabsValue, setTabsValue, simulation, setResultsSimulationData, - estimatorsTabData + estimatorsTabData, + isFlukaExample }: EstimatorsTabProps) => { const [controller] = useState(new AbortController()); @@ -29,7 +29,9 @@ const EstimatorsSelect = ({ const currentEstimatorData = simulation.estimators; const estimatorExists = currentEstimatorData.some(estimator => estimator.name === estimatorsTabData[id]) || - estimatorsTabData[id] === FLUKKA_EXMAPLE_ESTIMATOR_NAMES[id]; + isFlukaExample; + + console.log(estimatorsTabData); if (!estimatorExists) { const simulationJobId = simulation.jobId; @@ -54,7 +56,14 @@ const EstimatorsSelect = ({ } } }, - [controller.signal, estimatorsTabData, getJobResult, setResultsSimulationData, simulation] + [ + controller.signal, + estimatorsTabData, + getJobResult, + isFlukaExample, + setResultsSimulationData, + simulation + ] ); useEffect(() => { diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 5051eb567..79eb577d3 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -14,8 +14,6 @@ export interface EstimatorResults extends Estimator { gridPages: Page[]; } -const FLUKKA_EXMAPLE_RESULTS_NAMES = ['21', '22']; - function ResultsPanel() { const { open: openSaveFileDialog } = useDialog('saveFile'); const { @@ -23,6 +21,7 @@ function ResultsPanel() { resultsSimulationData: simulation, setResultsSimulationData } = useStore(); + const isFlukaExample = simulation?.metadata.simType === 'fluka'; const [tabsValue, setTabsValue] = useState(0); const [estimatorsResults, setEstimatorsResults] = useState([]); @@ -69,17 +68,10 @@ function ResultsPanel() { } const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; - const isFlukkaExample = estimatorsResults.some( - estimator => estimator.name === FLUKKA_EXMAPLE_RESULTS_NAMES[tabsValue] - ); - const chosenEstimator = estimatorsResults.filter( - estimator => - estimator.name === - (isFlukkaExample - ? FLUKKA_EXMAPLE_RESULTS_NAMES[tabsValue] - : estimatorsTabData[tabsValue]) - )[0]; + const chosenEstimator = isFlukaExample + ? estimatorsResults[tabsValue] + : estimatorsResults.filter(estimator => estimator.name === estimatorsTabData[tabsValue])[0]; return ( Date: Tue, 19 Nov 2024 13:29:04 +0100 Subject: [PATCH 08/13] little changes --- .../EstimatorsSelect/EstimatorsSelect.tsx | 8 +++---- .../components/Results/ResultsPanel.tsx | 22 +++++++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx index 7671c46a4..ab928e857 100644 --- a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx +++ b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx @@ -27,11 +27,9 @@ const EstimatorsSelect = ({ const handleEstimatorTabChange = useCallback( async (id: number) => { const currentEstimatorData = simulation.estimators; - const estimatorExists = - currentEstimatorData.some(estimator => estimator.name === estimatorsTabData[id]) || - isFlukaExample; - - console.log(estimatorsTabData); + const estimatorExists = currentEstimatorData.some( + estimator => estimator.name === estimatorsTabData[id] + ); if (!estimatorExists) { const simulationJobId = simulation.jobId; diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 79eb577d3..7b80345a2 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -27,11 +27,19 @@ function ResultsPanel() { const [estimatorsResults, setEstimatorsResults] = useState([]); const [groupQuantities, setGroupQuantities] = useState(false); + const inputFilesEstimatorNames = simulation?.input.inputFilesEstimatorNames?.map(output => + output.slice(0, -1) + ); + const flukaEditorEstimatorNames = simulation?.estimators.map(estimator => estimator.name); + const editorEstimatorNames = simulation?.input.inputJson?.scoringManager.outputs + .filter(output => output.name) + .map(output => output.name); + const estimatorsTabData: string[] | undefined = simulation?.input.inputFilesEstimatorNames - ? simulation.input.inputFilesEstimatorNames.map(output => output.slice(0, -1)) - : simulation?.input.inputJson?.scoringManager.outputs - .filter(output => output.name) - .map(output => output.name); + ? inputFilesEstimatorNames + : isFlukaExample + ? flukaEditorEstimatorNames + : editorEstimatorNames; useEffect(() => { setEstimatorsResults(parseEstimators(simulation?.estimators ?? [])); @@ -69,9 +77,9 @@ function ResultsPanel() { const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; - const chosenEstimator = isFlukaExample - ? estimatorsResults[tabsValue] - : estimatorsResults.filter(estimator => estimator.name === estimatorsTabData[tabsValue])[0]; + const chosenEstimator = estimatorsResults.filter( + estimator => estimator.name === estimatorsTabData[tabsValue] + )[0]; return ( Date: Fri, 22 Nov 2024 17:30:04 +0100 Subject: [PATCH 09/13] changes after cr --- .../EstimatorsSelect/EstimatorsSelect.tsx | 12 ++++++------ .../components/Results/ResultsPanel.tsx | 16 +++++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx index ab928e857..0f1fcc4c5 100644 --- a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx +++ b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx @@ -9,7 +9,7 @@ interface EstimatorsTabProps { simulation: FullSimulationData; setResultsSimulationData: React.Dispatch>; estimatorsTabData: string[]; - isFlukaExample: boolean; + isFlukaSimulation: boolean; } const EstimatorsSelect = ({ @@ -18,7 +18,7 @@ const EstimatorsSelect = ({ simulation, setResultsSimulationData, estimatorsTabData, - isFlukaExample + isFlukaSimulation }: EstimatorsTabProps) => { const [controller] = useState(new AbortController()); @@ -27,9 +27,9 @@ const EstimatorsSelect = ({ const handleEstimatorTabChange = useCallback( async (id: number) => { const currentEstimatorData = simulation.estimators; - const estimatorExists = currentEstimatorData.some( - estimator => estimator.name === estimatorsTabData[id] - ); + const estimatorExists = + currentEstimatorData.some(estimator => estimator.name === estimatorsTabData[id]) || + isFlukaSimulation; if (!estimatorExists) { const simulationJobId = simulation.jobId; @@ -58,7 +58,7 @@ const EstimatorsSelect = ({ controller.signal, estimatorsTabData, getJobResult, - isFlukaExample, + isFlukaSimulation, setResultsSimulationData, simulation ] diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 7b80345a2..ec49eb520 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -21,7 +21,7 @@ function ResultsPanel() { resultsSimulationData: simulation, setResultsSimulationData } = useStore(); - const isFlukaExample = simulation?.metadata.simType === 'fluka'; + const isFlukaSimulation = simulation?.metadata.simType === 'fluka'; const [tabsValue, setTabsValue] = useState(0); const [estimatorsResults, setEstimatorsResults] = useState([]); @@ -30,15 +30,15 @@ function ResultsPanel() { const inputFilesEstimatorNames = simulation?.input.inputFilesEstimatorNames?.map(output => output.slice(0, -1) ); - const flukaEditorEstimatorNames = simulation?.estimators.map(estimator => estimator.name); + const editorEstimatorNames = simulation?.input.inputJson?.scoringManager.outputs .filter(output => output.name) .map(output => output.name); const estimatorsTabData: string[] | undefined = simulation?.input.inputFilesEstimatorNames ? inputFilesEstimatorNames - : isFlukaExample - ? flukaEditorEstimatorNames + : isFlukaSimulation + ? editorEstimatorNames : editorEstimatorNames; useEffect(() => { @@ -77,8 +77,10 @@ function ResultsPanel() { const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; - const chosenEstimator = estimatorsResults.filter( - estimator => estimator.name === estimatorsTabData[tabsValue] + const chosenEstimator = estimatorsResults.filter(estimator => + isFlukaSimulation + ? estimatorsTabData[tabsValue] + : estimator.name === estimatorsTabData[tabsValue] )[0]; return ( @@ -167,7 +169,7 @@ function ResultsPanel() { simulation={simulation} setResultsSimulationData={setResultsSimulationData} estimatorsTabData={estimatorsTabData} - isFlukaExample={isFlukaExample} + isFlukaSimulation={isFlukaSimulation} /> Date: Fri, 22 Nov 2024 21:16:21 +0100 Subject: [PATCH 10/13] delete fluka condition --- .../EstimatorsSelect/EstimatorsSelect.tsx | 29 ++++++++++--------- .../components/Results/ResultsPanel.tsx | 13 ++------- src/types/ResponseTypes.ts | 2 +- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx index 0f1fcc4c5..fcb5b8593 100644 --- a/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx +++ b/src/WrapperApp/components/Results/EstimatorsSelect/EstimatorsSelect.tsx @@ -9,7 +9,6 @@ interface EstimatorsTabProps { simulation: FullSimulationData; setResultsSimulationData: React.Dispatch>; estimatorsTabData: string[]; - isFlukaSimulation: boolean; } const EstimatorsSelect = ({ @@ -17,8 +16,7 @@ const EstimatorsSelect = ({ setTabsValue, simulation, setResultsSimulationData, - estimatorsTabData, - isFlukaSimulation + estimatorsTabData }: EstimatorsTabProps) => { const [controller] = useState(new AbortController()); @@ -28,8 +26,7 @@ const EstimatorsSelect = ({ async (id: number) => { const currentEstimatorData = simulation.estimators; const estimatorExists = - currentEstimatorData.some(estimator => estimator.name === estimatorsTabData[id]) || - isFlukaSimulation; + currentEstimatorData[id] && currentEstimatorData[id].name !== ''; if (!estimatorExists) { const simulationJobId = simulation.jobId; @@ -46,22 +43,26 @@ const EstimatorsSelect = ({ const newEstimatorData = estimatorData?.estimators; if (newEstimatorData) { + const newEstimators = [...currentEstimatorData]; + + while (newEstimators.length <= id) { + newEstimators.push({ + name: '', + pages: [] + }); + } + + newEstimators[id] = newEstimatorData[0]; + const newSimulation = { ...simulation, - estimators: [...currentEstimatorData, ...newEstimatorData] + estimators: newEstimators }; setResultsSimulationData(newSimulation); } } }, - [ - controller.signal, - estimatorsTabData, - getJobResult, - isFlukaSimulation, - setResultsSimulationData, - simulation - ] + [controller.signal, estimatorsTabData, getJobResult, setResultsSimulationData, simulation] ); useEffect(() => { diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index ec49eb520..66ee2961e 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -21,7 +21,6 @@ function ResultsPanel() { resultsSimulationData: simulation, setResultsSimulationData } = useStore(); - const isFlukaSimulation = simulation?.metadata.simType === 'fluka'; const [tabsValue, setTabsValue] = useState(0); const [estimatorsResults, setEstimatorsResults] = useState([]); @@ -37,9 +36,7 @@ function ResultsPanel() { const estimatorsTabData: string[] | undefined = simulation?.input.inputFilesEstimatorNames ? inputFilesEstimatorNames - : isFlukaSimulation - ? editorEstimatorNames - : editorEstimatorNames; + : editorEstimatorNames; useEffect(() => { setEstimatorsResults(parseEstimators(simulation?.estimators ?? [])); @@ -76,12 +73,7 @@ function ResultsPanel() { } const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; - - const chosenEstimator = estimatorsResults.filter(estimator => - isFlukaSimulation - ? estimatorsTabData[tabsValue] - : estimator.name === estimatorsTabData[tabsValue] - )[0]; + const chosenEstimator = estimatorsResults[tabsValue]; return ( Date: Sat, 23 Nov 2024 00:08:29 +0100 Subject: [PATCH 11/13] changes after code review --- .../components/Results/ResultsPanel.tsx | 19 ++++++++++--------- src/services/ShSimulatorService.tsx | 10 +++++++--- src/types/ResponseTypes.ts | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 66ee2961e..838504942 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -26,16 +26,17 @@ function ResultsPanel() { const [estimatorsResults, setEstimatorsResults] = useState([]); const [groupQuantities, setGroupQuantities] = useState(false); - const inputFilesEstimatorNames = simulation?.input.inputFilesEstimatorNames?.map(output => - output.slice(0, -1) + const userTabInputFilesEstimatorNames = simulation?.input.userInputFilesEstimatorNames?.map( + output => output.slice(0, -1) ); + const uploadedInputFilesEstimatorNames = estimatorsResults?.map(estimator => estimator.name); const editorEstimatorNames = simulation?.input.inputJson?.scoringManager.outputs .filter(output => output.name) .map(output => output.name); - const estimatorsTabData: string[] | undefined = simulation?.input.inputFilesEstimatorNames - ? inputFilesEstimatorNames + const estimatorsTabData: string[] | undefined = simulation?.input.userInputFilesEstimatorNames + ? userTabInputFilesEstimatorNames : editorEstimatorNames; useEffect(() => { @@ -68,10 +69,6 @@ function ResultsPanel() { return estimatorResults; }; - if (!estimatorsTabData) { - return null; - } - const resultsGeneratedFromProjectFile = !!simulation?.input.inputJson; const chosenEstimator = estimatorsResults[tabsValue]; @@ -160,7 +157,11 @@ function ResultsPanel() { setTabsValue={setTabsValue} simulation={simulation} setResultsSimulationData={setResultsSimulationData} - estimatorsTabData={estimatorsTabData} + estimatorsTabData={ + estimatorsTabData + ? estimatorsTabData + : uploadedInputFilesEstimatorNames + } /> { [getJobStatus] ); + // This function is used to find the first estimator name in the simulation data to fetch the results for estimators. + // If name isn't passed, it will try to find the first estimator name in the simulation data. + // If the name isn't found, it will try to get name from the backend. + // It wouldn't be handled if we load the example. const findFirstEstimatorName = useCallback( async ( jobStatus: JobStatusData, @@ -553,14 +557,14 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { !firstEstimatorName && jobStatus.jobState === StatusState.COMPLETED ) { - if (inputs && !inputs.input.inputFilesEstimatorNames) { + if (inputs && !inputs.input.userInputFilesEstimatorNames) { const estimators = await getCurrentEstimators(jobStatus.jobId); - inputs.input.inputFilesEstimatorNames = estimators?.estimatorNames; + inputs.input.userInputFilesEstimatorNames = estimators?.estimatorNames; } } - const firstEstimatorInputFileName = inputs?.input.inputFilesEstimatorNames?.[0]; + const firstEstimatorInputFileName = inputs?.input.userInputFilesEstimatorNames?.[0]; if (givenEstimatorName) { return givenEstimatorName; diff --git a/src/types/ResponseTypes.ts b/src/types/ResponseTypes.ts index 6dc766d4b..614239d49 100644 --- a/src/types/ResponseTypes.ts +++ b/src/types/ResponseTypes.ts @@ -334,7 +334,7 @@ export type ResponseGetJobInputs = { inputFiles: SimulationInputFiles; inputJson?: EditorJson; inputType: SimulationSourceType; - inputFilesEstimatorNames?: string[]; + userInputFilesEstimatorNames?: string[]; }; } & YaptideResponse; From 704adfc77554b89c37a3352c88551677ab35e6bd Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Sun, 1 Dec 2024 15:55:28 +0100 Subject: [PATCH 12/13] hope thats all --- .../components/Dialog/SaveFileDialog.tsx | 47 ++++++++++++++-- .../Editor/EditorAppBar/EditorAppBar.tsx | 5 +- .../components/Results/ResultsPanel.tsx | 5 +- .../SimulationCard/SimulationCardHelpers.ts | 5 +- src/services/ShSimulatorService.tsx | 56 ++++++++++++------- 5 files changed, 88 insertions(+), 30 deletions(-) diff --git a/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx b/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx index e1ed63d08..4e0e91206 100644 --- a/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx +++ b/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx @@ -1,8 +1,11 @@ import { Button, Checkbox, FormControlLabel, TextField } from '@mui/material'; import { ChangeEvent, useCallback, useEffect, useState } from 'react'; -import { FullSimulationData } from '../../../services/ShSimulatorService'; +import { useAuth } from '../../../services/AuthService'; +import { FullSimulationData, JobResults } from '../../../services/ShSimulatorService'; import { StoreContext } from '../../../services/StoreService'; +import { RequestGetJobResults } from '../../../types/RequestTypes'; +import { StatusState } from '../../../types/ResponseTypes'; import { saveString } from '../../../util/File'; import { ConcreteDialogProps, CustomDialog } from './CustomDialog'; @@ -26,21 +29,29 @@ export function SaveFileDialog({ name: defaultName = 'editor', results: providedResults, disableCheckbox = false, - yaptideEditor + yaptideEditor, + getJobResults }: ConcreteDialogProps< { name?: string; results?: FullSimulationData; disableCheckbox?: boolean; + getJobResults: (...args: RequestGetJobResults) => Promise; } & Required> >) { const results: FullSimulationData | undefined = providedResults ?? yaptideEditor?.getResults(); + const [controller] = useState(new AbortController()); const [keepResults, setKeepResults] = useState(false); + const [fetchedResults, setFetchedResults] = useState(results); + const jobId = fetchedResults?.jobId; const canKeepResults = useCallback(() => { - return disableCheckbox && results?.input.inputJson?.hash === yaptideEditor?.toJSON().hash; - }, [disableCheckbox, results?.input.inputJson?.hash, yaptideEditor]); + return ( + disableCheckbox && + fetchedResults?.input.inputJson?.hash === yaptideEditor?.toJSON().hash + ); + }, [disableCheckbox, fetchedResults?.input.inputJson?.hash, yaptideEditor]); useEffect(() => { setKeepResults(canKeepResults() || !!providedResults); @@ -58,6 +69,27 @@ export function SaveFileDialog({ setKeepResults(event.target.checked); }; + // Get results from the server if they are not provided + useEffect(() => { + if (jobId) { + getJobResults({ jobId }, controller.signal, false) + .then(requestResults => { + if (requestResults) { + setFetchedResults( + prevResults => + ({ + ...prevResults, + estimators: requestResults.estimators + }) as FullSimulationData + ); + } + }) + .catch(error => { + console.error('Failed to fetch job results:', error); + }); + } + }, [jobId, controller.signal, getJobResults]); + return ( Save diff --git a/src/ThreeEditor/components/Editor/EditorAppBar/EditorAppBar.tsx b/src/ThreeEditor/components/Editor/EditorAppBar/EditorAppBar.tsx index e26eaad46..ac61c76e8 100644 --- a/src/ThreeEditor/components/Editor/EditorAppBar/EditorAppBar.tsx +++ b/src/ThreeEditor/components/Editor/EditorAppBar/EditorAppBar.tsx @@ -12,6 +12,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useDialog } from '../../../../services/DialogService'; import { useLoader } from '../../../../services/LoaderService'; +import { useShSimulation } from '../../../../services/ShSimulatorService'; import { useStore } from '../../../../services/StoreService'; import { YaptideEditor } from '../../../js/YaptideEditor'; import { EditorTitleBar } from './components/EditorTitlebar'; @@ -31,6 +32,7 @@ type AppBarOptions = { function EditorAppBar({ editor }: AppBarProps) { const { loadFromJson, loadFromFiles, loadFromUrl, loadFromJsonString } = useLoader(); + const { getJobResults } = useShSimulation(); const { open: openTheOpenFileDialog } = useDialog('openFile'); const { open: openTheSaveFileDialog } = useDialog('saveFile'); const { open: openTheNewProjectDialog } = useDialog('newProject'); @@ -98,7 +100,8 @@ function EditorAppBar({ editor }: AppBarProps) { label: 'Save as', icon: , disabled: false, - onClick: () => yaptideEditor && openTheSaveFileDialog({ yaptideEditor }) + onClick: () => + yaptideEditor && openTheSaveFileDialog({ yaptideEditor, getJobResults }) }, { label: 'Redo (ctrl+y)', diff --git a/src/WrapperApp/components/Results/ResultsPanel.tsx b/src/WrapperApp/components/Results/ResultsPanel.tsx index 838504942..a52c2c48e 100644 --- a/src/WrapperApp/components/Results/ResultsPanel.tsx +++ b/src/WrapperApp/components/Results/ResultsPanel.tsx @@ -3,6 +3,7 @@ import { ChangeEvent, useEffect, useState } from 'react'; import { Estimator, isPage0d, Page, Page0D } from '../../../JsRoot/GraphData'; import { useDialog } from '../../../services/DialogService'; +import { useShSimulation } from '../../../services/ShSimulatorService'; import { useStore } from '../../../services/StoreService'; import { InfoTooltip } from '../../../shared/components/tooltip/InfoTooltip'; import { titleToKebabCase } from '../../../ThreeEditor/components/Dialog/CustomDialog'; @@ -15,6 +16,7 @@ export interface EstimatorResults extends Estimator { } function ResultsPanel() { + const { getJobResults } = useShSimulation(); const { open: openSaveFileDialog } = useDialog('saveFile'); const { yaptideEditor, @@ -53,7 +55,8 @@ function ResultsPanel() { name: `${titleToKebabCase(simulation?.title ?? 'simulation')}-result.json`, results: simulation, disableCheckbox: true, - yaptideEditor + yaptideEditor, + getJobResults }); }; diff --git a/src/WrapperApp/components/Simulation/SimulationCard/SimulationCardHelpers.ts b/src/WrapperApp/components/Simulation/SimulationCard/SimulationCardHelpers.ts index ab5d7faed..0208063d0 100644 --- a/src/WrapperApp/components/Simulation/SimulationCard/SimulationCardHelpers.ts +++ b/src/WrapperApp/components/Simulation/SimulationCard/SimulationCardHelpers.ts @@ -23,7 +23,7 @@ const SimulationCardHelpers = ({ yaptideEditor }: SimulationCardHelpersProps) => { const { loadFromJson } = useLoader(); - const { getJobLogs, getJobInputs, getFullSimulationData } = useShSimulation(); + const { getJobLogs, getJobInputs, getFullSimulationData, getJobResults } = useShSimulation(); const { enqueueSnackbar } = useSnackbar(); const { open: openSaveFileDialog } = useDialog('saveFile'); @@ -90,7 +90,8 @@ const SimulationCardHelpers = ({ name: `${titleToKebabCase(simulation?.title ?? 'simulation')}-result.json`, results: simulation, disableCheckbox: true, - yaptideEditor + yaptideEditor, + getJobResults }); }) .catch(() => { diff --git a/src/services/ShSimulatorService.tsx b/src/services/ShSimulatorService.tsx index f10eefe51..6377ce409 100644 --- a/src/services/ShSimulatorService.tsx +++ b/src/services/ShSimulatorService.tsx @@ -59,6 +59,12 @@ export type JobResults = { jobId: string; } & ResponseGetJobResults; +export type SpecificEstimator = { + jobId: string; + estimators: Estimator[]; + message: string; +}; + export type FullSimulationData = Omit; export const fetchItSymbol = Symbol('fetchItSymbol'); @@ -389,10 +395,10 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { jobInputs?.input.inputJson && recreateRefsInResults(jobInputs.input.inputJson, estimator); - const data: JobResults = { - ...response, + const data: SpecificEstimator = { jobId, - estimators: refsInResults ?? estimator + estimators: refsInResults ?? estimator, + message: response.message }; resolve(data); @@ -544,19 +550,13 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { // If name isn't passed, it will try to find the first estimator name in the simulation data. // If the name isn't found, it will try to get name from the backend. // It wouldn't be handled if we load the example. - const findFirstEstimatorName = useCallback( + const findFirstEstimatorNameForInputFiles = useCallback( async ( jobStatus: JobStatusData, inputs: JobInputs | undefined, givenEstimatorName?: string ) => { - const firstEstimatorName = inputs?.input.inputJson?.scoringManager.outputs[0].name; - - if ( - !givenEstimatorName && - !firstEstimatorName && - jobStatus.jobState === StatusState.COMPLETED - ) { + if (!givenEstimatorName && jobStatus.jobState === StatusState.COMPLETED) { if (inputs && !inputs.input.userInputFilesEstimatorNames) { const estimators = await getCurrentEstimators(jobStatus.jobId); @@ -573,12 +573,23 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { if (firstEstimatorInputFileName) { return firstEstimatorInputFileName; } + }, + [getCurrentEstimators] + ); + + const findFirstEstimatorNameForEditor = useCallback( + (inputs: JobInputs | undefined, givenEstimatorName?: string) => { + const firstEstimatorName = inputs?.input.inputJson?.scoringManager.outputs[0].name; + + if (givenEstimatorName) { + return givenEstimatorName; + } if (firstEstimatorName) { return firstEstimatorName + '_'; } }, - [getCurrentEstimators] + [] ); const getFullSimulationData = useCallback( @@ -590,20 +601,18 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { ) => { const inputs: JobInputs | undefined = await getJobInputs(jobStatus, signal, cache); - const firstEstimator = await findFirstEstimatorName( - jobStatus, - inputs, - givenEstimatorName - ); + const isSimulationFromEditor = inputs?.input.inputType.toLowerCase() === 'editor'; + + const firstEstimator = isSimulationFromEditor + ? findFirstEstimatorNameForEditor(inputs, givenEstimatorName) + : await findFirstEstimatorNameForInputFiles(jobStatus, inputs, givenEstimatorName); const results: JobResults | undefined = jobStatus.jobState === StatusState.COMPLETED && firstEstimator ? await getJobResult( { jobId: jobStatus.jobId, - estimatorName: givenEstimatorName - ? givenEstimatorName - : firstEstimator + estimatorName: firstEstimator }, signal, cache @@ -624,7 +633,12 @@ const ShSimulation = ({ children }: GenericContextProviderProps) => { return simData; }, - [findFirstEstimatorName, getJobInputs, getJobResult] + [ + findFirstEstimatorNameForEditor, + findFirstEstimatorNameForInputFiles, + getJobInputs, + getJobResult + ] ); return ( From 9498878ec16ef828acbf8a2f72f7573cfc0906d1 Mon Sep 17 00:00:00 2001 From: matuszsmig Date: Mon, 2 Dec 2024 19:36:26 +0100 Subject: [PATCH 13/13] fix problem with loading example --- src/ThreeEditor/components/Dialog/SaveFileDialog.tsx | 12 +++++++----- src/WrapperApp/components/Results/ResultsPanel.tsx | 7 ++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx b/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx index 4e0e91206..c0bca7271 100644 --- a/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx +++ b/src/ThreeEditor/components/Dialog/SaveFileDialog.tsx @@ -1,11 +1,9 @@ import { Button, Checkbox, FormControlLabel, TextField } from '@mui/material'; import { ChangeEvent, useCallback, useEffect, useState } from 'react'; -import { useAuth } from '../../../services/AuthService'; import { FullSimulationData, JobResults } from '../../../services/ShSimulatorService'; import { StoreContext } from '../../../services/StoreService'; import { RequestGetJobResults } from '../../../types/RequestTypes'; -import { StatusState } from '../../../types/ResponseTypes'; import { saveString } from '../../../util/File'; import { ConcreteDialogProps, CustomDialog } from './CustomDialog'; @@ -30,13 +28,15 @@ export function SaveFileDialog({ results: providedResults, disableCheckbox = false, yaptideEditor, - getJobResults + getJobResults, + expectedEstimatorsSize }: ConcreteDialogProps< { name?: string; results?: FullSimulationData; disableCheckbox?: boolean; getJobResults: (...args: RequestGetJobResults) => Promise; + expectedEstimatorsSize?: number; } & Required> >) { const results: FullSimulationData | undefined = providedResults ?? yaptideEditor?.getResults(); @@ -45,6 +45,8 @@ export function SaveFileDialog({ const [keepResults, setKeepResults] = useState(false); const [fetchedResults, setFetchedResults] = useState(results); const jobId = fetchedResults?.jobId; + const shouldFetchEstimators = + jobId && fetchedResults?.estimators.length !== expectedEstimatorsSize; const canKeepResults = useCallback(() => { return ( @@ -71,7 +73,7 @@ export function SaveFileDialog({ // Get results from the server if they are not provided useEffect(() => { - if (jobId) { + if (shouldFetchEstimators) { getJobResults({ jobId }, controller.signal, false) .then(requestResults => { if (requestResults) { @@ -88,7 +90,7 @@ export function SaveFileDialog({ console.error('Failed to fetch job results:', error); }); } - }, [jobId, controller.signal, getJobResults]); + }, [jobId, controller.signal, getJobResults, shouldFetchEstimators]); return ( { + const expectedEstimators = estimatorsTabData + ? estimatorsTabData + : uploadedInputFilesEstimatorNames; + if (yaptideEditor) openSaveFileDialog({ name: `${titleToKebabCase(simulation?.title ?? 'simulation')}-result.json`, results: simulation, disableCheckbox: true, yaptideEditor, - getJobResults + getJobResults, + expectedEstimatorsSize: expectedEstimators.length }); };