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 5 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 PointSelectionAnalysis from "./components/PointSelectionAnalysis";
import RadialFourierAnalysis from "./components/RadialFourierAnalysis";
import RingMaskAnalysis from "./components/RingMaskAnalysis";
Expand Down Expand Up @@ -59,6 +60,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
9 changes: 8 additions & 1 deletion 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 @@ -293,13 +294,19 @@ export enum AnalysisTypes {
SUM_FRAMES_ROI = "SUM_FRAMES_ROI",
PICK_FRAME = "PICK_FRAME",
RADIAL_FOURIER = "RADIAL_FOURIER",
FEM = "FEM"
}

export interface RingMaskDetails {
type: AnalysisTypes.APPLY_RING_MASK,
parameters: MaskDefRing,
}

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

export interface DiskMaskDetails {
type: AnalysisTypes.APPLY_DISK_MASK,
parameters: MaskDefDisk,
Expand Down Expand Up @@ -331,7 +338,7 @@ export interface RadialFourierDetails {
}

export type AnalysisParameters = MaskDefRing | MaskDefDisk | CenterOfMassParams | PointDef | PickFrameParams | RadialFourierParams;
export type AnalysisDetails = RingMaskDetails | DiskMaskDetails | CenterOfMassDetails | PointDefDetails | SumFramesDetails | PickFrameDetails | RadialFourierDetails;
export type AnalysisDetails = RingMaskDetails | DiskMaskDetails | CenterOfMassDetails | PointDefDetails | SumFramesDetails | PickFrameDetails | RadialFourierDetails | FEMDetails;

export interface StartJobRequest {
job: {
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 ApplyFEM

__all__ = [
'SumAnalysis',
Expand All @@ -16,4 +17,5 @@
'PointMaskAnalysis',
'MasksAnalysis',
'PickFrameAnalysis',
'ApplyFEM',
]
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 ApplyFEM(BaseAnalysis):
kruzaeva marked this conversation as resolved.
Show resolved Hide resolved
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"),
])
3 changes: 2 additions & 1 deletion src/libertem/web/jobs.py
Expand Up @@ -6,7 +6,7 @@

from libertem.analysis import (
DiskMaskAnalysis, RingMaskAnalysis, PointMaskAnalysis,
COMAnalysis, SumAnalysis, PickFrameAnalysis, RadialFourierAnalysis
COMAnalysis, SumAnalysis, PickFrameAnalysis, RadialFourierAnalysis, ApplyFEM
)
from .base import CORSMixin, run_blocking, log_message, result_images
from .messages import Message
Expand All @@ -30,6 +30,7 @@ def get_analysis_by_type(self, type_):
"RADIAL_FOURIER": RadialFourierAnalysis,
"SUM_FRAMES": SumAnalysis,
"PICK_FRAME": PickFrameAnalysis,
"FEM": ApplyFEM,
}
return analysis_by_type[type_]

Expand Down