Skip to content

Commit

Permalink
feat: Display integrals for the ranges
Browse files Browse the repository at this point in the history
close #1225
  • Loading branch information
hamed-musallam committed Sep 21, 2021
1 parent 31bce41 commit 2644fae
Show file tree
Hide file tree
Showing 13 changed files with 251 additions and 117 deletions.
63 changes: 10 additions & 53 deletions src/component/1d/Integral.tsx
@@ -1,34 +1,23 @@
import { ScaleLinear } from 'd3';
import { xyReduce, xyIntegral } from 'ml-spectra-processing';
import { useCallback, useMemo } from 'react';
// import { xyReduce, xyIntegral } from 'ml-spectra-processing';
import { useMemo } from 'react';

import { Datum1D } from '../../data/data1d/Spectrum1D';
import { usePreferences } from '../context/PreferencesContext';
import { integralDefaultValues } from '../panels/extra/preferences/defaultValues';
import { getValue } from '../utility/LocalStorage';

import IntegralResizable from './IntegralResizable';
import useIntegralPath from './utilities/useIntegralPath';

interface IntegralProps {
integralData: { id: string; from: number; to: number; integral?: number };
x: Array<number>;
y: Array<number>;
xDomain: number[];
integral: { id: string; from: number; to: number; integral?: number };
spectrum: Datum1D;
isActive: boolean;
scaleY: ScaleLinear<any, any, never> | null;
scaleX: any;
}

function Integral({
integralData,
x,
y,
xDomain,
isActive,
scaleY,
scaleX,
}: IntegralProps) {
const { from, to } = integralData;
function Integral({ integral, spectrum, isActive }: IntegralProps) {
const preferences = usePreferences();
const path = useIntegralPath(integral, { spectrum });

const integralSettings = useMemo(() => {
let {
Expand All @@ -38,38 +27,6 @@ function Integral({
return { color, strokeWidth };
}, [preferences]);

const integral = useMemo(() => {
return xyIntegral(
{ x: x, y: y },
{
from: from,
to: to,
reverse: true,
},
);
}, [from, to, x, y]);

const makePath = useCallback(() => {
if (integral && scaleY) {
const pathPoints = xyReduce(integral, {
from: xDomain[0],
to: xDomain[1],
nbPoints: 200,
optimize: true,
});

let path = `M ${scaleX()(pathPoints.x[0])} ${scaleY(pathPoints.y[0])}`;
path += pathPoints.x.slice(1).reduce((accumulator, point, i) => {
accumulator += ` L ${scaleX()(point)} ${scaleY(pathPoints.y[i + 1])}`;
return accumulator;
}, '');

return path;
} else {
return '';
}
}, [integral, scaleX, scaleY, xDomain]);

return (
<g>
<path
Expand All @@ -81,10 +38,10 @@ function Integral({
transformOrigin: 'center top',
opacity: isActive ? 1 : 0.2,
}}
d={makePath()}
d={path}
/>

<IntegralResizable integralData={integralData} />
<IntegralResizable integralData={integral} />
</g>
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/component/1d/IntegralResizable.tsx
Expand Up @@ -50,11 +50,11 @@ function IntegralResizable({ integralData }: IntegralResizableProps) {
const { scaleX } = useScaleChecked();
const dispatch = useDispatch();

const [{ id, integral, from, to }, setIntgral] = useState(integralData);
const [{ id, integral, from, to }, setIntegral] = useState(integralData);
const highlight = useHighlight([id], TYPES.INTEGRAL);

useEffect(() => {
setIntgral(integralData);
setIntegral(integralData);
}, [integralData]);

const handleOnStopResizing = useCallback(
Expand All @@ -76,7 +76,7 @@ function IntegralResizable({ integralData }: IntegralResizableProps) {
}, [highlight]);

const dragHandler = useCallback((boundary) => {
setIntgral((integral) => ({ ...integral, ...boundary }));
setIntegral((integral) => ({ ...integral, ...boundary }));
}, []);

const x0 = from ? scaleX()(from) : 0;
Expand Down
41 changes: 5 additions & 36 deletions src/component/1d/IntegralsSeries.tsx
@@ -1,39 +1,12 @@
import { useCallback, useMemo } from 'react';
import { useMemo } from 'react';

import { isSpectrum1D } from '../../data/data1d/Spectrum1D';
import { useChartData } from '../context/ChartContext';
import { useScale } from '../context/ScaleContext';

import Integral from './Integral';
import { getIntegralYScale } from './utilities/scale';

function IntegralsSeries() {
const {
xDomains,
xDomain,
activeSpectrum,
data,
height,
margin,
verticalAlign,
integralsYDomains,
displayerKey,
} = useChartData();
const { scaleX } = useScale();

const scaleY = useCallback(
(id) => {
if (activeSpectrum && integralsYDomains[id]) {
return getIntegralYScale(
{ height, margin, verticalAlign, integralsYDomains },
id,
);
} else {
return null;
}
},
[activeSpectrum, height, integralsYDomains, margin, verticalAlign],
);
const { xDomains, activeSpectrum, data, displayerKey } = useChartData();

const Integrals = useMemo(() => {
const isActive = (id) => {
Expand All @@ -54,19 +27,15 @@ function IntegralsSeries() {
spectrum.integrals.values.map((integral) => (
<Integral
key={integral.id}
integralData={integral}
x={spectrum.data.x}
y={spectrum.data.y}
integral={integral}
spectrum={spectrum}
isActive={isActive(spectrum.id)}
xDomain={xDomain}
scaleY={scaleY(spectrum.id)}
scaleX={scaleX}
/>
)),
)}
</g>
);
}, [activeSpectrum, data, scaleX, scaleY, xDomain, xDomains]);
}, [activeSpectrum, data, xDomains]);

return <g clipPath={`url(#${displayerKey}clip-chart-1d)`}>{Integrals}</g>;
}
Expand Down
30 changes: 30 additions & 0 deletions src/component/1d/ranges/RangeIntegral.tsx
@@ -0,0 +1,30 @@
import { useChartData } from '../../context/ChartContext';
import useIntegralPath from '../utilities/useIntegralPath';

interface IntegralProps {
range: { id: string; from: number; to: number; integral?: number };
}

function RangeIntegral({ range }: IntegralProps) {
const path = useIntegralPath(range, {
useActiveSpectrum: true,
useConstantScale: true,
});
const { height } = useChartData();

return (
<path
className="line"
stroke="black"
strokeWidth="1"
fill="none"
style={{
transformOrigin: 'center center',
transform: `translateY(-${height / 4}px)`,
}}
d={path}
/>
);
}

export default RangeIntegral;
25 changes: 17 additions & 8 deletions src/component/1d/ranges/Ranges.tsx
Expand Up @@ -8,13 +8,15 @@ import { useChartData } from '../../context/ChartContext';
import useSpectrum from '../../hooks/useSpectrum';

import Range from './Range';
import RangeIntegral from './RangeIntegral';

interface RangesInnerProps {
displayerKey: string;
selectedTool: string;
ranges: RangesProps;
editRangeID: string;
showMultiplicityTrees: boolean;
showRangesIntegrals: boolean;
}

function RangesInner({
Expand All @@ -23,17 +25,23 @@ function RangesInner({
selectedTool,
editRangeID,
showMultiplicityTrees,
showRangesIntegrals,
}: RangesInnerProps) {
return (
<g clipPath={`url(#${displayerKey}clip-chart-1d)`}>
{ranges?.values?.map((range) => (
<Range
key={range.id}
rangeData={range}
selectedTool={selectedTool}
showMultiplicityTrees={showMultiplicityTrees}
startEditMode={editRangeID && editRangeID === range.id ? true : false}
/>
<>
<Range
key={range.id}
rangeData={range}
selectedTool={selectedTool}
showMultiplicityTrees={showMultiplicityTrees}
startEditMode={
editRangeID && editRangeID === range.id ? true : false
}
/>
{showRangesIntegrals && <RangeIntegral range={range} />}
</>
))}
</g>
);
Expand All @@ -48,7 +56,7 @@ export default function Ranges() {
displayerKey,
toolOptions: {
selectedTool,
data: { tempRange, showMultiplicityTrees },
data: { tempRange, showMultiplicityTrees, showRangesIntegrals },
},
} = useChartData();

Expand All @@ -59,6 +67,7 @@ export default function Ranges() {
{...{
ranges,
showMultiplicityTrees,
showRangesIntegrals,
selectedTool,
displayerKey,
editRangeID: tempRange?.id || '',
Expand Down
15 changes: 13 additions & 2 deletions src/component/1d/utilities/scale.ts
@@ -1,4 +1,4 @@
import { scaleLinear } from 'd3';
import { scaleLinear, zoomIdentity } from 'd3';

function getXScale(state, spectrumId: number | null | string = null) {
const { width, margin, xDomains, xDomain, mode } = state;
Expand Down Expand Up @@ -36,4 +36,15 @@ function getIntegralYScale(state, spectrumId) {
]);
}

export { getXScale, getYScale, getIntegralYScale };
function reScaleY(scale: number, { domain, height, margin }) {
const _scale = scaleLinear(domain, [height - margin.bottom, margin.top]);

const t = zoomIdentity
.translate(0, _scale(0))
.scale(scale)
.translate(0, -_scale(0));

return t.rescaleY(_scale).domain();
}

export { getXScale, getYScale, getIntegralYScale, reScaleY };

0 comments on commit 2644fae

Please sign in to comment.