Skip to content
Snippets Groups Projects
Commit 87e93eeb authored by Steve Reis's avatar Steve Reis
Browse files

wip: Logistic integration

parent 80ca0376
No related branches found
No related tags found
No related merge requests found
...@@ -319,21 +319,27 @@ export default class DataShieldConnector implements Connector { ...@@ -319,21 +319,27 @@ export default class DataShieldConnector implements Connector {
const coVariable = const coVariable =
experiment.variables.length > 0 ? experiment.variables[0] : undefined; experiment.variables.length > 0 ? experiment.variables[0] : undefined;
const expToInput = {
coVariable,
variables: experiment.coVariables,
algorithm: {
id: experiment.algorithm.name,
},
datasets: experiment.datasets,
};
experiment.algorithm.parameters.forEach((param) => {
if (!expToInput.algorithm[param.name]) {
// FIXME: the parameter should be added in a specific key entry (e.g. expToInput.algorithm.parameters')
// Should be fixed inside the Datashield API
expToInput.algorithm[param.name] = param.value;
}
});
const result = await firstValueFrom( const result = await firstValueFrom(
this.httpService.post( this.httpService.post(path.href, expToInput, {
path.href, headers: { cookie, 'Content-Type': 'application/json' },
{ }),
coVariable,
variables: experiment.coVariables,
algorithm: {
id: experiment.algorithm.name,
},
datasets: experiment.datasets,
},
{
headers: { cookie, 'Content-Type': 'application/json' },
},
),
); );
handlers(experiment, result.data, vars); handlers(experiment, result.data, vars);
......
...@@ -23,6 +23,8 @@ const properties = [ ...@@ -23,6 +23,8 @@ const properties = [
'high0.95CI', 'high0.95CI',
]; ];
const summaryProps = ['iter', 'Nvalid', 'Ntotal', 'df'];
export default class LinearRegressionHandler extends BaseHandler { export default class LinearRegressionHandler extends BaseHandler {
canHandle(algorithm: string, data: any): boolean { canHandle(algorithm: string, data: any): boolean {
return ( return (
...@@ -30,6 +32,19 @@ export default class LinearRegressionHandler extends BaseHandler { ...@@ -30,6 +32,19 @@ export default class LinearRegressionHandler extends BaseHandler {
); );
} }
getSummaryTable(data: any): TableResult {
const summaryTable: TableResult = {
name: 'Summary',
headers: [
{ name: 'Name', type: 'string' },
{ name: 'Value', type: 'string' },
],
data: summaryProps.map((prop) => [lookupDict[prop], data[prop]]),
};
return summaryTable;
}
private getTableResult(data: any, vars: Variable[]): TableResult { private getTableResult(data: any, vars: Variable[]): TableResult {
return { return {
name: 'Results', name: 'Results',
...@@ -50,9 +65,11 @@ export default class LinearRegressionHandler extends BaseHandler { ...@@ -50,9 +65,11 @@ export default class LinearRegressionHandler extends BaseHandler {
return this.next?.handle(experiment, data, vars); return this.next?.handle(experiment, data, vars);
const tableResult = this.getTableResult(data, vars); const tableResult = this.getTableResult(data, vars);
const summaryResult = this.getSummaryTable(data);
if (summaryResult) experiment.results.push(summaryResult);
if (tableResult) experiment.results.push(tableResult);
if (tableResult) { this.next?.handle(experiment, data, vars);
experiment.results.push(tableResult);
}
} }
} }
import { Experiment } from '../../../../models/experiment/experiment.model';
import LogisticRegressionHandler from './logistic-regression.handler';
const data = {
Nvalid: 214,
Nmissing: 0,
Ntotal: 214,
'disclosure.risk': [[0], [0]],
errorMessage: [['No errors'], ['No errors']],
nsubs: 214,
iter: 6,
formula:
'race ~ Urea.nitrogen..Mass.volume..in.Serum.or.Plasma + Albumin..Mass.volume..in.Serum.or.Plasma',
coefficients: [
{
Estimate: -4.53,
'Std. Error': 3.4497,
'z-value': -1.3132,
'p-value': 0.1891,
'low0.95CI.LP': -11.2914,
'high0.95CI.LP': 2.2313,
P_OR: 0.0107,
'low0.95CI.P_OR': 0,
'high0.95CI.P_OR': 0.903,
_row: '(Intercept)',
},
{
Estimate: 0.0598,
'Std. Error': 0.0663,
'z-value': 0.9023,
'p-value': 0.3669,
'low0.95CI.LP': -0.0701,
'high0.95CI.LP': 0.1898,
P_OR: 1.0617,
'low0.95CI.P_OR': 0.9323,
'high0.95CI.P_OR': 1.209,
_row: 'Urea.nitrogen..Mass.volume..in.Serum.or.Plasma',
},
{
Estimate: 0.4569,
'Std. Error': 0.7518,
'z-value': 0.6078,
'p-value': 0.5433,
'low0.95CI.LP': -1.0166,
'high0.95CI.LP': 1.9304,
P_OR: 1.5792,
'low0.95CI.P_OR': 0.3618,
'high0.95CI.P_OR': 6.8926,
_row: 'Albumin..Mass.volume..in.Serum.or.Plasma',
},
],
dev: 172.4603,
df: 211,
'output.information':
'SEE TOP OF OUTPUT FOR INFORMATION ON MISSING DATA AND ERROR MESSAGES',
};
const createExperiment = (): Experiment => ({
id: 'dummy-id',
name: 'Testing purpose',
algorithm: {
name: 'logistic-regression',
parameters: [
{
name: 'pos-level',
value: 'White',
},
],
},
datasets: ['sophia.db'],
domain: 'dementia',
variables: ['race'],
coVariables: [
'Urea.nitrogen..Mass.volume..in.Serum.or.Plasma',
'Albumin..Mass.volume..in.Serum.or.Plasma',
],
results: [],
});
describe('Logistic Regression Handler', () => {
describe('Normal usage', () => {
it('should return the correct results', () => {
const experiment = createExperiment();
const handler = new LogisticRegressionHandler();
handler.handle(experiment, data, []);
expect(experiment.results).toHaveLength(1);
});
});
});
import { Experiment } from '../../../../models/experiment/experiment.model';
import { TableResult } from '../../../../models/result/table-result.model';
import { Variable } from '../../../../models/variable.model';
import BaseHandler from '../base.handler';
const lookupDict = {
Estimate: 'Estimate',
'Std. Error': 'Std. Error',
'z-value': 'Z value',
'p-value': 'P value',
'low0.95CI.LP': 'Low 95% CI',
'high0.95CI': 'High 95% CI',
P_OR: 'P OR',
'low0.95CI.P_OR': 'Low 95% CI P_OR',
'high0.95CI.P_OR': 'High 95% CI P OR',
_row: '',
iter: 'Iteration(s)',
Nvalid: 'Valid observations',
Ntotal: 'Total observations',
df: 'Degrees of freedom',
};
const properties = [
'_row',
'Estimate',
'Std. Error',
'z-value',
'p-value',
'low0.95CI.LP',
'high0.95CI.LP',
'P_OR',
'low0.95CI.P_OR',
'high0.95CI.P_OR',
];
const summaryProps = ['iter', 'Nvalid', 'Ntotal', 'df'];
export default class LogisticRegressionHandler extends BaseHandler {
canHandle(algorithm: string, data: any): boolean {
return (
algorithm.toLowerCase() === 'logistic-regression' && data['coefficients']
);
}
getSummaryTable(data: any): TableResult {
return {
name: 'Summary',
headers: [
{ name: 'Name', type: 'string' },
{ name: 'Value', type: 'string' },
],
data: summaryProps.map((prop) => [lookupDict[prop], data[prop]]),
};
}
getTableResult(data: unknown, vars: Variable[]): TableResult {
return {
name: 'Results',
headers: properties.map((name) => ({
name: lookupDict[name],
type: 'string',
})),
data: data['coefficients'].map((row: any) => {
const variable = vars.find((v) => v.id === row['_row']);
if (variable) row['_row'] = variable.label ?? variable.id;
return properties.map((name) => row[name]);
}),
};
}
handle(experiment: Experiment, data: unknown, vars: Variable[]): void {
if (!this.canHandle(experiment.algorithm.name, data))
return this.next?.handle(experiment, data, vars);
const tableResult = this.getTableResult(data, vars);
const summaryTable = this.getSummaryTable(data);
if (tableResult) experiment.results.push(tableResult);
if (summaryTable) experiment.results.push(summaryTable);
this.next?.handle(experiment, data, vars);
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment