diff --git a/src/__test__/components/data-processing/data-integration/DataIntegration.test.jsx b/src/__test__/components/data-processing/data-integration/DataIntegration.test.jsx index adecc739bd..3e5f583af2 100644 --- a/src/__test__/components/data-processing/data-integration/DataIntegration.test.jsx +++ b/src/__test__/components/data-processing/data-integration/DataIntegration.test.jsx @@ -1,7 +1,9 @@ import React from 'react'; import { Provider } from 'react-redux'; import '__test__/test-utils/setupTests'; -import { screen, render, waitFor } from '@testing-library/react'; +import { + screen, render, waitFor, within, +} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import _ from 'lodash'; import fake from '__test__/test-utils/constants'; @@ -204,4 +206,31 @@ describe('DataIntegration', () => { // The legend alert plot text should appear expect(screen.getByText(/We have hidden the plot legend, because it is too large and it interferes with the display of the plot/)).toBeInTheDocument(); }); + + it('Renders the elbow plot by default when the experiment is single sample', async () => { + // Remove all sample other than the first one. + // This way, getIsUnisample() will detect the exp as unisample + const unisampleCellSetsData = _.cloneDeep(cellSetsData); + _.find(unisampleCellSetsData.cellSets, { key: 'sample' }).children.splice(1); + + const mockSingleSampleApiResponses = { + ...generateDefaultMockAPIResponses(fake.EXPERIMENT_ID), + [`experiments/${fake.EXPERIMENT_ID}/cellSets$`]: () => promiseResponse( + JSON.stringify(unisampleCellSetsData), + ), + }; + + fetchMock + .mockReset() + .mockIf(/.*/, mockAPI(mockSingleSampleApiResponses)); + + storeState = makeStore(); + await storeState.dispatch(loadBackendStatus(fake.EXPERIMENT_ID)); + await storeState.dispatch(loadProcessingSettings(fake.EXPERIMENT_ID)); + await storeState.dispatch(loadCellSets(fake.EXPERIMENT_ID)); + + await renderDataIntegration(storeState); + + expect(screen.getByRole('radio', { name: 'Elbow plot showing principal components' })).toBeChecked(); + }); }); diff --git a/src/components/data-processing/ConfigureEmbedding/ConfigureEmbedding.jsx b/src/components/data-processing/ConfigureEmbedding/ConfigureEmbedding.jsx index fca390c0e9..d627a36fac 100644 --- a/src/components/data-processing/ConfigureEmbedding/ConfigureEmbedding.jsx +++ b/src/components/data-processing/ConfigureEmbedding/ConfigureEmbedding.jsx @@ -7,7 +7,7 @@ import { } from 'antd'; import SelectData from 'components/plots/styling/embedding-continuous/SelectData'; -import { isUnisample } from 'utils/experimentPredicates'; +import { getIsUnisample } from 'utils/experimentPredicates'; import CategoricalEmbeddingPlot from 'components/plots/CategoricalEmbeddingPlot'; import ContinuousEmbeddingPlot from 'components/plots/ContinuousEmbeddingPlot'; @@ -135,11 +135,11 @@ const ConfigureEmbedding = (props) => { const { loading, data: plotData, error } = cellMeta[colouring]; const modifiedConfig = { ...config, - axes:{ + axes: { ...config.axes, yAxisText: config.axes.yAxisText || plotColouring, - } - } + }, + }; return ( { ); } - if (plotColouring === 'sample' && cellSets.accessible && isUnisample(cellSets.hierarchy) + if (plotColouring === 'sample' && cellSets.accessible && getIsUnisample(cellSets.hierarchy) ) { return (
diff --git a/src/components/data-processing/DataIntegration/DataIntegration.jsx b/src/components/data-processing/DataIntegration/DataIntegration.jsx index c59ef95320..4412dc9fde 100644 --- a/src/components/data-processing/DataIntegration/DataIntegration.jsx +++ b/src/components/data-processing/DataIntegration/DataIntegration.jsx @@ -1,5 +1,5 @@ import React, { - useState, useEffect, useRef, useCallback, + useState, useEffect, useRef, useCallback, useMemo, } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { @@ -24,7 +24,7 @@ import ElbowPlot from 'components/plots/ElbowPlot'; import { generateDataProcessingPlotUuid } from 'utils/generateCustomPlotUuid'; import EmptyPlot from 'components/plots/helpers/EmptyPlot'; import PlotStyling from 'components/plots/styling/PlotStyling'; -import { isUnisample } from 'utils/experimentPredicates'; +import { getIsUnisample } from 'utils/experimentPredicates'; import PlotLegendAlert, { MAX_LEGEND_ITEMS } from 'components/plots/helpers/PlotLegendAlert'; import CalculationConfig from './CalculationConfig'; @@ -33,9 +33,14 @@ const DataIntegration = (props) => { const { experimentId, onConfigChange, stepDisabled, stepHadErrors, disableDataIntegration, } = props; - const [selectedPlot, setSelectedPlot] = useState('embedding'); - const [plot, setPlot] = useState(null); + const cellSets = useSelector(getCellSets()); + + const isUnisample = useMemo(() => getIsUnisample(cellSets.hierarchy)); + + const [selectedPlot, setSelectedPlot] = useState(isUnisample ? 'elbow' : 'embedding'); + const [plot, setPlot] = useState(null); + const filterName = 'dataIntegration'; const configureEmbeddingFilterName = 'configureEmbedding'; @@ -275,7 +280,7 @@ const DataIntegration = (props) => { ); } - if ((selectedPlot === 'embedding' || selectedPlot === 'frequency') && cellSets.accessible && isUnisample(cellSets.hierarchy) + if ((selectedPlot === 'embedding' || selectedPlot === 'frequency') && cellSets.accessible && isUnisample ) { return (
diff --git a/src/utils/experimentPredicates.js b/src/utils/experimentPredicates.js index b08527ca2b..dd283ba682 100644 --- a/src/utils/experimentPredicates.js +++ b/src/utils/experimentPredicates.js @@ -1,4 +1,4 @@ -const isUnisample = (hierarchy) => hierarchy.find((rootNode) => rootNode.key === 'sample')?.children?.length === 1; +const getIsUnisample = (hierarchy) => hierarchy.find((rootNode) => rootNode.key === 'sample')?.children?.length === 1; // eslint-disable-next-line import/prefer-default-export -export { isUnisample }; +export { getIsUnisample };