Skip to content

Commit

Permalink
feat: pass source with descendants
Browse files Browse the repository at this point in the history
  • Loading branch information
tokebe committed Aug 21, 2024
1 parent 271c64e commit d44f248
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 26 deletions.
32 changes: 16 additions & 16 deletions __test__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,69 +5,69 @@ const { getDescendants } = require('../src/index');
test('chebi', () => {
let curies = ['CHEBI:26218'];
let descendants = getDescendants(curies);
expect(descendants['CHEBI:26218']).toContain('CHEBI:50394');
expect(descendants['CHEBI:26218']).toContain('CHEBI:51700');
expect(descendants['CHEBI:26218']).toHaveProperty('CHEBI:50394');
expect(descendants['CHEBI:26218']).toHaveProperty('CHEBI:51700');
});

//DOID:0060524 -> DOID:0040001 -> DOID:0060527
//crustacean allergy -> shrimp allergy -> indian prawn allergy
test('doid', () => {
let curies = ['DOID:0060524'];
let descendants = getDescendants(curies);
expect(descendants['DOID:0060524']).toContain('DOID:0040001');
expect(descendants['DOID:0060524']).toContain('DOID:0060527');
expect(descendants['DOID:0060524']).toHaveProperty('DOID:0040001');
expect(descendants['DOID:0060524']).toHaveProperty('DOID:0060527');
});

//GO:0032553 -> GO:0032555 -> GO:0032559
//ribonucleotide binding -> purine ribonucleotide binding -> adenyl ribonucleotide binding
test('go', () => {
let curies = ['GO:0032553'];
let descendants = getDescendants(curies);
expect(descendants['GO:0032553']).toContain('GO:0032555');
expect(descendants['GO:0032553']).toContain('GO:0032559');
expect(descendants['GO:0032553']).toHaveProperty('GO:0032555');
expect(descendants['GO:0032553']).toHaveProperty('GO:0032559');
});

//HP:0003812 -> HP:0003828
//Phenotypic variability -> Variable expressivity
test('hp', () => {
let curies = ['HP:0003812'];
let descendants = getDescendants(curies);
expect(descendants['HP:0003812']).toContain('HP:0003828');
expect(descendants['HP:0003812']).toHaveProperty('HP:0003828');
});

//MONDO:0001517 -> MONDO:0001955 -> MONDO:0024275
//dysentery -> protozoal dysentery -> amebic dysentery
test('mondo', () => {
let curies = ['MONDO:0001517'];
let descendants = getDescendants(curies);
expect(descendants['MONDO:0001517']).toContain('MONDO:0001955');
expect(descendants['MONDO:0001517']).toContain('MONDO:0024275');
expect(descendants['MONDO:0001517']).toHaveProperty('MONDO:0001955');
expect(descendants['MONDO:0001517']).toHaveProperty('MONDO:0024275');
});

//UMLS:C0680344 -> UMLS:C0003114 -> UMLS:C0680369
//sociocultural values, norms, and social control -> anomie -> anomie(normless)
test('umls', () => {
let curies = ['UMLS:C0680344'];
let descendants = getDescendants(curies);
expect(descendants['UMLS:C0680344']).toContain('UMLS:C0003114');
expect(descendants['UMLS:C0680344']).toContain('UMLS:C0680369');
expect(descendants['UMLS:C0680344']).toHaveProperty('UMLS:C0003114');
expect(descendants['UMLS:C0680344']).toHaveProperty('UMLS:C0680369');
});

test('multiple', () => {
let curies = ['HP:0003812', 'MONDO:0001517'];
let descendants = getDescendants(curies);
expect(descendants['HP:0003812']).toContain('HP:0003828');
expect(descendants['MONDO:0001517']).toContain('MONDO:0001955');
expect(descendants['MONDO:0001517']).toContain('MONDO:0024275');
expect(descendants['HP:0003812']).toHaveProperty('HP:0003828');
expect(descendants['MONDO:0001517']).toHaveProperty('MONDO:0001955');
expect(descendants['MONDO:0001517']).toHaveProperty('MONDO:0024275');
});

test('no descendants', () => {
let curies = ['DOID:0060527'];
let descendants = getDescendants(curies);
expect(descendants['DOID:0060527'].length).toBe(0);
expect(Object.keys(descendants['DOID:0060527']).length).toBe(0);
});

test('recursive', () => {
let curies = ['UMLS:C0012634'];
let descendants = getDescendants(curies);
});
});
38 changes: 28 additions & 10 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const loadData = () => {
for (let ontology in ONTOLOGIES) {
const filename = `../data/${ontology}-parsed.json`;
const ontologyData = require(filename);
data = { ...data, ...ontologyData };
Object.entries(ontologyData).forEach(([parent, descendants]) => {
data[parent] = { source: ontology.toUpperCase(), descendants };
});
}
// const end = performance.now();
// console.log(`loadData took ${end - start} milliseconds.`);
Expand All @@ -28,27 +30,43 @@ exports.getDescendants = (curies, recursive = true) => {
const children = {};

for (let curie of curies) {
children[curie] = [];
children[curie] = {};
level = [curie];
while (level.length > 0 && children[curie].length < ENTITY_CAP) {
while (
level.length > 0 &&
Object.keys(children[curie]).length < ENTITY_CAP
) {
next_level = [];
for (let c of level) {
if (data[c]) {
children[curie].push(...data[c]);
next_level.push(...data[c]);
data[c].descendants.forEach(
child => (children[curie][child] = data[c].source),
);
next_level.push(
...data[c].descendants.filter(child => child !== curie),
);
}
}
level = next_level;
}
children[curie] = _.uniq(children[curie])
.filter(child => child !== curie)
.slice(0, ENTITY_CAP);

delete children[curie][curie]; // Ensure no self-children
children[curie] = Object.fromEntries(
Object.entries(children[curie]).slice(0, ENTITY_CAP),
);
}
return children;
} else {
return Object.fromEntries(
Object.entries(_.pick(data, curies)).map(([curie, descendants]) => {
return [curie, descendants.filter(descendant => descendant !== curie)];
Object.entries(_.pick(data, curies)).map(([curie, descendantInfo]) => {
return [
curie,
Object.fromEntries(
descendantInfo.descendants
.filter(descendant => descendant !== curie)
.map(descendant => [descendant, source]),
),
];
}),
);
}
Expand Down

0 comments on commit d44f248

Please sign in to comment.