diff --git a/src/calculations/detectorProps.ts b/src/calculations/detectorProps.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/calculations/diffractionCrystalEnvironment.ts b/src/calculations/diffractionCrystalEnvironment.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/calculations/qspace.test.ts b/src/calculations/qspace.test.ts new file mode 100644 index 0000000..1d115a1 --- /dev/null +++ b/src/calculations/qspace.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from "vitest"; +import { Vector4, Vector3 } from "three"; +import QSpace, { DetectorProperties } from "./qspace"; + +test("Test getting q from pixel position ", () => { + const detProps: DetectorProperties = { + resolution: { + height: 1, + width: 1 + }, + pixelSize: { + height: 1, + width: 1 + }, + origin: new Vector3(0, 0, 0), + beamVector: new Vector3(1, 1, 0), + } + + const diffCrystEnv = { + wavelength: 1, + referenceNormal: new Vector3(1, 1, 1), + strokesVector: new Vector4(1, 0, 1, 0), + } + + const qspace = new QSpace(detProps, diffCrystEnv, 1) + const result = qspace.qFromPixelPosition(1, 1) + expect(result).toBeInstanceOf(Vector3) + console.log(result) + // do better testing when you understand it better +}); diff --git a/src/calculations/qspace.ts b/src/calculations/qspace.ts index 84f9102..9ed604d 100644 --- a/src/calculations/qspace.ts +++ b/src/calculations/qspace.ts @@ -1,19 +1,56 @@ import { Vector3, Vector4 } from "three"; import { Detector } from "../utils/types"; +export interface DiffractionCrystalEnvironment { + wavelength: number; + referenceNormal: Vector3; + strokesVector: Vector4; +} + +export interface DetectorProperties extends Detector { + origin: Vector3; + beamVector: Vector3; +} export default class QSpace { - static QSCALE_DEFAULT = 2 * Math.PI; - private detector: Detector; - private kmod: number; - private ki: Vector3; - private mki: Vector3; - private qScale: number; - private residual: number; - private refrennce: Vector3; - private stroks: Vector4; + detProps: DetectorProperties; + kmod: number; + reference: Vector3; + strokes: Vector4; + qScale: number; + mki: Vector3; + + constructor(detProps: DetectorProperties, diffexp: DiffractionCrystalEnvironment, qScale: number) { + this.detProps = detProps; + detProps.beamVector.normalize() + this.qScale = qScale + this.mki = new Vector3().copy(detProps.beamVector).negate() + this.kmod = this.qScale / diffexp.wavelength; + this.reference = diffexp.referenceNormal; + this.strokes = diffexp.strokesVector; + } - constructor(detector: Detector, diffexp: DiffractionCrystalEnvironment, scale: number) { + convertToQ(q: Vector3) { + const qLength = q.length(); + if (qLength > 0) { + q.multiplyScalar(this.kmod / qLength); + q.add(this.mki) + } else { + q.add(this.mki); + } + } + + qFromPixelPosition(x: number, y: number) { + const q = new Vector3(); + q.set(-this.detProps.pixelSize.height * (x), -this.detProps.pixelSize.width * (y), 0); + q.add(this.detProps.origin); + this.convertToQ(q); + return q + } + setDiffractionCrystalEnviroment(diffexp: DiffractionCrystalEnvironment) { + this.kmod = this.qScale / diffexp.wavelength; + this.reference = diffexp.referenceNormal; + this.strokes = diffexp.strokesVector; } -} \ No newline at end of file +} diff --git a/src/presets/detectors.json b/src/presets/detectors.json index 847479c..60764f0 100644 --- a/src/presets/detectors.json +++ b/src/presets/detectors.json @@ -4,14 +4,20 @@ "width": 1, "height": 1 }, - "pixelSize": 1 + "pixelSize": { + "width": 1, + "height": 1 + } }, "Pilatus P3-2M": { "resolution": { "width": 1475, "height": 1679 }, - "pixelSize": 0.172 + "pixelSize": { + "width": 0.172, + "height": 0.172 + } }, "long boy": { "resolution": { @@ -20,4 +26,4 @@ }, "pixelSize": 0.2 } -} +} \ No newline at end of file diff --git a/src/results/results.ts b/src/results/results.ts deleted file mode 100644 index 768ff06..0000000 --- a/src/results/results.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Vector3 } from "three" -import { BeamlineConfig, Beamstop, CircularDevice, Detector } from "../utils/types" -import { Ray } from "../calculations/ray"; -import NumericRange from "../calculations/numericRange"; - - -const computeQRanges = (detector: Detector, beamstop: Beamstop, cameraTube: CircularDevice, beamProperties: BeamlineConfig) => { - const initialPosition = new Vector3(beamstop.clearance ?? 0 * Math.cos(beamProperties.angle ?? 0) + (beamstop.centre.y ?? 0), - beamstop.clearance ?? 0 * Math.sin(beamProperties.angle ?? 0) + (beamstop.centre.y ?? 0)) - - const ray = new Ray(new Vector3(Math.cos(beamProperties.angle ?? 0), Math.sin(beamProperties.angle ?? 0)), initialPosition); - let t1 = ray.getRectangleIntersectionParameterRange(new Vector3(0, detector.resolution.height), detector.resolution.width, detector.resolution.height) - - if (t1 != null && cameraTube != null && cameraTube.diameter != 0) { - t1 = t1.intersect(ray.getCircleIntersectionParameterRange((cameraTube.diameter ?? 0) / 2, new Vector3(cameraTube.centre.x ?? 0, cameraTube.centre.y ?? 0))); - } - - if (t1 === null || beamProperties.wavelength == null || beamProperties.cameraLength == null) { - return null - } - - const ptMin = ray.getPoint(t1.min); - const ptMax = ray.getPoint(t1.max); - - -} \ No newline at end of file diff --git a/src/results/resultsStore.ts b/src/results/resultsStore.ts index 82f779d..60fdd62 100644 --- a/src/results/resultsStore.ts +++ b/src/results/resultsStore.ts @@ -1,5 +1,10 @@ import { create } from "zustand"; import { AngleUnits, WavelengthUnits } from "../utils/units"; +import QSpace, { DetectorProperties, DiffractionCrystalEnvironment } from "../calculations/qspace"; +import NumericRange from "../calculations/numericRange"; +import { BeamlineConfig, Beamstop, CircularDevice, Detector } from "../utils/types"; +import { Vector2, Vector3, Vector4 } from "three"; +import { Ray } from "../calculations/ray"; interface ScatteringQuantity { name: string, @@ -13,8 +18,61 @@ export interface ResultStore { selected: string, q: ScatteringQuantity, qUnits: WavelengthUnits, + qspace: QSpace twoTheta: ScatteringQuantity thetaUnits: AngleUnits + visableQRange: NumericRange + fullQRange: NumericRange } +function computeQrange(detector: Detector, beamstop: Beamstop, cameraTube: CircularDevice, beamProperties: BeamlineConfig) { + const initialPosition = new Vector3(beamstop.clearance ?? 0 * Math.cos(beamProperties.angle ?? 0) + (beamstop.centre.y ?? 0), + beamstop.clearance ?? 0 * Math.sin(beamProperties.angle ?? 0) + (beamstop.centre.y ?? 0)) + + const ray = new Ray(new Vector3(Math.cos(beamProperties.angle ?? 0), Math.sin(beamProperties.angle ?? 0)), initialPosition); + let t1 = ray.getRectangleIntersectionParameterRange(new Vector3(0, detector.resolution.height), detector.resolution.width, detector.resolution.height) + + if (t1 != null && cameraTube != null && cameraTube.diameter != 0) { + t1 = t1.intersect(ray.getCircleIntersectionParameterRange((cameraTube.diameter ?? 0) / 2, new Vector3(cameraTube.centre.x ?? 0, cameraTube.centre.y ?? 0))); + } + + if (t1 === null || beamProperties.wavelength == null || beamProperties.cameraLength == null) { + return null + } + + const ptMin = ray.getPoint(t1.min); + const ptMax = ray.getPoint(t1.max); + + const detProps: DetectorProperties = { + ...detector, + origin: new Vector3(beamstop.centre.x ?? 0, beamstop.centre.y ?? 0, beamProperties.cameraLength * 1e-3), + beamVector: new Vector3(0, 0, 1) + } + + const diffCrystEnv: DiffractionCrystalEnvironment = { + wavelength: beamProperties.wavelength * 1e10, + referenceNormal: new Vector3(0, 1, 0), + strokesVector: new Vector4(1, 1, 0, 0) + } + + const qspace = new QSpace(detProps, diffCrystEnv, 2 * Math.PI) + + // get visible range + const visibleQmin = qspace.qFromPixelPosition(ptMin.x / detector.pixelSize.width, ptMin.y / detector.pixelSize.height) + const visibleQmax = qspace.qFromPixelPosition(ptMax.x / detector.pixelSize.width, ptMax.y / detector.pixelSize.height) + + + detProps.origin.z = beamProperties.minCameraLength * 1e3 + qspace.setDiffractionCrystalEnviroment({ ...diffCrystEnv, wavelength: beamProperties.minCameraLength * 1e10 }) + const fullQMin = qspace.qFromPixelPosition(ptMin.x / detector.pixelSize.width, ptMin.y / detector.pixelSize.height) + + detProps.origin.z = beamProperties.maxCameraLength * 1e3 + qspace.setDiffractionCrystalEnviroment({ ...diffCrystEnv, wavelength: beamProperties.maxCameraLength * 1e10 }) + const fullQMax = qspace.qFromPixelPosition(ptMax.x / detector.pixelSize.width, ptMax.y / detector.pixelSize.height) + + return { visibleQmin: visibleQmin, visibleQmax: visibleQmax, fullQMax, fullQMin } + +} + + diff --git a/src/utils/types.ts b/src/utils/types.ts index 8a8c60d..09f476e 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,15 +1,15 @@ export interface Detector { resolution: { height: number; width: number }; - pixelSize: number; + pixelSize: { height: number; width: number }; } -export interface SerialisedVector2 { +export interface SimpleVector2 { x?: number | null; y?: number | null; } export interface CircularDevice { - centre: SerialisedVector2; + centre: SimpleVector2; diameter: number; }