Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 34 additions & 26 deletions src/component/2d/utilities/extractSpectrumSignals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,54 @@ interface ExtractSpectrumSignalsOptions<T> {
from?: number;
to?: number;
include?: (range: Range) => T;
onlyFirstSignal?: boolean;
}

function isRangeInBounds(range: Range, from?: number, to?: number): boolean {
if (typeof from === 'number' && typeof to === 'number') {
return range.from <= to && range.to >= from;
}
if (typeof to === 'number') {
return range.to <= to;
}
if (typeof from === 'number') {
return range.from >= from;
}
return true;
}

export function extractSpectrumSignals<T extends object = object>(
spectrum: Spectrum1D,
options: ExtractSpectrumSignalsOptions<T> = {},
) {
const result: Array<ExtractedSignal<T>> = [];
const { from, to, include } = options;
): Array<ExtractedSignal<T>> {
const { from, to, include, onlyFirstSignal = false } = options;

const ranges = spectrum?.ranges?.values;
if (!Array.isArray(ranges) || ranges?.length === 0) {
if (!Array.isArray(ranges) || ranges.length === 0) {
return [];
}

for (const range of ranges) {
const rangeFrom = range.from;
const rangeTo = range.to;
let isInRange = true;

if (typeof from === 'number' && typeof to === 'number') {
isInRange = rangeFrom <= to && rangeTo >= from;
} else if (typeof to === 'number') {
isInRange = rangeTo <= to;
} else if (typeof from === 'number') {
isInRange = rangeFrom >= from;
}
const result: Array<ExtractedSignal<T>> = [];

if (!isInRange) continue;
for (const range of ranges) {
if (!isRangeInBounds(range, from, to)) continue;

const { signals = [] } = range;
let index = 0;
let includedCount = 0;

for (const signal of signals) {
const { kind, assignment } = signal;
if (kind && signalKindsToInclude.has(kind)) {
result.push({
...signal,
assignment: index === 0 ? assignment : '',
...include?.(range),
} as ExtractedSignal<T>);
index++;
}
if (!kind || !signalKindsToInclude.has(kind)) continue;

const keepAssignment = !onlyFirstSignal || includedCount === 0;

result.push({
...signal,
assignment: keepAssignment ? assignment : '',
...include?.(range),
} as ExtractedSignal<T>);

includedCount++;
}
}

Expand Down
41 changes: 17 additions & 24 deletions src/component/2d/zones/SignalsGuideLines.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import { PiTextTBold, PiTextTSlashBold } from 'react-icons/pi';

import { isAssigned } from '../../../data/data1d/Spectrum1D/isRangeAssigned.js';
import { FieldEdition } from '../../1d-2d/FieldEdition.js';
import {
useAssignment,
useAssignmentContext,
} from '../../assignment/AssignmentsContext.js';
import { filterAssignedIDs } from '../../assignment/utilities/filterAssignedIDs.js';
import { useAssignment } from '../../assignment/AssignmentsContext.js';
import { useChartData } from '../../context/ChartContext.js';
import { useDispatch } from '../../context/DispatchContext.js';
import {
Expand Down Expand Up @@ -76,6 +72,7 @@ function useSignalsOverlap(axis: IndicationLinesAxis, spectrum: Spectrum1D) {
const processedSignals: ProcessedSignal[] = signals.map((signal) => {
const { delta, assignment } = signal;
const text = assignment ?? '';

const labelWidth = getTextWidth(text);

return {
Expand Down Expand Up @@ -151,23 +148,23 @@ function getAxisRangeId(options: GetAxisRangeIdOptions) {

interface UseRangeAssignmentOptions {
rangeId: string;
signalsIds: string[];
spectrumId: string;
signalId: string;
}

function useRangeAssignment(options: UseRangeAssignmentOptions) {
const { rangeId, signalsIds, spectrumId, signalId } = options;
const { rangeId, spectrumId, signalId } = options;

const assignmentData = useAssignmentContext();
// const assignmentData = useAssignmentContext();
const assignmentContext = useAssignment(signalId, spectrumId);
const highlightId = [rangeId]
.concat(assignmentContext.assignedDiaIds?.x || [])
.concat(filterAssignedIDs(assignmentData.data, signalsIds));
const highlightId = [signalId].concat(
assignmentContext.assignedDiaIds?.x || [],
);
// .concat(filterAssignedIDs(assignmentData.data, signalsIds));

const highlightContext = useHighlight(highlightId, {
type: 'RANGE',
extra: { id: rangeId, spectrumID: spectrumId },
type: 'SIGNAL_1D',
extra: { id: signalId, rangeId, spectrumID: spectrumId },
});

return { highlightContext, assignmentContext };
Expand All @@ -180,10 +177,8 @@ function isRangeSignalAssigned(
return isAssigned(otherProps);
}

function hasDiaIds(signals: Signal1D[]) {
return signals.some(
(signal) => Array.isArray(signal?.diaIDs) && signal.diaIDs.length > 0,
);
function hasDiaIds(signal: Partial<Signal1D>) {
return Array.isArray(signal?.diaIDs) && signal.diaIDs.length > 0;
}

function IndicationLine(props: IndicationLineProps) {
Expand All @@ -199,23 +194,20 @@ function IndicationLine(props: IndicationLineProps) {
nbAtoms,
id: signalId,
} = props;
const { id: rangeId, signals } = range;
const { id: rangeId } = range;
const highlightColor = useHighlightColor();
const isSignalAssigned = isRangeSignalAssigned({ range, diaIDs, nbAtoms });

const signalsIds = signals.map(({ id }) => id);
const { margin, width, height } = useChartData();
const { setData: addNewAssignmentLabel } = useShareData();

const dispatch = useDispatch();
const { assignmentContext, highlightContext } = useRangeAssignment({
rangeId,
spectrumId,
signalsIds,
signalId,
});

const hasDiaIDs = hasDiaIds(signals);
const hasDiaIDs = hasDiaIds({ nbAtoms, diaIDs });
const isAssignmentActive = assignmentContext.isActive;
const isHighlighted = highlightContext.isActive || isAssignmentActive;

Expand Down Expand Up @@ -269,6 +261,7 @@ function IndicationLine(props: IndicationLineProps) {
type: 'UNASSIGN_1D_SIGNAL',
payload: {
rangeKey: rangeId,
signalId,
spectrumId,
},
});
Expand All @@ -279,13 +272,13 @@ function IndicationLine(props: IndicationLineProps) {
icon: <LuLink />,
onClick: assignHandler,
intent: 'success',
title: 'Assign range',
title: 'Assign signal',
},
{
icon: <LuUnlink />,
onClick: () => unAssignHandler(),
intent: 'danger',
title: 'Unassign range',
title: 'Unassign signal',
visible: isAssignmentActive || hasDiaIDs,
},
{
Expand Down
3 changes: 2 additions & 1 deletion src/component/EventsTrackers/KeysListenerTracker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,13 @@ function KeysListenerTracker(props: KeysListenerTrackerProps) {
break;
}
case 'SIGNAL_1D': {
const { id, rangeId } = extra;
const { id, rangeId, spectrumID } = extra;
dispatch({
type: 'DELETE_1D_SIGNAL',
payload: {
signalId: id,
rangeId,
spectrumId: spectrumID,
},
});
// remove keys from the highlighted list after delete
Expand Down
4 changes: 4 additions & 0 deletions src/component/panels/RangesPanel/RangesTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ export default function RangesTableRow(props: RangesTableRowProps) {

const signalIndex = tableMetaInfo.signalIndex;

if (typeof signalIndex !== 'number') {
return;
}

dispatch({
type: 'UNASSIGN_1D_SIGNAL',
payload: {
Expand Down
47 changes: 38 additions & 9 deletions src/component/reducer/actions/RangesActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,15 @@ interface DeleteSignalProps {
}
type DeleteSignalAction = ActionType<'DELETE_1D_SIGNAL', DeleteSignalProps>;

interface UnAssign1DSignalOptions {
type SignalSelector =
| { signalId: string; signalIndex?: never }
| { signalIndex: number; signalId?: never }
| { signalId?: never; signalIndex?: never };

type UnAssign1DSignalOptions = {
rangeKey?: string;
spectrumId?: string; // If not specified, the currently active spectrum will be used by default.
signalIndex?: number;
}
spectrumId?: string;
} & SignalSelector;
type UnAssign1DSignalAction = ActionType<
'UNASSIGN_1D_SIGNAL',
UnAssign1DSignalOptions
Expand Down Expand Up @@ -413,24 +417,49 @@ function handleDeleteSignal(draft: Draft<State>, action: DeleteSignalAction) {
deleteSignal1D(draft, action.payload);
}

function resolveSignalIndex(
range: Range,
{
signalId,
signalIndex = -1,
}: Pick<UnAssign1DSignalOptions, 'signalId' | 'signalIndex'>,
): number {
if (!signalId) return signalIndex;
return range.signals.findIndex((signal) => signal.id === signalId);
}

function clearRangeAssignment(
ranges: Draft<Range[]>,
rangeIndex: number,
options: Pick<UnAssign1DSignalOptions, 'signalId' | 'signalIndex'>,
) {
const index = resolveSignalIndex(ranges[rangeIndex], options);
ranges[rangeIndex] = unlink(ranges[rangeIndex], index);
}

function clearSignalAssignment(
draft: Draft<State>,
options: UnAssign1DSignalOptions = {},
) {
const { spectrumId, rangeKey, signalIndex = -1 } = options;
const { spectrumId, rangeKey, signalIndex = -1, signalId } = options;

const spectrum = getSpectrum(draft, spectrumId);
if (!isSpectrum1D(spectrum)) return;

const ranges = spectrum.ranges.values;
if (rangeKey) {
const rangeIndex = getRangeIndex(spectrum, rangeKey);
ranges[rangeIndex] = unlink(ranges[rangeIndex], signalIndex);
} else {

if (!rangeKey) {
for (const range of ranges) {
unlink(range, -1);
}
return;
}

const rangeIndex = getRangeIndex(spectrum, rangeKey);
const index = resolveSignalIndex(ranges[rangeIndex], options);
ranges[rangeIndex] = unlink(ranges[rangeIndex], index);

clearRangeAssignment(ranges, rangeIndex, { signalId, signalIndex });
}

//action
Expand Down
Loading