From 9cdd17953328c7f547808cbf2f6bbb6e37525486 Mon Sep 17 00:00:00 2001 From: tizayi Date: Thu, 15 Aug 2024 17:16:17 +0100 Subject: [PATCH] working mask stripes --- package-lock.json | 60 ++++++++-------- package.json | 2 +- src/app.tsx | 16 ++++- src/plot/centrePlot.tsx | 16 ++++- src/plot/svgMask.tsx | 105 ++++++++++++++++++++++++++++ src/results/rangeTable.tsx | 16 ++--- src/results/resultsBar.tsx | 6 +- src/results/resultsStore.ts | 9 +-- src/results/scatteringQuantities.ts | 16 ++--- 9 files changed, 186 insertions(+), 60 deletions(-) create mode 100644 src/plot/svgMask.tsx diff --git a/package-lock.json b/package-lock.json index 43b2eff..426ef98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", - "@h5web/lib": "^11.2.0", + "@h5web/lib": "^12.0.1", "@mui/icons-material": "^5.15.3", "@mui/material": "^5.14.17", "@mui/system": "^5.15.9", @@ -800,6 +800,20 @@ "@floating-ui/utils": "^0.2.0" } }, + "node_modules/@floating-ui/react": { + "version": "0.26.14", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.14.tgz", + "integrity": "sha512-I2EhfezC+H0WfkMEkCcF9+++PU1Wq08bDKhHHGIoBZVCciiftEQHgrSI4dTUTsa7446SiIVW0gWATliIlVNgfg==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@floating-ui/utils": "^0.2.0", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/@floating-ui/react-dom": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", @@ -818,10 +832,11 @@ "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, "node_modules/@h5web/lib": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@h5web/lib/-/lib-11.2.0.tgz", - "integrity": "sha512-itB2zy/cv+tn55ydUk4zqc5/2aVL8984v98rClxrwxj10JIRlLKFz+g0RSDyAqhWUOjONcAG7Ud1kX9byX0WsQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@h5web/lib/-/lib-12.0.1.tgz", + "integrity": "sha512-HuJJjsgxkWn6rPAX0W4tMJSMNh6xYLHw9YZqraAo2t8Gk5Xcddh0Pnd1ilJNss3LHu+vz2ASich5NUHxV01MOA==", "dependencies": { + "@floating-ui/react": "0.26.14", "@react-hookz/web": "24.0.4", "@visx/axis": "3.10.1", "@visx/drag": "3.3.0", @@ -837,8 +852,7 @@ "d3-scale-chromatic": "3.1.0", "ndarray": "1.0.19", "ndarray-ops": "1.2.2", - "react-aria-menubutton": "7.0.3", - "react-icons": "5.0.1", + "react-icons": "5.2.1", "react-keyed-flatten-children": "3.0.0", "react-measure": "2.5.2", "react-slider": "2.0.4", @@ -4422,11 +4436,6 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/focus-group": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/focus-group/-/focus-group-0.3.1.tgz", - "integrity": "sha512-IA01dzk2cStQso/qnt2rWhXCFBZlBfjZmohB9mXUx9feEaJcORAK0FQGvwaApsNNGwzEnqrp/2qTR4lq8PXfnQ==" - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -6733,19 +6742,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-aria-menubutton": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/react-aria-menubutton/-/react-aria-menubutton-7.0.3.tgz", - "integrity": "sha512-Ql4W3rNiZmuVJ1wQ0UUeV4OZX3IZq2evsfEqJGefSMdfkK6o8X/6Ufxrzu0wL+/Dr7JUY3xnrnIQimSCFghlCQ==", - "dependencies": { - "focus-group": "^0.3.1", - "prop-types": "^15.6.0", - "teeny-tap": "^0.2.0" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.0" - } - }, "node_modules/react-color": { "version": "2.19.3", "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", @@ -6791,9 +6787,9 @@ } }, "node_modules/react-icons": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz", - "integrity": "sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", + "integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==", "peerDependencies": { "react": "*" } @@ -7789,10 +7785,10 @@ "react": ">=17.0" } }, - "node_modules/teeny-tap": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/teeny-tap/-/teeny-tap-0.2.0.tgz", - "integrity": "sha512-HnA3I2sxRQe/SZgQTQgQvvA17DhfzhBJ1LfSOXZ5VUTbxGLvnAqUef84ZGNNSEbk1ZMEIDeghTHZagJ7LifAgg==" + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" }, "node_modules/text-table": { "version": "0.2.0", @@ -8060,7 +8056,7 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 0b6944d..2e110f4 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", - "@h5web/lib": "^11.2.0", + "@h5web/lib": "^12.0.1", "@mui/icons-material": "^5.15.3", "@mui/material": "^5.14.17", "@mui/system": "^5.15.9", diff --git a/src/app.tsx b/src/app.tsx index 6398410..a5a29e5 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,14 +1,27 @@ -import { Stack} from "@mui/material"; +import { Stack, ThemeProvider, createTheme } from "@mui/material"; import DataSideBar from "./data-entry/dataSideBar"; import CentrePlot from "./plot/centrePlot"; import BasicAppBar from "./basicAppBar"; import CssBaseline from '@mui/material/CssBaseline'; +const theme = createTheme({ + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 900, + lg: 1500, + xl: 1536, + }, + }, +}); + export default function App(): JSX.Element { return ( <> + + ); diff --git a/src/plot/centrePlot.tsx b/src/plot/centrePlot.tsx index 431fd28..fe4e4ae 100644 --- a/src/plot/centrePlot.tsx +++ b/src/plot/centrePlot.tsx @@ -25,7 +25,7 @@ import { } from "../results/resultsStore"; import { convertBetweenQAndD, - convertBetweenQAndS, + convertFromQTooS, } from "../results/scatteringQuantities"; import { AppBeamline, @@ -41,6 +41,7 @@ import { UnitVector, color2String, getDomains } from "./plotUtils"; import SvgAxisAlignedEllipse from "./svgEllipse"; import { useMemo } from "react"; import { formatLogMessage } from "../utils/units"; +import SvgMask from "./svgMask"; /** * A react componenet that plots the items that make up the system @@ -171,7 +172,7 @@ export default function CentrePlot(): JSX.Element { return ( - +
)} + {plotConfig.detector && ( + + )} {plotConfig.inaccessibleRange && ( UnitRange | null { result = convertBetweenQAndD(unit(value, state.dUnits)); break; case ScatteringOptions.s: - result = convertBetweenQAndS(unit(value, state.sUnits)); + result = convertFromQTooS(unit(value, state.sUnits)); break; default: result = unit(value, state.qUnits); diff --git a/src/plot/svgMask.tsx b/src/plot/svgMask.tsx new file mode 100644 index 0000000..75c65cb --- /dev/null +++ b/src/plot/svgMask.tsx @@ -0,0 +1,105 @@ +import { SvgRect } from '@h5web/lib'; +import type { SVGProps } from 'react'; +import { Vector3 } from 'three'; + +type Rect = [Vector3, Vector3]; + +interface Props extends SVGProps { + coords: Rect; + strokePosition?: 'inside' | 'outside'; + strokeWidth?: number; + numModules: Vector3, + gapFraction: Vector3, + missingSegments: number[] +} + +function SvgMask(props: Props){ + // watch out some crazy insane big boy maths is incoming + const [detectorUpper, detectorLower] = props.coords; + // check if clone is needed later on + const fulllength = detectorLower.clone().sub(detectorUpper); + const gaplength = fulllength.clone().multiply(props.gapFraction); + const moduleLength = + fulllength.clone() + .sub(gaplength.clone() + .multiply(props.numModules)) + .divide(props.numModules); + + return ( + <> + {/* plot vertical stripes */} + {[...Array(props.numModules.x -1).keys()].map((i:number) => + ) + } + {/* plot horizontal stripes */} + {[...Array(props.numModules.y -1).keys()].map((i:number) => + ) + } + + ) +} + +export type {Props as SvgMaskProps}; +export default SvgMask; + + + +function generateLowerBound( + moduleLen: number, gapLen:number, moduleNum: number): number{ + return moduleNum*moduleLen + (moduleNum-1)*gapLen +} + +function generateUpperBound( + moduleLen: number, gapLen:number, moduleNum: number): number{ + return moduleNum*moduleLen + moduleNum*gapLen +} + +function generateVerticalStripes( + coords: Rect, + moduleLenX: number, + gapLenX: number, + moduleNum: number): Rect{ + return [ + new Vector3( + coords[0].x + generateLowerBound(moduleLenX, gapLenX, moduleNum), + coords[0].y), + new Vector3( + coords[0].x + generateUpperBound(moduleLenX, gapLenX, moduleNum), + coords[1].y) + ] +} + +function generateHorizontalStripes( + coords: Rect, + moduleLenY: number, + gapLenY: number, + moduleNum: number): Rect{ + return [ + new Vector3(coords[0].x, + coords[0].y + generateLowerBound(moduleLenY, gapLenY, moduleNum)), + new Vector3(coords[1].x, + coords[0].y + generateUpperBound(moduleLenY, gapLenY, moduleNum)) + ] +} \ No newline at end of file diff --git a/src/results/rangeTable.tsx b/src/results/rangeTable.tsx index af6332b..9d3b780 100644 --- a/src/results/rangeTable.tsx +++ b/src/results/rangeTable.tsx @@ -15,7 +15,7 @@ import { ScatteringOptions, useResultStore } from "./resultsStore"; import { ReciprocalWavelengthUnits, WavelengthUnits } from "../utils/units"; import { convertBetweenQAndD, - convertBetweenQAndS, + convertFromQTooS, } from "./scatteringQuantities"; import UnitRange from "../calculations/unitRange"; @@ -31,8 +31,8 @@ export default function RangeTable(props: { qRange: UnitRange }): JSX.Element { updateQUnits(event.target.value as ReciprocalWavelengthUnits); }; - const handleSunits = (event: SelectChangeEvent) => { - updateSUnits(event.target.value as WavelengthUnits); + const handleSunits = (event: SelectChangeEvent) => { + updateSUnits(event.target.value as ReciprocalWavelengthUnits); }; const handleDunits = (event: SelectChangeEvent) => { @@ -40,7 +40,7 @@ export default function RangeTable(props: { qRange: UnitRange }): JSX.Element { }; const qRange = props.qRange.to(resultsStore.qUnits as string); const sRange = props.qRange - .apply(convertBetweenQAndS) + .apply(convertFromQTooS) .to(resultsStore.sUnits as string); const dRange = props.qRange .apply(convertBetweenQAndD) @@ -118,11 +118,11 @@ export default function RangeTable(props: { qRange: UnitRange }): JSX.Element { value={resultsStore.sUnits} onChange={handleSunits} > - - {WavelengthUnits.nanometres} + + {"1 / nm"} - - {"\u212B"} + + {"1 / " + "\u212B"} diff --git a/src/results/resultsBar.tsx b/src/results/resultsBar.tsx index 08a1ae4..2855b5d 100644 --- a/src/results/resultsBar.tsx +++ b/src/results/resultsBar.tsx @@ -25,7 +25,7 @@ import RangeTable from "./rangeTable"; import { ResultStore, ScatteringOptions, useResultStore } from "./resultsStore"; import { convertBetweenQAndD, - convertBetweenQAndS, + convertFromSTooQ, } from "./scatteringQuantities"; function getVisibilitySettings( @@ -55,8 +55,8 @@ function getVisibilitySettings( textBoxUnits = resultStore.dUnits; break; case ScatteringOptions.s: - diagramVisible = visableQRange.apply(convertBetweenQAndS).to("nm"); - diagramFull = fullQrange.apply(convertBetweenQAndS).to("nm"); + diagramVisible = visableQRange.apply(convertFromSTooQ).to("nm"); + diagramFull = fullQrange.apply(convertFromSTooQ).to("nm"); diagramRequested = UnitRange.fromNumericRange( requestedRange, resultStore.sUnits as string, diff --git a/src/results/resultsStore.ts b/src/results/resultsStore.ts index e8c3411..4cfecb1 100644 --- a/src/results/resultsStore.ts +++ b/src/results/resultsStore.ts @@ -12,7 +12,7 @@ export enum ScatteringOptions { export interface ResultStore { requested: ScatteringOptions; qUnits: ReciprocalWavelengthUnits; - sUnits: WavelengthUnits; + sUnits: ReciprocalWavelengthUnits; dUnits: WavelengthUnits; requestedMin: number | null; requestedMax: number | null; @@ -24,7 +24,7 @@ export interface ResultStore { }>, ) => void; updateQUnits: (newunits: ReciprocalWavelengthUnits) => void; - updateSUnits: (newunits: WavelengthUnits) => void; + updateSUnits: (newunits: ReciprocalWavelengthUnits) => void; updateDUnits: (newunits: WavelengthUnits) => void; } @@ -34,7 +34,7 @@ export interface ResultStore { export const useResultStore = create((set) => ({ requested: ScatteringOptions.q, qUnits: ReciprocalWavelengthUnits.nanometres, - sUnits: WavelengthUnits.nanometres, + sUnits: ReciprocalWavelengthUnits.nanometres, dUnits: WavelengthUnits.nanometres, requestedMin: null, requestedMax: null, @@ -51,6 +51,7 @@ export const useResultStore = create((set) => ({ }, updateQUnits: (newunits: ReciprocalWavelengthUnits) => set({ qUnits: newunits }), - updateSUnits: (newunits: WavelengthUnits) => set({ sUnits: newunits }), + updateSUnits: (newunits: ReciprocalWavelengthUnits) => + set({ sUnits: newunits }), updateDUnits: (newunits: WavelengthUnits) => set({ dUnits: newunits }), })); diff --git a/src/results/scatteringQuantities.ts b/src/results/scatteringQuantities.ts index d460196..82a2a89 100644 --- a/src/results/scatteringQuantities.ts +++ b/src/results/scatteringQuantities.ts @@ -1,7 +1,7 @@ import { Unit, divide, multiply } from "mathjs"; -export const convertBetweenQAndS = (quantity: Unit): Unit => { - const result = divide(1, quantity); +export const convertFromQTooS = (quantity: Unit): Unit => { + const result = multiply(quantity, 2 * Math.PI); if (typeof result == "number" || !("units" in result)) { throw TypeError("name this error later "); } @@ -16,18 +16,18 @@ export const convertBetweenQAndD = (quantity: Unit): Unit => { return result; }; -export const convertFromDTooS = (quantity: Unit): Unit => { - const result = divide(quantity, 2 * Math.PI); +export const convertBetweenDandS = (quantity: Unit): Unit => { + const result = divide(4* Math.pow(Math.PI,2),quantity); if (typeof result == "number" || !("units" in result)) { throw TypeError(""); } return result; }; -export const convertFromStooD = (quantity: Unit): Unit => { - const result = multiply(quantity, 2 * Math.PI); +export const convertFromSTooQ = (quantity: Unit): Unit => { + const result = divide(quantity, 2 * Math.PI); if (typeof result == "number" || !("units" in result)) { - throw TypeError(""); + throw TypeError("name this error later "); } return result; -}; +} \ No newline at end of file