Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ad49e9b
Added express boilerplate
Jul 2, 2020
cc642b4
Added env variables for DB connection and express
Jul 2, 2020
99a6829
removed node modules
Jul 2, 2020
b63ceca
Added DB backup file
Jul 2, 2020
87314d1
Modified database connection rules for AWS environment
Jul 2, 2020
788cc34
Added Database connection check
Jul 2, 2020
a73e92e
Added testing interface
Quantaliinuxite Jul 3, 2020
65addd5
Small refactoring of testing platform + search from Cureus article.
Quantaliinuxite Jul 5, 2020
08efa0a
Added results view
Quantaliinuxite Jul 6, 2020
6e11747
Added multi-algorithm testing
Quantaliinuxite Jul 6, 2020
e731d49
Resolved merge conflicts
Quantaliinuxite Jul 6, 2020
bdb2aaa
Create README.md
Quantaliinuxite Jul 6, 2020
966dee4
Merge branch 'axel' of github.com:daphnedemekas/RareDiagnosticsAlgori…
Quantaliinuxite Jul 6, 2020
3e2e2a6
Housekeeping + Database interaction rewrtie
Quantaliinuxite Jul 6, 2020
d02b978
Rewrite of basic search route
Quantaliinuxite Jul 7, 2020
07c41de
Update README.md
Quantaliinuxite Jul 7, 2020
d6a4bd3
Update README.md
Quantaliinuxite Jul 7, 2020
ebd9f7c
Added a test in app.js
Quantaliinuxite Jul 7, 2020
4216fa0
Merge branch 'axel' of github.com:daphnedemekas/RareDiagnosticsAlgori…
Quantaliinuxite Jul 7, 2020
1490cc2
pluralized table names
Jul 7, 2020
cfdf5ba
Pluralized model names
Quantaliinuxite Jul 7, 2020
bf5936c
moved the getparent function
Jul 7, 2020
c8cd93b
changed the two algorithms and created a test file to test all 3 simu…
Jul 7, 2020
0368efc
added algorithms with sequelizer
Jul 7, 2020
3153aab
added an insert file and parser for disease synonyms and updated the …
Jul 9, 2020
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
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
build
npm-debug.log
.env
.DS_Store
package-lock.json

# Elastic Beanstalk Files
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml
67 changes: 67 additions & 0 deletions Algorithms/Bayes_Distance_combo/combination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
var db = require('../../controllers/DatabaseConnection')
var Disease = db.Disease;
var Symptom = db.Symptom;
const {Op} = require('sequelize');
var distance_function = require('euclidean-distance')

function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}

async function combination(input_symptoms) {
var results = []
let number_of_input_symptoms = parseFloat(input_symptoms.length)
let unchanged_vector = Array((input_symptoms.length)).fill(0);
var parent_symptoms = await db.getParentSymptoms(input_symptoms);
// again we push superclasses to the input
var parent_symptoms_names = parent_symptoms.map(sym => sym.symptom_name);

for (superclass of parent_symptoms_names) {input_symptoms.push(superclass)};

var diseases = await Disease.findAll({include: Symptom})

// initialize the symptom vector (currently all symptom point values are 1.5 but this would change with input symptom frequency)
var symptom_vector = Array((input_symptoms.length)).fill(1.5);

for (var disease of diseases){
var disease_vector = Array((input_symptoms.length)).fill(0);
// initialize variables
let matches = 0;
let frequency_sum = 0;
let frequency = 0;

for (var symptom of disease.Symptoms) {
frequency_sum += parseFloat(symptom.Correlation.frequency);
// If one of the input symptoms matches this symptom
if (input_symptoms.includes(symptom.symptom_name)) {
matches += 1;
frequency += parseFloat(symptom.Correlation.frequency);
let index = input_symptoms.indexOf(symptom.name);
if (symptom.frequency == 0.895) {disease_vector.splice(index,1,3);}
if (symptom.frequency == 0.545) {disease_vector.splice(index,1,2);}
if (symptom.frequency == 0.17) {disease_vector.splice(index,1,1);}
}
}

if (!arraysEqual(disease_vector,unchanged_vector)) {
var distance = (distance_function(disease_vector, symptom_vector));
var likelihood = (frequency / frequency_sum) * (matches/number_of_input_symptoms);
var score = distance * (1-likelihood);
results.push({
disease: disease,
score: score
});
}
}
return results;
}

module.exports = {
combination
}
12 changes: 12 additions & 0 deletions Algorithms/Bayes_Distance_combo/combination_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var combination = require('./combination');

let input_symptoms = ['Hypertension', 'Portal hypertension', 'Umbilical hernia', 'Ascites', 'Splenomegaly', 'Iron deficiency anemia', 'Polycythemia', 'Anemia', 'Acidosis', 'Pulmonary embolism', 'Hematemesis', 'Colitis', 'Intestinal bleeding', 'Duodenal ulcer', 'Venous thrombosis', 'Portal vein thrombosis', 'Hernia'];
combination.combination(input_symptoms).then(ranking => {
var ordered_ranking = ranking.sort(function(a,b){return a.score - b.score})
var results = []
for (var i=0; i < 10; i++){
results.push({name: ordered_ranking[i].disease.disease_name,score: ordered_ranking[i].score})
}
console.log('Combination Test Results')
console.log(results)
})
75 changes: 75 additions & 0 deletions Algorithms/BayesianAlgorithm/bayesian.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// var queries = require(__dirname+'/queries');
// var q = require('q');
// var database = require(__dirname+'/db_connection')
// var getdata_controller = require(__dirname+'/getData');

var db = require('../../controllers/DatabaseConnection')
var Disease = db.Disease;
var Symptom = db.Symptom;

// Input symptoms by name: ['Pain','Fever']
// Returns: array of score/disease tuple: [{disease: Disease, score: float}]
//TODO: Not case sensitive
async function likelihoodCalculator(input_symptoms) {
//The results array we return later
var results = []

var parent_symptoms = await db.getParentSymptoms(input_symptoms);
// number of input symptoms does not includes superclasses
let number_of_input_symptoms = parseFloat(input_symptoms.length)

var parent_symptoms = await db.getParentSymptoms(input_symptoms);
var parent_symptoms_names = parent_symptoms.map(sym => sym.symptom_name);

for (superclass of parent_symptoms_names) {input_symptoms.push(superclass)};

//We put this in a variable for later use.

//Pull every disease into memory. TODO: Make request a bit finer.
var diseases = await Disease.findAll({include: Symptom})

//We iterate through each disease and calculate their score.
for (var disease of diseases){
// Initial some computational variables
var frequency = 0.0;
var matches = 0.0;
var importance = 1.0; //We don't actually use this at the moment.
var frequency_sum = 0.0;

//Example Symptom object (for easy reference)
// {
// id: 'HP:0000003',
// symptom_name: 'Multicystic kidney dysplasia',
// definition: 'Multicystic dysplasi...',
// Correlation: { disease_orpha: '564', symptom_id: 'HP:0000003', frequency: 0.895 }
// }
for (var symptom of disease.Symptoms) {
frequency_sum += parseFloat(symptom.Correlation.frequency);

// If one of the input symptoms matches this symptom
if (input_symptoms.includes(symptom.symptom_name)) {
matches += 1;
frequency += parseFloat(symptom.Correlation.frequency);
}

//There is no match, so pull parent symptoms and see if they might match.

}

//else if: deal with subclasses

// If there was at least oen symptom match
if (matches != 0) {
let likelihood = (frequency / frequency_sum) * (matches/number_of_input_symptoms);
results.push({
disease: disease,
score: likelihood
})
}
}
return results;
}

module.exports = {
likelihoodCalculator
}
16 changes: 16 additions & 0 deletions Algorithms/BayesianAlgorithm/bayesiantest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// problem is we always get diseases with very few symtpms
// want to emphasize similar symptoms over few symptoms

var bayesian = require('./bayesian');

let input_symptoms = ['Arthritis','Fever','Anorexia','Immunodeficiency','Arthralgia','Erythema','Neutrophilia','Hepatitis','Pharyngitis']

bayesian.likelihoodCalculator(input_symptoms).then(ranking => {
var ordered_ranking = ranking.sort(function(a,b){return b.score - a.score})
var results = []
for (var i=0; i < 10; i++){
results.push({name: ordered_ranking[i].disease.disease_name,score: ordered_ranking[i].score})
}
console.log('Bayesian Test Results')
console.log(results)
})
60 changes: 60 additions & 0 deletions Algorithms/DistanceAlgorithm/distance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
var db = require('../../controllers/DatabaseConnection')
var Disease = db.Disease;
var Symptom = db.Symptom;
//const {Op} = require('sequelize');

var distance_function = require('euclidean-distance')

function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}

async function distanceCalculator(input_symptoms) {
//The results array we return later
var results = []
var parent_symptoms = await db.getParentSymptoms(input_symptoms);
var parent_symptoms_names = parent_symptoms.map(sym => sym.symptom_name)
// here we just add the parent symptoms to the input symptoms so we treat
// all superclasses as symptoms
for (superclass of parent_symptoms_names) {input_symptoms.push(superclass)};

var diseases = await Disease.findAll({include: Symptom})

// initialize the symptom vector (currently all symptom point values are 1.5 but this would change with input symptom frequency)
var symptom_vector = Array((input_symptoms.length)).fill(1.5);
let unchanged_vector = Array((input_symptoms.length)).fill(0);

for (var disease of diseases){
var disease_vector = Array((input_symptoms.length)).fill(0);
// disease symptoms
for (var symptom of disease.Symptoms) {
if (input_symptoms.includes(symptom.symptom_name)) {
index = input_symptoms.indexOf(symptom.symptom_name);
if (symptom.Correlation.frequency == 0.895) {disease_vector.splice(index,1,3);}
if (symptom.Correlation.frequency == 0.545) {disease_vector.splice(index,1,2);}
if (symptom.Correlation.frequency == 0.17) {disease_vector.splice(index,1,1); }
}
}
// example:
// s = 1.5 1.5 1.5 1.5 1.5
// d = 1 0 3 2 0
if (!arraysEqual(disease_vector,unchanged_vector)) {
var distance = (distance_function(disease_vector, symptom_vector));
results.push({
disease: disease,
score: distance
})
}
}
return results;
}

module.exports = {
distanceCalculator
}
12 changes: 12 additions & 0 deletions Algorithms/DistanceAlgorithm/distance_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var distance = require('./distance');

let input_symptoms = ['Hypertension', 'Portal hypertension', 'Umbilical hernia', 'Ascites', 'Splenomegaly', 'Iron deficiency anemia', 'Polycythemia', 'Anemia', 'Acidosis', 'Pulmonary embolism', 'Hematemesis', 'Colitis', 'Intestinal bleeding', 'Duodenal ulcer', 'Venous thrombosis', 'Portal vein thrombosis', 'Hernia'];
distance.distanceCalculator(input_symptoms).then(ranking => {
var ordered_ranking = ranking.sort(function(a,b){return a.score - b.score})
var results = []
for (var i=0; i < 10; i++){
results.push({name: ordered_ranking[i].disease.disease_name,score: ordered_ranking[i].score})
}
console.log('Distance Test Results')
console.log(results)
})
39 changes: 39 additions & 0 deletions Algorithms/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var bayesian = require('./BayesianAlgorithm/bayesian');
var distance = require('./DistanceAlgorithm/distance');
var combination = require('./Bayes_Distance_combo/combination');


let input_symptoms = ['Hypertension', 'Portal hypertension', 'Umbilical hernia', 'Ascites', 'Splenomegaly', 'Iron deficiency anemia', 'Polycythemia', 'Anemia', 'Acidosis', 'Pulmonary embolism', 'Hematemesis', 'Colitis', 'Intestinal bleeding', 'Duodenal ulcer', 'Venous thrombosis', 'Portal vein thrombosis', 'Hernia'];

var bayesian = require('./BayesianAlgorithm/bayesian');

bayesian.likelihoodCalculator(input_symptoms).then(ranking => {
var ordered_ranking = ranking.sort(function(a,b){return b.score - a.score})
var results = []
for (var i=0; i < 10; i++){
results.push({name: ordered_ranking[i].disease.disease_name,score: ordered_ranking[i].score})
}
console.log('Bayesian Test Results')
console.log(results)
})


distance.distanceCalculator(input_symptoms).then(ranking => {
var ordered_ranking = ranking.sort(function(a,b){return a.score - b.score})
var results = []
for (var i=0; i < 10; i++){
results.push({name: ordered_ranking[i].disease.disease_name,score: ordered_ranking[i].score})
}
console.log('Distance Test Results')
console.log(results)
})

combination.combination(input_symptoms).then(ranking => {
var ordered_ranking = ranking.sort(function(a,b){return a.score - b.score})
var results = []
for (var i=0; i < 10; i++){
results.push({name: ordered_ranking[i].disease.disease_name,score: ordered_ranking[i].score})
}
console.log('Combination Test Results')
console.log(results)
})
Loading