Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select zone as scoring object. #1906

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions src/ThreeEditor/Simulation/Scoring/ScoringManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ export class ScoringManager
}, [])
.filter(Boolean);
}

getOutputByQuantityUuid(uuid: string) {
return this.outputs.find(output => output.quantities.some(q => q.uuid === uuid)) ?? null;
}
/***************************************************************/

constructor(editor: YaptideEditor) {
Expand Down
46 changes: 46 additions & 0 deletions src/ThreeEditor/Simulation/Scoring/ScoringOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import { YaptideEditor } from '../../js/YaptideEditor';
import { SimulationSceneContainer } from '../Base/SimulationContainer';
import { SimulationElement, SimulationElementJSON } from '../Base/SimulationElement';
import { SimulationElementManager } from '../Base/SimulationManager';
import { SimulationZone } from '../Base/SimulationZone';
import { Detector } from '../Detectors/Detector';
import { ScoringFilter } from './ScoringFilter';
import { SCORING_TYPE, SCORING_TYPE_ENUM } from './ScoringOutputTypes';
import { ScoringQuantity, ScoringQuantityJSON } from './ScoringQuantity';

export type ScoringOutputJSON = Omit<
SimulationElementJSON & {
quantities: ScoringQuantityJSON[];
detectorUuid?: string;
zoneUuid?: string;
scoringType?: string;
jagodek marked this conversation as resolved.
Show resolved Hide resolved
trace: boolean;
traceFilter?: string;
},
Expand Down Expand Up @@ -62,6 +66,10 @@ export class ScoringOutput

private _detector?: string;

private _zone?: string;

private _scoringType?: SCORING_TYPE;

//TODO: Issue#320
private _trace: [boolean, string | null];

Expand Down Expand Up @@ -96,13 +104,39 @@ export class ScoringOutput
return this.editor.detectorManager.getDetectorByUuid(this._detector);
}

get zone(): SimulationZone | null {
if (!this._zone) return null;

return this.editor.zoneManager.getZoneByUuid(this._zone);
}

set detector(detector: Detector | null) {
this._detector = detector?.uuid;
this.geometry =
detector?.geometry.clone().translate(...detector.position.toArray()) ?? null;
this.signals.objectSelected.dispatch(this);
}

set zone(zone: SimulationZone | null) {
this._zone = zone?.uuid;
this.geometry = null;
this.signals.objectSelected.dispatch(this);
}

get scoringType(): SCORING_TYPE {
return this._scoringType ?? SCORING_TYPE_ENUM.DETECTOR;
}

set scoringType(scoringType: SCORING_TYPE_ENUM) {
this._scoringType = scoringType;

if (scoringType === SCORING_TYPE_ENUM.DETECTOR) {
this._zone = undefined;
} else if (scoringType === SCORING_TYPE_ENUM.ZONE) {
this._detector = undefined;
}
}

constructor(editor: YaptideEditor) {
super(editor, 'Output', 'Output');
this.children = [];
Expand Down Expand Up @@ -148,11 +182,17 @@ export class ScoringOutput
return this.quantities.find(qty => qty.uuid === uuid) ?? null;
}

removeAllQuantities() {
this.quantityContainer.clear();
}

toJSON(): ScoringOutputJSON {
return {
...super.toJSON(),
quantities: this.quantityContainer.toJSON(),
detectorUuid: this._detector,
zoneUuid: this._zone,
scoringType: this._scoringType,
trace: this._trace[0],
...(this.trace[1] && { traceFilter: this.trace[1] })
};
Expand All @@ -163,9 +203,13 @@ export class ScoringOutput
this.name = json.name;
this._trace = [json.trace, json.traceFilter ?? null];
this.quantityContainer.fromJSON(json.quantities);

this.detector = json.detectorUuid
? this.editor.detectorManager.getDetectorByUuid(json.detectorUuid)
: null;
this.zone = json.zoneUuid ? this.editor.zoneManager.getZoneByUuid(json.zoneUuid) : null;

this._scoringType = (json.scoringType as SCORING_TYPE) ?? SCORING_TYPE_ENUM.DETECTOR;

return this;
}
Expand All @@ -183,6 +227,8 @@ export class ScoringOutput
duplicated.quantityContainer = this.quantityContainer.duplicate();
duplicated.add(duplicated.quantityContainer);

duplicated._scoringType = this._scoringType ?? SCORING_TYPE_ENUM.DETECTOR;

return duplicated;
}
}
Expand Down
37 changes: 36 additions & 1 deletion src/ThreeEditor/Simulation/Scoring/ScoringOutputTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,24 @@ export const DETECTOR_KEYWORD_OPTIONS = Object.keys(DETECTOR_KEYWORD_DESCRIPTION
{} as Record<DETECTOR_KEYWORDS, DETECTOR_KEYWORDS>
);

const FLUKA_DETECTOR_KEYWORD = ['Dose', 'Fluence'] as const;

export const FLUKA_DETECTOR_KEYWORD_OPTIONS = Object.keys(DETECTOR_KEYWORD_DESCRIPTION).reduce(
(acc, key) => {
if (key === 'Dose' || key === 'Fluence') {
if (FLUKA_DETECTOR_KEYWORD.includes(key)) {
return { ...acc, [key]: key };
}

return acc;
},
{} as Record<DETECTOR_KEYWORDS, DETECTOR_KEYWORDS>
);

const FLUKA_ZONE_KEYWORDS = ['Dose', 'Fluence'] as const;

export const FLUKA_ZONE_KEYWORD_OPTIONS = Object.keys(DETECTOR_KEYWORD_DESCRIPTION).reduce(
(acc, key) => {
if (FLUKA_ZONE_KEYWORDS.includes(key)) {
return { ...acc, [key]: key };
}

Expand All @@ -130,6 +145,19 @@ export const FLUKA_DETECTOR_KEYWORD_OPTIONS = Object.keys(DETECTOR_KEYWORD_DESCR
{} as Record<DETECTOR_KEYWORDS, DETECTOR_KEYWORDS>
);

const FLUKA_ZONE_MODIFIERS = ['E', 'ENUC'] as const;

export const FLUKA_ZONE_MODIFIERS_OPTIONS = Object.keys(DETECTOR_MODIFIERS_DESCRIPTION).reduce(
(acc, key) => {
if (FLUKA_ZONE_MODIFIERS.includes(key)) {
return { ...acc, [key]: key };
}

return acc;
},
{} as Record<DETECTOR_MODIFIERS, DETECTOR_MODIFIERS>
);

export type MEDIUM = keyof typeof MEDIUM_KEYWORDS;

export const MEDIUM_KEYWORD_OPTIONS = Object.keys(MEDIUM_KEYWORDS).reduce(
Expand All @@ -138,3 +166,10 @@ export const MEDIUM_KEYWORD_OPTIONS = Object.keys(MEDIUM_KEYWORDS).reduce(
},
{} as Record<MEDIUM, MEDIUM>
);

export type SCORING_TYPE = keyof typeof SCORING_TYPE_ENUM;

export enum SCORING_TYPE_ENUM {
DETECTOR = 'DETECTOR',
ZONE = 'ZONE'
}
13 changes: 13 additions & 0 deletions src/ThreeEditor/Simulation/Zones/ZoneManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ export class ZoneManager
return zoneOptions;
}

getZoneOptionsForScoring(): Record<string, string> {
const zoneOptions = [...this.zones].reduce(
(acc, zone) => {
acc[zone.uuid] = `${zone.name} [${zone.id}]`;

return acc;
},
{} as Record<string, string>
);

return zoneOptions;
}

getBooleanZoneOptions() {
return this.getZoneOptions();
}
Expand Down
50 changes: 50 additions & 0 deletions src/ThreeEditor/components/Dialog/ChangeScoringTypeDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Button } from '@mui/material';

import { StoreContext } from '../../../services/StoreService';
import { ScoringOutput } from '../../Simulation/Scoring/ScoringOutput';
import { SCORING_TYPE, SCORING_TYPE_ENUM } from '../../Simulation/Scoring/ScoringOutputTypes';
import { ConcreteDialogProps, CustomDialog } from './CustomDialog';

export function ChangeScoringTypeDialog({
onClose,
yaptideEditor,
scoringOutput,
newAlignment,
setScoringType
}: ConcreteDialogProps<
Required<Pick<StoreContext, 'yaptideEditor'>> & { scoringOutput: ScoringOutput } & {
newAlignment: SCORING_TYPE;
} & { setScoringType: (scoringType: SCORING_TYPE) => void }
>) {
return (
<CustomDialog
onClose={onClose}
alert={true}
title='Warning: Change Scoring Type'
contentText='Changing scoring type will remove quantities and their configurations. Are you sure you want to continue?'>
<Button
onClick={onClose}
autoFocus>
Cancel
</Button>
<Button
onClick={() => {
onClose();

if (scoringOutput && yaptideEditor) {
scoringOutput.removeAllQuantities();

if (newAlignment === SCORING_TYPE_ENUM.ZONE) {
setScoringType(SCORING_TYPE_ENUM.ZONE);
scoringOutput.scoringType = SCORING_TYPE_ENUM.ZONE;
} else if (newAlignment === SCORING_TYPE_ENUM.DETECTOR) {
setScoringType(SCORING_TYPE_ENUM.DETECTOR);
scoringOutput.scoringType = SCORING_TYPE_ENUM.DETECTOR;
}
}
}}>
Clear and proceed
</Button>
</CustomDialog>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ export function PropertiesPanel(props: { boxProps: BoxProps; editor: YaptideEdit
<ParticleFilterConfiguration {...panelProps} />
<OutputConfiguration {...panelProps} />
<QuantityConfiguration {...panelProps} />
{editor.contextManager.currentSimulator === SimulatorType.SHIELDHIT && (
<QuantityDifferentialScoring {...panelProps} />
)}
{[SimulatorType.SHIELDHIT, SimulatorType.FLUKA].includes(
editor.contextManager.currentSimulator
) && <QuantityDifferentialScoring {...panelProps} />}
<BeamConfiguration {...panelProps} />
<ObjectConfiguration {...panelProps} />
<ObjectDimensions {...panelProps} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Grid } from '@mui/material';
import { Object3D } from 'three';

import { useSmartWatchEditorState } from '../../../../../util/hooks/signals';
import { SetValueCommand } from '../../../../js/commands/SetValueCommand';
import { YaptideEditor } from '../../../../js/YaptideEditor';
import { isBeam } from '../../../../Simulation/Physics/Beam';
import { ScoringOutput } from '../../../../Simulation/Scoring/ScoringOutput';
import { isScoringQuantity } from '../../../../Simulation/Scoring/ScoringQuantity';
import { TextPropertyField } from '../fields/PropertyField';
import { PropertiesCategory } from './PropertiesCategory';

Expand All @@ -13,6 +16,14 @@ export function ObjectInfo(props: { editor: YaptideEditor; object: Object3D }) {
const { state: watchedObject } = useSmartWatchEditorState(editor, object);

const visibleFlag = !isBeam(watchedObject);
let scoringType: string | undefined = 'unknown';

if (isScoringQuantity(watchedObject)) {
let scoringOutput: ScoringOutput | null = editor.scoringManager.getOutputByQuantityUuid(
watchedObject.uuid
);
scoringType = scoringOutput?.scoringType;
}

return (
<PropertiesCategory
Expand All @@ -34,6 +45,21 @@ export function ObjectInfo(props: { editor: YaptideEditor; object: Object3D }) {
);
}}
/>
{isScoringQuantity(watchedObject) && (
<>
<Grid
item
xs={4}
sx={{ textAlign: 'right' }}>
{'Scoring Type'}
</Grid>
<Grid
item
xs={8}>
{scoringType}
</Grid>
</>
)}
</>
)}
</PropertiesCategory>
Expand Down
Loading
Loading