Skip to content

Commit

Permalink
Feature/sort datasets (#74)
Browse files Browse the repository at this point in the history
* sort datasets in the selector

* add some test and remove userData sort

* add comment

* sort versions as numbers

* use zero if sub version isn't there

* fix typo

* remove unneded check
  • Loading branch information
meganrm authored Oct 11, 2021
1 parent d51addb commit 11b1536
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 36 deletions.
2 changes: 1 addition & 1 deletion src/containers/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function mapStateToProps(state: State) {
isLoading: metadataStateBranch.selectors.getIsLoading(state),
loadingText: metadataStateBranch.selectors.getLoadingText(state),
selectedDataset: selectionStateBranch.selectors.getSelectedDataset(state),
datasets: metadataStateBranch.selectors.getDatasets(state),
datasets: metadataStateBranch.selectors.getDatasetsByNewest(state),
};
}

Expand Down
122 changes: 92 additions & 30 deletions src/state/metadata/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { map, filter, sortBy, find } from "lodash";
import { createSelector } from "reselect";

import {
MITOTIC_STAGE_KEY,
PROTEIN_NAME_KEY,
} from "../../constants";
import { MITOTIC_STAGE_KEY, PROTEIN_NAME_KEY } from "../../constants";
import { DatasetMetaData } from "../../constants/datasets";
import { State } from "../types";

import {
Expand All @@ -28,16 +26,67 @@ export const getMeasuredFeaturesDefs = (state: State) => state.metadata.measured
export const getFileInfo = (state: State) => state.metadata.cellFileInfo;
export const getClusterData = (state: State) => state.metadata.clusterData;

export const getMeasuredFeatureArrays = createSelector([getPerCellDataForPlot], (dataForPlot: DataForPlot) => {
return dataForPlot.values;
});
export const compareVersions = (versionA: string, versionB: string): number => {
const [majorA, minorA , patchA] = versionA.split(".");
const [majorB, minorB, patchB] = versionB.split(".");
// may not exist (or actually be 0), either way, set to zero for comparison
const minorANum = Number(minorA) || 0;
const minorBNum = Number(minorB) || 0;
const patchANum = Number(patchA) || 0;
const patchBNum = Number(patchB) || 0;

if (majorA === majorB) {
// if the major versions are equal, check the minor and patch numbers
if (minorANum === minorBNum) {
// if minor versions are also equal, check patch number
return patchBNum - patchANum;
} else {
return minorBNum - minorANum;
}
} else {
return Number(majorB) - Number(majorA)
}

export const getLabelsPerCell = createSelector([getPerCellDataForPlot], (dataForPlot: DataForPlot) => {
return dataForPlot.labels;
};

export const getDatasetsByNewest = createSelector([getDatasets], (datasets) => {
return datasets.sort((a: DatasetMetaData, b: DatasetMetaData) => {
// TODO: We need to sort and group datasets by "megasets"
// and then order those megasets by "newness"
// plus we have plans to have different versions of the same
// dataset contained within one card, so this is a temporary
// sort function to get the newest datasets on top
if (a.name === b.name) {
// if it's the same dataset, return the newest version first
return compareVersions(a.version, b.version);
// otherwise sort by name
} else if (a.name > b.name) {
return -1;
} else if (a.name < b.name) {
return 1;
} else {
return 0;
}
});
});

export const getSortedCellLineDefs = createSelector([getCellLineDefs], (cellLineDefs: CellLineDef[]): CellLineDef[] =>
sortBy(cellLineDefs, [PROTEIN_NAME_KEY])
export const getMeasuredFeatureArrays = createSelector(
[getPerCellDataForPlot],
(dataForPlot: DataForPlot) => {
return dataForPlot.values;
}
);

export const getLabelsPerCell = createSelector(
[getPerCellDataForPlot],
(dataForPlot: DataForPlot) => {
return dataForPlot.labels;
}
);

export const getSortedCellLineDefs = createSelector(
[getCellLineDefs],
(cellLineDefs: CellLineDef[]): CellLineDef[] => sortBy(cellLineDefs, [PROTEIN_NAME_KEY])
);

export const getProteinNames = createSelector(
Expand All @@ -47,27 +96,40 @@ export const getProteinNames = createSelector(
}
);

export const getMeasuredFeaturesKeys = createSelector([getMeasuredFeaturesDefs], (measuredFeatureDefs): string[] => {
return map(measuredFeatureDefs, "key");
});

export const getCategoricalFeatureKeys = createSelector([getMeasuredFeaturesDefs], (measuredFeatureDefs): string[] => {
return map(filter(measuredFeatureDefs, "discrete"), "key");
});
export const getMeasuredFeaturesKeys = createSelector(
[getMeasuredFeaturesDefs],
(measuredFeatureDefs): string[] => {
return map(measuredFeatureDefs, "key");
}
);

export const getProteinLabelsPerCell = createSelector([getLabelsPerCell], (labels: PerCellLabels): string[] => {
return labels[PROTEIN_NAME_KEY] || [];
});
export const getCategoricalFeatureKeys = createSelector(
[getMeasuredFeaturesDefs],
(measuredFeatureDefs): string[] => {
return map(filter(measuredFeatureDefs, "discrete"), "key");
}
);

export const getMitoticStageNames = createSelector([getMeasuredFeaturesDefs], (defs: MeasuredFeatureDef[]) => {
const mitoticFeature = find(defs, {key: MITOTIC_STAGE_KEY});
if (mitoticFeature) {
return mitoticFeature.options;
export const getProteinLabelsPerCell = createSelector(
[getLabelsPerCell],
(labels: PerCellLabels): string[] => {
return labels[PROTEIN_NAME_KEY] || [];
}
else return {};
});
);

export const getMitoticKeyPerCell = createSelector([getMeasuredFeatureArrays], (measuredFeatures: MappingOfMeasuredValuesArrays): number[] => {
return measuredFeatures[MITOTIC_STAGE_KEY] || [];
})
export const getMitoticStageNames = createSelector(
[getMeasuredFeaturesDefs],
(defs: MeasuredFeatureDef[]) => {
const mitoticFeature = find(defs, { key: MITOTIC_STAGE_KEY });
if (mitoticFeature) {
return mitoticFeature.options;
} else return {};
}
);

export const getMitoticKeyPerCell = createSelector(
[getMeasuredFeatureArrays],
(measuredFeatures: MappingOfMeasuredValuesArrays): number[] => {
return measuredFeatures[MITOTIC_STAGE_KEY] || [];
}
);
118 changes: 113 additions & 5 deletions src/state/metadata/test/selectors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ import { expect } from "chai";

import { mockState } from "../../test/mocks";
import { State } from "../../types";
import { getMeasuredFeaturesKeys, getProteinNames } from "../selectors";
import { compareVersions, getDatasetsByNewest, getMeasuredFeaturesKeys, getProteinNames } from "../selectors";

describe("Metadata branch selectors", () => {

describe("getMeasuredFeaturesKeys", () => {
it("returns the keys of measured features data", () => {
const state: State = {
...mockState,
};
const result: string[] = getMeasuredFeaturesKeys(state);
expect(result).to.deep.equal(["apical-proximity", "cell-segmentation", "cellular-surface-area", "missing-data"]);
expect(result).to.deep.equal([
"apical-proximity",
"cell-segmentation",
"cellular-surface-area",
"missing-data",
]);
});
});

describe("getProteinNames", () => {
it("returns names of the proteins in the dataset", () => {
const state: State = {
Expand All @@ -24,8 +27,113 @@ describe("Metadata branch selectors", () => {
const result: string[] = getProteinNames(state).sort((a: string, b: string) => {
return b > a ? 1 : -1;
});
expect(result).to.deep.equal(["Nucleophosmin", "Delta-actin", "Beta-catenin", "Beta-actin", "Alpha-actinin-1"]);
expect(result).to.deep.equal([
"Nucleophosmin",
"Delta-actin",
"Beta-catenin",
"Beta-actin",
"Alpha-actinin-1",
]);
});
});

describe("compareVersions", () => {
it("returns a negative if the major version of the first item is greater", () => {
const result = compareVersions("2021.1", "2020.1");
const resultNoMinor = compareVersions("2021", "2020");

expect(result).to.be.lessThan(0);
expect(resultNoMinor).to.be.lessThan(0);
})
it("returns a negative if the first item has a minor version and the second doesn't", () => {
const result = compareVersions("2021.1", "2021");

expect(result).to.be.lessThan(0);
});
it("returns negative if the minor version of the first item is greater", () => {
const result = compareVersions("2020.2", "2020.1");
const resultDoubleDigit = compareVersions("2020.10", "2020.1");

expect(result).to.be.lessThan(0);
expect(resultDoubleDigit).to.be.lessThan(0);
});
it("returns negative if the patch version of the first item is greater", () => {
const result = compareVersions("2020.1.2", "2020.1.0");
const resultDoubleDigit = compareVersions("2020.1.10", "2020.1.1");

expect(result).to.be.lessThan(0);
expect(resultDoubleDigit).to.be.lessThan(0);
});
it("returns 0 if versions are the same", () => {
const resultMajor = compareVersions("2020", "2020");
const resultMinor = compareVersions("2020.1", "2020.1");
const resultPatch = compareVersions("2020.1.1", "2020.1.1");

expect(resultMajor).to.equal(0);
expect(resultMinor).to.equal(0);
expect(resultPatch).to.equal(0);

});
})

describe("getDatasetsByNewest", () => {
it("returns the dataset card data in the order of newest to oldest", () => {
const dataset1 = {
name: "name1",
version: "2020.1",
};
const dataset2 = {
name: "name1",
version: "2021.1",
};
const state: State = {
...mockState,
metadata: {
datasets: [dataset1, dataset2],
},
};
const result: string[] = getDatasetsByNewest(state);
expect(result).to.deep.equal([dataset2, dataset1]);
});
it("returns the dataset card data in the order of newest to oldest", () => {
const dataset1 = {
name: "name1",
version: "2021.1",
};
const dataset2 = {
name: "name1",
version: "2021.2",
};
const state: State = {
...mockState,
metadata: {
datasets: [dataset1, dataset2],
},
};
const result: string[] = getDatasetsByNewest(state);
expect(result).to.deep.equal([dataset2, dataset1]);
});
it("returns the dataset card data with datasets grouped by name", () => {
const newerName1 = {
name: "name1",
version: "2021.2",
};
const dataset2 = {
name: "name2",
version: "2021.2",
};
const olderName1 = {
name: "name1",
version: "2021.1",
};
const state: State = {
...mockState,
metadata: {
datasets: [newerName1, dataset2, olderName1],
},
};
const result: string[] = getDatasetsByNewest(state);
expect(result).to.deep.equal([dataset2, newerName1, olderName1]);
});
});
});

0 comments on commit 11b1536

Please sign in to comment.