Skip to content

Commit

Permalink
Merge pull request #385 from kruzaeva/FEMGUI
Browse files Browse the repository at this point in the history
Fluctuation EM GUI
  • Loading branch information
sk1p committed Jul 5, 2019
2 parents 0f90ccf + ba9de67 commit db404ff
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 4 deletions.
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

0 comments on commit db404ff

Please sign in to comment.