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

Fluctuation EM GUI #385

Merged
merged 7 commits into from Jul 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
121 changes: 121 additions & 0 deletions client/src/analysis/components/FEM.tsx
@@ -0,0 +1,121 @@
import * as React from "react";
import { useState } from "react";
import { useDispatch } from "react-redux";
import { defaultDebounce } from "../../helpers";
import ResultList from "../../job/components/ResultList";
import { AnalysisTypes } from "../../messages";
import { cbToRadius, inRectConstraint, riConstraint, roConstraints } from "../../widgets/constraints";
import DraggableHandle from "../../widgets/DraggableHandle";
import Ring from "../../widgets/Ring";
import { HandleRenderFunction } from "../../widgets/types";
import * as analysisActions from "../actions";
import { AnalysisProps } from "../types";
import AnalysisLayoutTwoCol from "./AnalysisLayoutTwoCol";
import useDefaultFrameView from "./DefaultFrameView";
import Toolbar from "./Toolbar";

const FEMAnalysis: React.SFC<AnalysisProps> = ({ analysis, dataset }) => {
const { shape } = dataset.params;
const [scanHeight, scanWidth, imageHeight, imageWidth] = shape;
const minLength = Math.min(imageWidth, imageHeight);

const [cx, setCx] = useState(imageWidth / 2);
const [cy, setCy] = useState(imageHeight / 2);
const [ri, setRi] = useState(minLength / 4);
const [ro, setRo] = useState(minLength / 2);

const riHandle = {
x: cx - ri,
y: cy,
}
const roHandle = {
x: cx - ro,
y: cy,
}

const handleCenterChange = defaultDebounce((newCx: number, newCy: number) => {
setCx(newCx);
setCy(newCy);
});
const handleRIChange = defaultDebounce(setRi);
const handleROChange = defaultDebounce(setRo);

const frameViewHandles: HandleRenderFunction = (handleDragStart, handleDrop) => (<>
<DraggableHandle x={cx} y={cy}
imageWidth={imageWidth}
onDragMove={handleCenterChange}
parentOnDrop={handleDrop}
parentOnDragStart={handleDragStart}
constraint={inRectConstraint(imageWidth, imageHeight)} />
<DraggableHandle x={roHandle.x} y={roHandle.y}
imageWidth={imageWidth}
onDragMove={cbToRadius(cx, cy, handleROChange)}
parentOnDrop={handleDrop}
parentOnDragStart={handleDragStart}
constraint={roConstraints(riHandle.x, cy)} />
<DraggableHandle x={riHandle.x} y={riHandle.y}
imageWidth={imageWidth}
parentOnDrop={handleDrop}
parentOnDragStart={handleDragStart}
onDragMove={cbToRadius(cx, cy, handleRIChange)}
constraint={riConstraint(roHandle.x, cy)} />
</>);

const frameViewWidgets = (
<Ring cx={cx} cy={cy} ri={ri} ro={ro}
imageWidth={imageWidth} />
)

const dispatch = useDispatch();

const runAnalysis = () => {
dispatch(analysisActions.Actions.run(analysis.id, 1, {
type: AnalysisTypes.FEM,
parameters: {
shape: "ring",
cx, cy, ri, ro,
}
}));
};

const {
frameViewTitle, frameModeSelector,
handles: resultHandles,
widgets: resultWidgets,
} = useDefaultFrameView({
scanWidth,
scanHeight,
analysisId: analysis.id,
})

const subtitle = (
<>{frameViewTitle} Ring: center=(x={cx.toFixed(2)}, y={cy.toFixed(2)}), ri={ri.toFixed(2)}, ro={ro.toFixed(2)}</>
)

const toolbar = <Toolbar analysis={analysis} onApply={runAnalysis} busyIdxs={[1]} />

return (
<AnalysisLayoutTwoCol
title="Fluctuation EM (SD over Ring analysis)" subtitle={subtitle}
left={<>
<ResultList
extraHandles={frameViewHandles} extraWidgets={frameViewWidgets}
jobIndex={0} analysis={analysis.id}
width={imageWidth} height={imageHeight}
selectors={frameModeSelector}
/>
</>}
right={<>
<ResultList
jobIndex={1} analysis={analysis.id}
width={scanWidth} height={scanHeight}
extraHandles={resultHandles}
extraWidgets={resultWidgets}
/>
</>}
toolbar={toolbar}
/>
);
}

export default FEMAnalysis;
9 changes: 9 additions & 0 deletions client/src/analysis/types.ts
@@ -1,6 +1,7 @@
import { AnalysisTypes, DatasetOpen, PickFrameDetails, SumFramesDetails } from "../messages";
import CenterOfMassAnalysis from "./components/CenterOfMassAnalysis";
import DiskMaskAnalysis from "./components/DiskMaskAnalysis";
import FEM from "./components/FEM";
import FFTAnalysis from "./components/FFTAnalysis";
import PointSelectionAnalysis from "./components/PointSelectionAnalysis";
import RadialFourierAnalysis from "./components/RadialFourierAnalysis";
Expand Down Expand Up @@ -61,6 +62,14 @@ export const AnalysisMetadata: { [s: string]: AnalysisMetadataItem } = {
title: "Disk",
component: DiskMaskAnalysis,
},

[AnalysisTypes.FEM]: {
desc: "Apply a ring mask with center cx, cy; radius r",
title: "FEM (SD over Ring)",
component: FEM,
},


[AnalysisTypes.CENTER_OF_MASS]: {
desc: "Compute the center of mass of all diffraction images",
title: "Center of mass",
Expand Down
13 changes: 10 additions & 3 deletions client/src/messages.ts
Expand Up @@ -239,6 +239,7 @@ export interface MaskDefRing {
ro: number
}


export interface MaskDefDisk {
shape: "disk",
cx: number,
Expand Down Expand Up @@ -318,6 +319,7 @@ export enum AnalysisTypes {
APPLY_FFT_MASK = "APPLY_FFT_MASK",
FFTSUM_FRAMES = "FFTSUM_FRAMES",
RADIAL_FOURIER = "RADIAL_FOURIER",
FEM = "FEM"
}

export interface RingMaskDetails {
Expand All @@ -331,6 +333,11 @@ export interface FFTDetails {
parameters: FFTParams,
}

export interface FEMDetails {
type: AnalysisTypes.FEM,
parameters: MaskDefRing,
}

export interface DiskMaskDetails {
type: AnalysisTypes.APPLY_DISK_MASK,
parameters: MaskDefDisk,
Expand Down Expand Up @@ -366,14 +373,14 @@ export interface PickFFTFrameDetails {
parameters: PickFFTFrameParams,
}


export type AnalysisParameters = MaskDefRing | MaskDefDisk | CenterOfMassParams | PointDef | PickFrameParams | RadialFourierParams | FFTParams | PickFFTFrameParams | FFTSumFramesParams;
export type AnalysisDetails = RingMaskDetails | DiskMaskDetails | CenterOfMassDetails | PointDefDetails | SumFramesDetails | PickFrameDetails | FFTDetails | RadialFourierDetails | FFTSumFramesDetails | PickFFTFrameDetails;
export interface RadialFourierDetails {
type: AnalysisTypes.RADIAL_FOURIER,
parameters: RadialFourierParams,
}

export type AnalysisParameters = MaskDefRing | MaskDefDisk | CenterOfMassParams | PointDef | PickFrameParams | RadialFourierParams| FFTParams | PickFFTFrameParams | FFTSumFramesParams;
export type AnalysisDetails = RingMaskDetails | DiskMaskDetails | CenterOfMassDetails | PointDefDetails | SumFramesDetails | PickFrameDetails | RadialFourierDetails | FEMDetails | FFTDetails | FFTSumFramesDetails | PickFFTFrameDetails;

export interface StartJobRequest {
job: {
dataset: string,
Expand Down
2 changes: 2 additions & 0 deletions src/libertem/analysis/__init__.py
Expand Up @@ -6,6 +6,7 @@
from .point import PointMaskAnalysis
from .masks import MasksAnalysis
from .raw import PickFrameAnalysis
from .fem import FEMAnalysis
from .rawfft import PickFFTFrameAnalysis
from .sumfft import SumfftAnalysis
from .apply_fft_mask import ApplyFFTMask
Expand All @@ -19,6 +20,7 @@
'PointMaskAnalysis',
'MasksAnalysis',
'PickFrameAnalysis',
'FEMAnalysis',
'PickFFTFrameAnalysis',
'SumfftAnalysis',
'ApplyFFTMask',
Expand Down
25 changes: 25 additions & 0 deletions src/libertem/analysis/fem.py
@@ -0,0 +1,25 @@
from libertem.viz import visualize_simple

from .base import BaseAnalysis, AnalysisResult, AnalysisResultSet

import libertem.udf.FEM as FEM


class FEMAnalysis(BaseAnalysis):
TYPE = "UDF"

def get_udf(self):
center = (self.parameters["cy"], self.parameters["cx"])
rad_in = self.parameters["ri"]
rad_out = self.parameters["ro"]
return FEM.FEMUDF(center=center, rad_in=rad_in, rad_out=rad_out)

def get_udf_results(self, udf_results):

return AnalysisResultSet([
AnalysisResult(raw_data=udf_results.intensity,
visualized=visualize_simple(
udf_results.intensity.reshape(self.dataset.shape.nav)),
key="intensity", title="intensity",
desc="result from SD calculation over ring"),
])
4 changes: 3 additions & 1 deletion src/libertem/web/jobs.py
Expand Up @@ -6,7 +6,8 @@

from libertem.analysis import (
DiskMaskAnalysis, RingMaskAnalysis, PointMaskAnalysis,
COMAnalysis, SumAnalysis, PickFrameAnalysis, PickFFTFrameAnalysis, SumfftAnalysis,
FEMAnalysis, COMAnalysis, SumAnalysis, PickFrameAnalysis,
PickFFTFrameAnalysis, SumfftAnalysis,
RadialFourierAnalysis, ApplyFFTMask
)
from .base import CORSMixin, run_blocking, log_message, result_images
Expand All @@ -32,6 +33,7 @@ def get_analysis_by_type(self, type_):
"RADIAL_FOURIER": RadialFourierAnalysis,
"SUM_FRAMES": SumAnalysis,
"PICK_FRAME": PickFrameAnalysis,
"FEM": FEMAnalysis,
"PICK_FFT_FRAME": PickFFTFrameAnalysis,
"APPLY_FFT_MASK": ApplyFFTMask,
}
Expand Down