Skip to content

Commit

Permalink
[MNT] Implemented getColumnsForCategory and getUniqueColumnValues (
Browse files Browse the repository at this point in the history
…#569)

* Implemented `getColumnsForCategory` and `getUniqueColumnValues`

Refactored `getUniqueValues` and moved some of its logic to the
newly implemented getters

* Refactored `getUniqueValues` unit test
  • Loading branch information
rmanaem authored Oct 12, 2023
1 parent 0968278 commit b7050b4
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 50 deletions.
2 changes: 1 addition & 1 deletion components/tool-navbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
data-cy="github"
href="https://github.com/neurobagel/annotation_tool/"
target="_blank">
<b-icon icon="github" font-scale="1"/>
<b-icon icon="github" font-scale="1" />
</b-nav-item>

</b-navbar-nav>
Expand Down
65 changes: 38 additions & 27 deletions cypress/unit/store-getter-getUniqueValues.cy.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,57 @@
import { getters } from "~/store";

let store;
let state;

describe("getUniqueValues getter", () => {

beforeEach(() => {
state = {

store = {
columnToCategoryMap: {
column1: "Diagnosis",
column2: "Age",
column3: "Sex"
},

state: {
dataDictionary: {

columnToCategoryMap: {
annotated: {

column1: "Diagnosis",
column2: "Age",
column3: "Sex"
},
column1: { missingValues: [] },
column2: { missingValues: [] },
column3: { missingValues: ["column3_value1", "column3_value2"] }
}
},

dataDictionary: {
dataTable: [

annotated: {
{ column1: 1, column2: "column2_value1", column3: "column3_value1" },
{ column1: 2, column2: "column2_value2", column3: "column3_value2" },
{ column1: 1, column2: "column2_value3", column3: "column3_value3" },
{ column1: 3, column2: "column2_value2", column3: "column3_value4" }
]
};

column1: { missingValues: [] },
column2: { missingValues: [] },
column3: { missingValues: ["column3_value1", "column3_value2"] }
}
},
store = {
getters: {
// getColumnsForCategory: () => (p_category) => {
// return ["column1", "column2", "column3"];
// },
getColumnsForCategory: getters.getColumnsForCategory(state),

dataTable: [
getUniqueColumnValues: getters.getUniqueColumnValues(state)
},

{ column1: 1, column2: "column2_value1", column3: "column3_value1" },
{ column1: 2, column2: "column2_value2", column3: "column3_value2" },
{ column1: 1, column2: "column2_value3", column3: "column3_value3" },
{ column1: 3, column2: "column2_value2", column3: "column3_value4" }
]
}
};
});
state: state
};
}
);

it("Retrieves unique values of a single column", () => {

// Act
const diagnosisUniqueValues = getters.getUniqueValues(store.state)("Diagnosis");
const diagnosisUniqueValues = getters.getUniqueValues(store.state, store.getters)("Diagnosis");

// Assert
expect(diagnosisUniqueValues).to.deep.equal({ "column1": [1, 2, 3] });
Expand All @@ -50,10 +60,11 @@ describe("getUniqueValues getter", () => {
it("Retrieves unique values of a multiple columns", () => {

// Setup
// We change the state by reference because the state passed to the getters needs to reflect that change
store.state.columnToCategoryMap.column2 = "Diagnosis";

// Act
const diagnosisUniqueValues = getters.getUniqueValues(store.state)("Diagnosis");
const diagnosisUniqueValues = getters.getUniqueValues(store.state, store.getters)("Diagnosis");

// Assert
expect(diagnosisUniqueValues).to.deep.equal({
Expand All @@ -66,7 +77,7 @@ describe("getUniqueValues getter", () => {
it("Retrieve unique value list of maximum length", () => {

// Act
const diagnosisUniqueValues = getters.getUniqueValues(store.state)("Diagnosis", 2);
const diagnosisUniqueValues = getters.getUniqueValues(store.state, store.getters)("Diagnosis", 2);

// Assert
expect(diagnosisUniqueValues).to.deep.equal({ "column1": [1, 2]});
Expand All @@ -75,7 +86,7 @@ describe("getUniqueValues getter", () => {
it("Make sure no missing values are included in unique values", () => {

// Act
const diagnosisUniqueValues = getters.getUniqueValues(store.state)("Sex");
const diagnosisUniqueValues = getters.getUniqueValues(store.state, store.getters)("Sex");

// Assert
expect(diagnosisUniqueValues).to.deep.equal({ "column3": ["column3_value3", "column3_value4"]});
Expand Down
61 changes: 39 additions & 22 deletions store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ export const state = () => ({
},
"Diagnosis": {

componentName: "annot-categorical",
explanation: "This is an explanation for how to annotate diagnosis.",
identifier: "nb:Diagnosis"
},
"Assessment Tool": {

componentName: "annot-categorical",
explanation: "This is an explanation for how to annotate diagnosis.",
identifier: "nb:Diagnosis"
Expand Down Expand Up @@ -541,41 +547,52 @@ export const getters = {
return Object.keys(p_state.transformationHeuristics);
},

getUniqueValues: (p_state) => (p_category, p_maxValues="None") => {

// 1. Construct an object containing a list of unique values for each column
const uniqueValues = {};
getColumnsForCategory: (p_state) => (p_category) => {
const columns = [];
for ( const columnName in p_state.columnToCategoryMap ) {

// A. Create a new list for values for each column linked to the given category
if ( p_category === p_state.columnToCategoryMap[columnName] ) {

// I. Save unique values for each column
uniqueValues[columnName] = new Set();
for ( let index = 0; index < p_state.dataTable.length; index++ ) {
columns.push(columnName);
}
}

// a. Check to see if this value is marked as 'missing' for this column
let value = p_state.dataTable[index][columnName];
if ( !p_state.dataDictionary?.annotated[columnName].missingValues.includes(value) ) {
return columns;
},

uniqueValues[columnName].add(value);
}
getUniqueColumnValues: (p_state) => (columnName, p_maxValues="None") => {
let uniqueColumnValues = new Set();
for ( let index = 0; index < p_state.dataTable.length; index++ ) {

// a. Check to see if this value is marked as 'missing' for this column
let value = p_state.dataTable[index][columnName];
if ( !p_state.dataDictionary?.annotated[columnName].missingValues.includes(value) ) {

uniqueColumnValues.add(value);
}
}

// II. Convert the unique values list for this column from a set to an array
uniqueValues[columnName] = [...uniqueValues[columnName]];
// II. Convert the unique values list for this column from a set to an array
uniqueColumnValues = [...uniqueColumnValues];

// III. Trim the value list if a maximum value amount was given
// NOTE: Trimming is done here instead of only looking at p_maxValues rows
// just in case there are blank entries for columns in the data table
if ( "None" !== p_maxValues ) {
// III. Trim the value list if a maximum value amount was given
// NOTE: Trimming is done here instead of only looking at p_maxValues rows
// just in case there are blank entries for columns in the data table
if ( "None" !== p_maxValues ) {

uniqueValues[columnName] = uniqueValues[columnName].slice(0, p_maxValues);
}
uniqueColumnValues = uniqueColumnValues.slice(0, p_maxValues);
}
}

// Return an object containing a list of unique values for each column
return uniqueColumnValues;
},

getUniqueValues: (p_state, p_getters) => (p_category, p_maxValues="None") => {
const columns = p_getters.getColumnsForCategory(p_category);
const uniqueValues = {};
for (const column of columns) {
uniqueValues[column] = p_getters.getUniqueColumnValues(column, p_maxValues);
}
return uniqueValues;
},

Expand Down

0 comments on commit b7050b4

Please sign in to comment.