From 4ce5c2a9dae8f2b1edbc218b231b3567ce6cf221 Mon Sep 17 00:00:00 2001 From: tizayi Date: Tue, 30 Apr 2024 16:52:53 +0100 Subject: [PATCH 01/15] add new beamline type --- src/presets/beamlines.json | 9 ++ src/presets/preset.test.ts | 42 ++------- src/presets/presetConfigs.json | 22 +---- src/presets/presetManager.ts | 164 ++++++++++++++++++--------------- src/utils/types.ts | 91 +++++++++++++++--- 5 files changed, 192 insertions(+), 136 deletions(-) create mode 100644 src/presets/beamlines.json diff --git a/src/presets/beamlines.json b/src/presets/beamlines.json new file mode 100644 index 0000000..7714d1a --- /dev/null +++ b/src/presets/beamlines.json @@ -0,0 +1,9 @@ +{ + "I22": { + "minWavelength": 0.062, + "maxWavelength": 0.335, + "minCameraLength": 1.9, + "maxCameraLength": 9.9, + "cameraLengthStep": 0.25 + } +} \ No newline at end of file diff --git a/src/presets/preset.test.ts b/src/presets/preset.test.ts index a015a9c..24efe23 100644 --- a/src/presets/preset.test.ts +++ b/src/presets/preset.test.ts @@ -1,38 +1,12 @@ import { expect, test } from "vitest"; -import { defaultConfig, detectorList, presetList } from "./presetManager"; +import { detectorRecord } from "./presetManager"; -test("Test detectors exist and are valid", () => { - expect(detectorList).toBeTruthy(); - for (const detector in detectorList) { - expect(detectorList[detector]).toHaveProperty("resolution.width"); - expect(detectorList[detector]).toHaveProperty("resolution.height"); - expect(detectorList[detector]).toHaveProperty("pixelSize.width"); - expect(detectorList[detector]).toHaveProperty("pixelSize.height"); - } -}); - -test("Test beamstop and camera tube are valid", () => { - for (const preset in presetList) { - expect(presetList[preset]).toHaveProperty("beamstop.diameter"); - expect(presetList[preset]).toHaveProperty("beamstop.centre.x"); - expect(presetList[preset]).toHaveProperty("beamstop.centre.y"); - expect(presetList[preset]).toHaveProperty("beamstop.clearance"); - expect(presetList[preset]).toHaveProperty("cameraTube.centre.x"); - expect(presetList[preset]).toHaveProperty("cameraTube.centre.y"); - expect(presetList[preset]).toHaveProperty("cameraTube.diameter"); - } -}); - -test("Test presets exist and are valid", () => { - expect(presetList).toBeTruthy(); - expect(defaultConfig).toBeTruthy(); - for (const preset in presetList) { - expect(Object.keys(detectorList)).toContain(presetList[preset].detector); - expect(presetList[preset]).toHaveProperty("angle"); - expect(presetList[preset]).toHaveProperty("cameraLength"); - expect(presetList[preset]).toHaveProperty("minWavelength"); - expect(presetList[preset]).toHaveProperty("maxWavelength"); - expect(presetList[preset]).toHaveProperty("minCameraLength"); - expect(presetList[preset]).toHaveProperty("maxCameraLength"); +test("Test detectors exist anordetectorRecordd are valid", () => { + expect(detectorRecord).toBeTruthy(); + for (const detector in detectorRecord) { + expect(detectorRecord[detector]).toHaveProperty("resolution.width"); + expect(detectorRecord[detector]).toHaveProperty("resolution.height"); + expect(detectorRecord[detector]).toHaveProperty("pixelSize.width"); + expect(detectorRecord[detector]).toHaveProperty("pixelSize.height"); } }); diff --git a/src/presets/presetConfigs.json b/src/presets/presetConfigs.json index 50e4bb2..d3e342c 100644 --- a/src/presets/presetConfigs.json +++ b/src/presets/presetConfigs.json @@ -1,6 +1,7 @@ { "I22 SAXS Isotropic": { "detector": "Pilatus P3-2M", + "beamline": "I22", "beamstop": { "centre": { "x": 738, @@ -15,18 +16,11 @@ "y": 840 }, "diameter": 310 - }, - "angle": 90, - "wavelength": null, - "cameraLength": 1.9, - "minWavelength": 0.062, - "maxWavelength": 0.335, - "minCameraLength": 1.9, - "maxCameraLength": 9.9, - "cameraLengthStep": 0.25 + } }, "I22 SAXS Anisotropic": { "detector": "Pilatus P3-2M", + "beamline": "I22", "beamstop": { "centre": { "x": 738, @@ -41,14 +35,6 @@ "y": 840 }, "diameter": 310 - }, - "angle": 90, - "wavelength": null, - "cameraLength": 1.9, - "minWavelength": 0.062, - "maxWavelength": 0.335, - "minCameraLength": 1.9, - "maxCameraLength": 9.9, - "cameraLengthStep": 0.25 + } } } diff --git a/src/presets/presetManager.ts b/src/presets/presetManager.ts index bfe738e..5f3dede 100644 --- a/src/presets/presetManager.ts +++ b/src/presets/presetManager.ts @@ -1,91 +1,109 @@ import {unit} from "mathjs"; -import detectorDataRecord from "../presets/detectors.json"; -import presetData from "../presets/presetConfigs.json"; -import { - BeamlineConfig, - Beamstop, - CircularDevice, - Detector, - SimpleVector2, +import detectorData from "./detectors.json"; +import presetConfigData from "./presetConfigs.json"; +import beamlineData from "./beamlines.json" +import { + AppBeamline, + AppDetector, + AppConfig, + IOBeamline, + IODetector, + IOPresetConfig } from "../utils/types"; -export interface AppDataFormat extends BeamlineConfig { - detector: string; - beamstop: Beamstop; - cameraTube: CircularDevice; - // todo use OOP composition over inheritance - // https://en.wikipedia.org/wiki/Composition_over_inheritance - // beamlineConfig: BeamlineConfig; -} - -interface DetectorData { - readonly resolution: { height: number; width: number }; - readonly pixelSize: { height: number; width: number }; -} -interface CircularDeviceData { - readonly centre: SimpleVector2; - readonly diameter: number; +/** + * Creates an internal detector with pixel size units from an IODetector + * @param detectorData IOdetector input + * @returns AppDetector output + */ +export function createInternalDetector(detectorData: IODetector): AppDetector { + return { + ...detectorData, + pixelSize: { + height: unit(detectorData.pixelSize.height, "mm"), + width: unit(detectorData.pixelSize.height, "mm"), + }, + } } -export interface BeamlineData { - readonly angle: number | null; - readonly cameraLength: number | null; - readonly minWavelength: number; - readonly maxWavelength: number; - readonly minCameraLength: number; - readonly maxCameraLength: number; - readonly wavelength: number | null; - readonly cameraLengthStep: number; -} +/** + * Holds all the preset detectors as AppDetectors + */ +export const detectorRecord: Record = Object.fromEntries( + Object.entries(detectorData as Record).map( + ([key, value]) => [ + key, + createInternalDetector(value) + ], + ), +); -interface BeamstopData extends CircularDeviceData { - readonly clearance: number | null; -} -export interface AppData extends BeamlineData { - readonly detector: string; - readonly beamstop: BeamstopData; - readonly cameraTube: CircularDeviceData; +/** + * Creates an internal beamline with units from an IODetector + * @param beamlineData Input IOBeamline + * @returns AppBeamline with correct data + */ +export function createInternalBeamline(beamlineData: IOBeamline): AppBeamline { + return { + minWavelength: unit(beamlineData.minWavelength, "nm"), + maxWavelength: unit(beamlineData.maxWavelength, "nm"), + minCameraLength: unit(beamlineData.minCameraLength, "m"), + maxCameraLength: unit(beamlineData.maxCameraLength, "m"), + cameraLengthStep: unit(beamlineData.cameraLengthStep, "m"), + } } -export const detectorList: Record = Object.fromEntries( - Object.entries(detectorDataRecord as Record).map( +/** + * Holds all the preset beamlines as AppBeamlines + */ +export const beamlineRecord: Record = Object.fromEntries( + Object.entries(beamlineData as Record).map( ([key, value]) => [ key, - { - ...value, - pixelSize: { - height: unit(value.pixelSize.height, "mm"), - width: unit(value.pixelSize.height, "mm"), - }, - }, + createInternalBeamline(value) ], ), -); +) + +/** + * Creates internal AppConfig from IOPresetConfig + * @param preset input IOPresetConfig + * @returns + */ +function createPresetConfigRecord(preset: IOPresetConfig):AppConfig{ + return { + ...preset, + beamstop: { + ...preset.beamstop, + diameter: unit(preset.beamstop.diameter, "mm"), + }, + cameraTube: { + ...preset.cameraTube, + diameter: unit(preset.cameraTube.diameter, "mm"), + }, + wavelength: unit(NaN, "nm"), + angle: unit(90, "deg"), + cameraLength: + beamlineRecord[preset.beamline].minCameraLength.toNumber("m"), + } + } -export const presetList: Record = Object.fromEntries( - Object.entries(presetData as Record).map(([key, value]) => [ - key, - { - ...value, - beamstop: { - ...value.beamstop, - diameter: unit(value.beamstop.diameter, "mm"), - }, - cameraTube: { - ...value.cameraTube, - diameter: unit(value.cameraTube.diameter, "mm"), - }, - minWavelength: unit(value.minWavelength, "nm"), - maxWavelength: unit(value.maxWavelength, "nm"), - minCameraLength: unit(value.minCameraLength, "m"), - maxCameraLength: unit(value.maxCameraLength, "m"), - cameraLengthStep: unit(value.cameraLengthStep, "m"), - wavelength: unit(value.wavelength ?? NaN, "nm"), - angle: unit(value.angle ?? NaN, "deg"), - }, + /** + * Holds the internal app configurations + */ +export const presetConfigRecord: Record = Object.fromEntries( + Object.entries(presetConfigData as Record).map( + ([key, value]) => [ + key, + createPresetConfigRecord(value) ]), ); -export const defaultConfig = presetList[Object.keys(presetList)[0]]; + +/** + * Sets how the app is configured by default + */ +export const defaultConfig = presetConfigRecord[ + Object.keys(presetConfigRecord)[0]]; diff --git a/src/utils/types.ts b/src/utils/types.ts index 778d9a2..c7b5504 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,31 +1,100 @@ import { Unit } from "mathjs"; -export interface Detector { - readonly resolution: { height: number; width: number }; - readonly pixelSize: { height: Unit; width: Unit }; -} - +/** + * Represnts a simple vector + */ export interface SimpleVector2 { x?: number | null; y?: number | null; } -export interface CircularDevice { +/** + * Internal Detector type + */ +export interface AppDetector { + readonly resolution: { height: number; width: number }; + readonly pixelSize: { height: Unit; width: Unit }; +} + +/** + * Internal Circular Device (eg Camera Tube or Beamstop) + */ +export interface AppCircularDevice { centre: SimpleVector2; diameter: Unit; } -export interface Beamstop extends CircularDevice { +/** + * Internal Beamstop type + */ +export interface AppBeamstop extends AppCircularDevice { clearance: number | null; } -export interface BeamlineConfig { - angle: Unit; - cameraLength: number | null; +/** + * Internal Beamline type (contains all immutable information about a beamline) + */ +export interface AppBeamline { readonly minWavelength: Unit; readonly maxWavelength: Unit; readonly minCameraLength: Unit; readonly maxCameraLength: Unit; - wavelength: Unit; readonly cameraLengthStep: Unit; } + +/** + * Internal Full AppConfig + */ +export interface AppConfig { + detector: string; + beamstop: AppBeamstop; + cameraTube: AppCircularDevice; + beamline: string; + wavelength: Unit; + angle: Unit; + cameraLength: number | null; +} + +/** + * External Detector type used in IO + */ +export interface IODetector { + readonly resolution: { height: number; width: number }; + readonly pixelSize: { height: number; width: number }; +} + +/** + * External CircularTube type used in IO + */ +export interface IOCircularDevice { + readonly centre: SimpleVector2; + readonly diameter: number; +} + +/** + * External Beamline type for use in + */ +export interface IOBeamline { + readonly minWavelength: number; + readonly maxWavelength: number; + readonly minCameraLength: number; + readonly maxCameraLength: number; + readonly cameraLengthStep: number; +} + +/** + * External Beamstop type + */ +export interface IOBeamstop extends IOCircularDevice { + readonly clearance: number | null; +} + +/** + * External Preset Config type + */ +export interface IOPresetConfig { + readonly detector: string; + readonly beamline: string; + readonly beamstop: IOBeamstop; + readonly cameraTube: IOCircularDevice; +} From 82a5d0510a91c977687f37d7ac4695576482b044 Mon Sep 17 00:00:00 2001 From: tizayi Date: Wed, 1 May 2024 12:37:58 +0100 Subject: [PATCH 02/15] seperate beamline and preset --- src/basicAppBar.tsx | 2 +- src/calculations/numericRange.ts | 16 ++-- src/calculations/qrange.ts | 10 +- src/calculations/unitRange.ts | 21 ++-- src/data-entry/beamProperties.tsx | 2 +- src/data-entry/beamlineconfigStore.ts | 95 +++++++++++++------ src/data-entry/beamstop.tsx | 10 +- src/data-entry/beamstopStore.ts | 20 ++-- src/data-entry/cameraTube.tsx | 10 +- src/data-entry/cameraTubeStore.ts | 17 ++-- src/data-entry/dataSideBar.tsx | 80 ++++++---------- src/data-entry/detectorStore.ts | 32 +++---- src/dialogs/BeamlineTable.tsx | 18 +--- .../{presetDialog.tsx => beamlineDialog.tsx} | 58 +---------- src/dialogs/detectorDialog.tsx | 12 ++- src/dialogs/detectorTable.tsx | 8 +- src/index.css | 21 ++-- src/plot/centrePlot.tsx | 23 +---- src/plot/legendBar.tsx | 54 ++++------- src/presets/beamlines.json | 16 ++-- src/presets/presetManager.ts | 94 ++++++++---------- src/results/rangeTable.tsx | 2 +- src/utils/colourPicker.tsx | 7 +- src/utils/types.ts | 10 +- src/utils/units.ts | 66 +++++++------ tsconfig.json | 8 +- 26 files changed, 323 insertions(+), 389 deletions(-) rename src/dialogs/{presetDialog.tsx => beamlineDialog.tsx} (70%) diff --git a/src/basicAppBar.tsx b/src/basicAppBar.tsx index 3f93213..bce2a4a 100644 --- a/src/basicAppBar.tsx +++ b/src/basicAppBar.tsx @@ -5,7 +5,7 @@ import Typography from "@mui/material/Typography"; export default function BasicAppBar(): JSX.Element { return ( - + diff --git a/src/calculations/numericRange.ts b/src/calculations/numericRange.ts index d3817bb..1c570ea 100644 --- a/src/calculations/numericRange.ts +++ b/src/calculations/numericRange.ts @@ -20,9 +20,9 @@ export default class NumericRange { /** * Checks if the input is contained in this range. - * - * @param value - Input number - * @returns + * + * @param value - Input number + * @returns */ containsValue(value: number): boolean { return value >= this.min && value <= this.max; @@ -71,19 +71,19 @@ export default class NumericRange { applyInPlace(func: (value: number) => number): NumericRange { this.min = func(this.min); this.max = func(this.max); - + if (this.min > this.max) { const temp = this.max; this.max = this.min; this.min = temp; } - + return this; } /** * Returns a string representation of this range. - * @returns + * @returns */ toString(): string { return `(min:${this.min}, max:${this.max})`; @@ -91,8 +91,8 @@ export default class NumericRange { /** * Check if this range is equal to the input range - * @param other Another NumericRange - * @returns + * @param other Another NumericRange + * @returns */ equals(other: NumericRange): boolean { return this.min === other.min && this.max === other.max; diff --git a/src/calculations/qrange.ts b/src/calculations/qrange.ts index 1050725..85b462f 100644 --- a/src/calculations/qrange.ts +++ b/src/calculations/qrange.ts @@ -25,11 +25,11 @@ const defaultReturn = { // I created blocks in it with comments (not the only way to do this) /** * Computes the qrange given detector, beamstop, cameraTube, and Beamproperties - * @param detector - * @param beamstop - * @param cameraTube - * @param beamProperties - * @returns + * @param detector + * @param beamstop + * @param cameraTube + * @param beamProperties + * @returns */ export function computeQrange( detector: Detector, diff --git a/src/calculations/unitRange.ts b/src/calculations/unitRange.ts index 04428e8..40631ff 100644 --- a/src/calculations/unitRange.ts +++ b/src/calculations/unitRange.ts @@ -28,10 +28,10 @@ export default class UnitRange { /** * Creates a new UnitRange with the units converted to the input unit string. - * - * @remarks To learn about the unit strings refer to + * + * @remarks To learn about the unit strings refer to * https://mathjs.org/docs/datatypes/units.html - * + * * @param units Unit name to convert too * @returns Unit range object with converted units */ @@ -109,16 +109,16 @@ export default class UnitRange { this.max = this.min; this.min = temp; } - + return this; } /** * Creates a UnitRange from a Numeric range - * - * @remarks To learn about the unit strings refer to + * + * @remarks To learn about the unit strings refer to * https://mathjs.org/docs/datatypes/units.html - * + * * @param range Input NumericRange * @param units Unit name of range * @returns @@ -135,17 +135,16 @@ export default class UnitRange { /** * Returns a string representation of this UnitRange. - * @returns + * @returns */ toString(): string { return `(min:${this.min.toString()}, max:${this.max.toString()})`; } - /** * Check if this range is equal to the input range - * @param other Another UnitRange - * @returns + * @param other Another UnitRange + * @returns */ equals(other: UnitRange): boolean { const result = diff --git a/src/data-entry/beamProperties.tsx b/src/data-entry/beamProperties.tsx index e4b2c2e..b3cd9bf 100644 --- a/src/data-entry/beamProperties.tsx +++ b/src/data-entry/beamProperties.tsx @@ -23,7 +23,7 @@ import { unit } from "mathjs"; // todo consider splitting this into components /** * Component with data entry inputs for the Beamline. - * @returns + * @returns */ export default function BeampropertiesDataEntry() { const beamlineConfig = useBeamlineConfigStore(); diff --git a/src/data-entry/beamlineconfigStore.ts b/src/data-entry/beamlineconfigStore.ts index 361642d..ed63fcf 100644 --- a/src/data-entry/beamlineconfigStore.ts +++ b/src/data-entry/beamlineconfigStore.ts @@ -1,66 +1,108 @@ -import { BeamlineConfig } from "../utils/types"; +import { AppBeamline } from "../utils/types"; import { create } from "zustand"; -import { AngleUnits, EnergyUnits, WavelengthUnits } from "../utils/units"; -import { - presetList, - defaultConfig, - AppDataFormat } from "../presets/presetManager"; +import { + AngleUnits, + EnergyUnits, + WavelengthUnits +} from "../utils/units"; +import { + beamlineRecord, + defaultConfig, + presetConfigRecord +} from "../presets/presetManager"; import { Unit, unit } from "mathjs"; import { wavelength2EnergyConverter } from "../utils/units"; -export interface BeamlineConfigStore extends BeamlineConfig { - preset: string | null; - presetList: Record; +export interface BeamlineConfigStore extends AppBeamline { + beamline: string; + beamlineRecord: Record; + energy: Unit; userEnergy: number | null; + + wavelength: Unit; userWavelength: number | null; + + angle: Unit; userAngle: number | null; - updateAngle: (newAngle: number | null, newUnits: AngleUnits) => void; - updateAngleUnits: (newUnits: AngleUnits) => void; - updateCameraLength: (newLength: number | null) => void; + + cameraLength: number | null; + + updateBeamline: (newBeamline: string) => void; + addNewBeamline: (name: string, beamline:AppBeamline) => void; + + updateEnergy: (newEnergy: number | null, newUnits: EnergyUnits) => void; + updateEnergyUnits: (newUnits: EnergyUnits) => void; updateWavelength: ( newWavelength: number | null, newUnits: WavelengthUnits, ) => void; updateWavelengthUnits: (newUnits: WavelengthUnits) => void; - updateEnergy: (newEnergy: number | null, newUnits: EnergyUnits) => void; - updateEnergyUnits: (newUnits: EnergyUnits) => void; + updateAngle: (newAngle: number | null, newUnits: AngleUnits) => void; + updateAngleUnits: (newUnits: AngleUnits) => void; + updateCameraLength: (newLength: number | null) => void; update: (newConfig: Partial) => void; - addPreset: (name: string, preset: AppDataFormat) => void; } /** * Zustand store for information relating to the beamline */ export const useBeamlineConfigStore = create((set) => ({ - preset: Object.keys(presetList)[0], - presetList: presetList, - ...defaultConfig, + ...beamlineRecord[defaultConfig.beamline], + beamline: defaultConfig.beamline, + beamlineRecord: beamlineRecord, + + preset: Object.keys(presetConfigRecord)[0], + presetRecord: presetConfigRecord, + + energy: wavelength2EnergyConverter(defaultConfig.wavelength).to("keV"), userEnergy: wavelength2EnergyConverter(defaultConfig.wavelength) - .to("keV") - .toNumber(), + .to("keV") + .toNumber(), + + wavelength: defaultConfig.wavelength, userWavelength: defaultConfig.wavelength.toNumber(), + + angle: defaultConfig.angle, userAngle: defaultConfig.angle.toNumber(), - energy: wavelength2EnergyConverter(defaultConfig.wavelength).to("keV"), + + cameraLength: defaultConfig.cameraLength, + + updateBeamline: (newBeamline: string) => + set((state: BeamlineConfigStore) => ({ + ...state.beamlineRecord[newBeamline], + beamline: newBeamline, + })), + + addNewBeamline: (name: string, beamline: AppBeamline) => { + ( state: BeamlineConfigStore ) => { + state.beamlineRecord[name] = beamline; + } + }, + updateAngle: (newAngle: number | null, newUnits: string) => set({ angle: unit(newAngle ?? NaN, newUnits), userAngle: newAngle, }), + updateAngleUnits: (newUnits: AngleUnits) => set((state) => ({ angle: state.angle.to(newUnits), userAngle: state.angle.to(newUnits).toNumber(), })), + updateCameraLength: (newLength: number | null) => set({ cameraLength: newLength }), + updateWavelength: (newWavelength: number | null, newUnits: WavelengthUnits) => - set((state) => ({ + set((state) => ({ wavelength: unit(newWavelength ?? NaN, newUnits), userWavelength: newWavelength, minWavelength: state.minWavelength.to(newUnits), maxWavelength: state.maxWavelength.to(newUnits), })), + updateWavelengthUnits: (newUnits: WavelengthUnits) => set((state) => ({ wavelength: state.wavelength.to(newUnits), @@ -68,20 +110,19 @@ export const useBeamlineConfigStore = create((set) => ({ minWavelength: state.minWavelength.to(newUnits), maxWavelength: state.maxWavelength.to(newUnits), })), + updateEnergy: (newEnergy: number | null, newUnits: EnergyUnits) => set({ energy: unit(newEnergy ?? NaN, newUnits), userEnergy: newEnergy, }), + updateEnergyUnits: (newUnits: EnergyUnits) => set((state) => ({ energy: state.energy.to(newUnits), userEnergy: state.energy.to(newUnits).toNumber(), })), + update: (newConfig: Partial) => set({ ...newConfig }), - addPreset: (name: string, preset: AppDataFormat)=> - { (state: BeamlineConfigStore) => { - state.presetList[name] = preset; - } - } + })); diff --git a/src/data-entry/beamstop.tsx b/src/data-entry/beamstop.tsx index 5474292..14275dc 100644 --- a/src/data-entry/beamstop.tsx +++ b/src/data-entry/beamstop.tsx @@ -9,13 +9,13 @@ import { TextField, InputAdornment, } from "@mui/material"; -import { DistanceUnits } from "../utils/units"; +import { LengthUnits } from "../utils/units"; import { useBeamstopStore } from "./beamstopStore"; import { useDetectorStore } from "./detectorStore"; /** * Component with data entry inputs for the Beamstop - * @returns + * @returns */ export default function BeamStopDataEntry(): JSX.Element { const beamstop = useBeamstopStore(); @@ -65,11 +65,11 @@ export default function BeamStopDataEntry(): JSX.Element { label="units" value={beamstop.diameter.formatUnits()} onChange={(event) => - beamstop.updateDiameterUnits(event.target.value as DistanceUnits) + beamstop.updateDiameterUnits(event.target.value as LengthUnits) } > - {"mm"} - + {"mm"} + {"\u03bc" + "m"} diff --git a/src/data-entry/beamstopStore.ts b/src/data-entry/beamstopStore.ts index 4603019..92dc6be 100644 --- a/src/data-entry/beamstopStore.ts +++ b/src/data-entry/beamstopStore.ts @@ -1,29 +1,29 @@ -import { Beamstop, SimpleVector2 } from "../utils/types"; +import { AppBeamstop, SimpleVector2 } from "../utils/types"; import { create } from "zustand"; -import { DistanceUnits } from "../utils/units"; +import { LengthUnits } from "../utils/units"; import { defaultConfig } from "../presets/presetManager"; import { unit } from "mathjs"; -export interface BeamstopStore extends Beamstop { +export interface BeamstopStore extends AppBeamstop { updateCentre: (centre: Partial) => void; - updateDiameter: (newDiameter: number, newUnits: DistanceUnits) => void; - updateDiameterUnits: (newUnits: DistanceUnits) => void; + updateDiameter: (newDiameter: number, newUnits: LengthUnits) => void; + updateDiameterUnits: (newUnits: LengthUnits) => void; updateClearance: (newClearnace: number | null) => void; - updateBeamstop: (presetBeamstop: Beamstop) => void; + updateBeamstop: (presetBeamstop: AppBeamstop) => void; } /** - * Zustand store with information on the beamstop + * Zustand store for the beamstop */ export const useBeamstopStore = create((set) => ({ ...defaultConfig.beamstop, updateCentre: (newCentre: Partial) => set((state) => ({ centre: { ...state.centre, ...newCentre } })), - updateDiameter: (newDiameter: number, newUnits: DistanceUnits) => + updateDiameter: (newDiameter: number, newUnits: LengthUnits) => set({ diameter: unit(newDiameter, newUnits) }), - updateDiameterUnits: (newUnits: DistanceUnits) => + updateDiameterUnits: (newUnits: LengthUnits) => set((state) => ({ diameter: state.diameter.to(newUnits) })), updateClearance: (newClearnace: number | null) => set({ clearance: newClearnace }), - updateBeamstop: (presetBeamstop: Beamstop) => set(presetBeamstop), + updateBeamstop: (presetBeamstop: AppBeamstop) => set(presetBeamstop), })); diff --git a/src/data-entry/cameraTube.tsx b/src/data-entry/cameraTube.tsx index 414d7e2..69e4151 100644 --- a/src/data-entry/cameraTube.tsx +++ b/src/data-entry/cameraTube.tsx @@ -9,11 +9,11 @@ import { } from "@mui/material"; import { Stack } from "@mui/system"; import { useCameraTubeStore } from "./cameraTubeStore"; -import { DistanceUnits } from "../utils/units"; +import { LengthUnits } from "../utils/units"; /** * Component with inputs for cameratube data entry - * @returns + * @returns */ export default function CameraTubeDataEntry(): JSX.Element { const cameraTube = useCameraTubeStore(); @@ -44,12 +44,12 @@ export default function CameraTubeDataEntry(): JSX.Element { value={cameraTube.diameter.formatUnits()} onChange={(event) => cameraTube.updateDiameterUnits( - event.target.value as DistanceUnits, + event.target.value as LengthUnits, ) } > - {"mm"} - + {"mm"} + {"\u03bc" + "m"} diff --git a/src/data-entry/cameraTubeStore.ts b/src/data-entry/cameraTubeStore.ts index 29ccdee..be7bb2f 100644 --- a/src/data-entry/cameraTubeStore.ts +++ b/src/data-entry/cameraTubeStore.ts @@ -1,22 +1,23 @@ -import { CircularDevice, SimpleVector2 } from "../utils/types"; +import { AppCircularDevice, SimpleVector2 } from "../utils/types"; import { create } from "zustand"; -import { DistanceUnits } from "../utils/units"; +import { LengthUnits } from "../utils/units"; import { defaultConfig } from "../presets/presetManager"; -export interface CameraTubeStore extends CircularDevice { +export interface CameraTubeStore extends AppCircularDevice { updateCentre: (centre: Partial) => void; - updateDiameterUnits: (newUnits: DistanceUnits) => void; - updateCameraTube: (presetCameraTube: CircularDevice) => void; + updateDiameterUnits: (newUnits: LengthUnits) => void; + updateCameraTube: (presetCameraTube: AppCircularDevice) => void; } /** - * Zustand store with camera tube information + * Zustand store for the camera tube. */ export const useCameraTubeStore = create((set) => ({ ...defaultConfig.cameraTube, updateCentre: (newCentre: Partial) => set((state) => ({ centre: { ...state.centre, ...newCentre } })), - updateDiameterUnits: (newUnits: DistanceUnits) => + updateDiameterUnits: (newUnits: LengthUnits) => set((state) => ({ diameter: state.diameter.to(newUnits) })), - updateCameraTube: (presetCameraTube: CircularDevice) => set(presetCameraTube), + updateCameraTube: + (presetCameraTube: AppCircularDevice) => set(presetCameraTube), })); diff --git a/src/data-entry/dataSideBar.tsx b/src/data-entry/dataSideBar.tsx index 2ce08da..a5b7a37 100644 --- a/src/data-entry/dataSideBar.tsx +++ b/src/data-entry/dataSideBar.tsx @@ -12,43 +12,23 @@ import { InputLabel, Button, } from "@mui/material"; -import { DistanceUnits } from "../utils/units"; +import { LengthUnits } from "../utils/units"; import BeamStopDataEntry from "./beamstop"; import CameraTubeDataEntry from "./cameraTube"; import BeampropertiesDataEntry from "./beamProperties"; import { useBeamlineConfigStore } from "./beamlineconfigStore"; -import { presetList } from "../presets/presetManager"; -import { useBeamstopStore } from "./beamstopStore"; -import { useCameraTubeStore } from "./cameraTubeStore"; import { useDetectorStore } from "./detectorStore"; import DetectorDialog from "../dialogs/detectorDialog"; import React from "react"; -import PresetDialog from "../dialogs/presetDialog"; +import PresetDialog from "../dialogs/beamlineDialog"; /** - * React component which represents the whole side bar for data entry. + * React components which represents the whole side bar for data entry. * @returns */ export default function DataSideBar(): JSX.Element { - const detector = useDetectorStore(); - const detectorList = useDetectorStore((state) => state.detectorList); - const beamlineConfig = useBeamlineConfigStore(); - - const updateBeamstop = useBeamstopStore((state) => state.updateBeamstop); - const updateCameraTube = useCameraTubeStore( - (state) => state.updateCameraTube, - ); - const updateBeamlineConfig = useBeamlineConfigStore((state) => state.update); - const updateDetector = useDetectorStore((state) => state.updateDetector); - const handlePreset = (preset: string) => { - const { beamstop, cameraTube, detector, ...beamlineConfig } = - presetList[preset]; - updateDetector(detector); - updateBeamstop(beamstop); - updateCameraTube(cameraTube); - updateBeamlineConfig(beamlineConfig); - updateBeamlineConfig({ preset: preset }); - }; + const detectorStore = useDetectorStore(); + const beamlineConfigStore = useBeamlineConfigStore(); const [openDetector, setOpenDetector] = React.useState(false); @@ -60,63 +40,60 @@ export default function DataSideBar(): JSX.Element { setOpenDetector(false); }; - const [openPreset, setOpenPreset] = React.useState(false); + const [openBeamline, setOpenBeamline] = React.useState(false); const handleClickOpenPreset = () => { - setOpenPreset(true); + setOpenBeamline(true); }; const handleClosePreset = () => { - setOpenPreset(false); + setOpenBeamline(false); }; return ( - Preset + Beamline ( )} onChange={(_, value) => { - value ? handlePreset(value) : {}; + value ? beamlineConfigStore.updateBeamline(value) : {}; }} /> + Detector ( - + )} - value={detector.name} + value={detectorStore.name} onChange={(_, value) => { - value ? detector.updateDetector(value) : {}; + value ? detectorStore.updateDetector(value) : {}; }} />