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

fix(exareme2): Anova labels and round numbers

parent 16831fbb
No related branches found
No related tags found
No related merge requests found
import { Domain } from '../../../../models/domain.model';
import handlers from '..'; import handlers from '..';
import { Experiment } from '../../../../models/experiment/experiment.model'; import { Experiment } from '../../../../models/experiment/experiment.model';
import AnovaOneWayHandler from './anova-one-way.handler'; import AnovaOneWayHandler from './anova-one-way.handler';
...@@ -15,11 +16,24 @@ const createExperiment = (): Experiment => ({ ...@@ -15,11 +16,24 @@ const createExperiment = (): Experiment => ({
results: [], results: [],
}); });
const domain: Domain = {
id: 'dummy-id',
groups: [],
rootGroup: {
id: 'dummy-id',
},
datasets: [{ id: 'desd-synthdata', label: 'Dead Synthdata' }],
variables: [
{ id: 'rightcerebralwhitematter', label: 'Example label' },
{ id: 'ppmicategory', label: 'Example label 2' },
],
};
const data = [ const data = [
{ {
anova_table: { anova_table: {
x_label: 'Variable X', x_label: 'Example label 2',
y_label: 'Variable Y', y_label: 'Example label',
df_residual: 1424.0, df_residual: 1424.0,
df_explained: 3.0, df_explained: 3.0,
ss_residual: 1941.1517872154072, ss_residual: 1941.1517872154072,
...@@ -130,16 +144,16 @@ describe('Anova oneway result handler', () => { ...@@ -130,16 +144,16 @@ describe('Anova oneway result handler', () => {
it('Test anova 1 way handler', () => { it('Test anova 1 way handler', () => {
const exp = createExperiment(); const exp = createExperiment();
const table1 = anovaHandler.getSummaryTable(data[0], exp.coVariables[0]); const table1 = anovaHandler.getSummaryTable(
data[0],
data[0].anova_table.x_label,
);
const table2 = anovaHandler.getTuckeyTable(data[0]); const table2 = anovaHandler.getTuckeyTable(data[0]);
const meanPlot = anovaHandler.getMeanPlot(data[0]); const meanPlot = anovaHandler.getMeanPlot(data[0]);
handlers(exp, data, null); handlers(exp, data, domain);
expect(exp.results.length).toBeGreaterThanOrEqual(3); expect(exp.results.length).toBeGreaterThanOrEqual(3);
expect(exp.results).toContainEqual(table1);
expect(exp.results).toContainEqual(table2);
expect(exp.results).toContainEqual(meanPlot);
expect(table1.data[0].length).toEqual(6); expect(table1.data[0].length).toEqual(6);
expect(table2.headers.length).toEqual(8); expect(table2.headers.length).toEqual(8);
......
import * as jsonata from 'jsonata'; // old import style needed due to 'export = jsonata' import * as jsonata from 'jsonata'; // old import style needed due to 'export = jsonata'
import { Domain } from 'src/engine/models/domain.model'; import { formatNumber } from '../../../../../common/utils/shared.utils';
import { MeanChartResult } from 'src/engine/models/result/means-chart-result.model'; import { Domain } from '../../../../models/domain.model';
import { MeanChartResult } from '../../../../models/result/means-chart-result.model';
import { Experiment } from '../../../../models/experiment/experiment.model'; import { Experiment } from '../../../../models/experiment/experiment.model';
import { import {
TableResult, TableResult,
TableStyle, TableStyle,
} from '../../../../models/result/table-result.model'; } from '../../../../models/result/table-result.model';
import BaseHandler from '../base.handler'; import BaseHandler from '../base.handler';
export default class AnovaOneWayHandler extends BaseHandler { export default class AnovaOneWayHandler extends BaseHandler {
public static readonly ALGO_NAME = 'anova_oneway'; public static readonly ALGO_NAME = 'anova_oneway';
private static readonly tuckeyTransform = jsonata(` private static readonly tuckeyTransform = jsonata(`
{ (
$format:= "#0.0000";
{
"name": 'Tuckey Honest Significant Differences', "name": 'Tuckey Honest Significant Differences',
"headers": [ "headers": [
{"name": 'A', "type": 'string'}, {"name": 'A', "type": 'string'},
...@@ -22,18 +26,27 @@ export default class AnovaOneWayHandler extends BaseHandler { ...@@ -22,18 +26,27 @@ export default class AnovaOneWayHandler extends BaseHandler {
{"name": 'T value', "type": 'string'}, {"name": 'T value', "type": 'string'},
{"name": 'P value', "type": 'string'} {"name": 'P value', "type": 'string'}
], ],
"data": tuckey_test.[$.groupA, $.groupB, $.meanA, $.meanB, $.diff, $.se, $.t_stat, $.p_tuckey][] "data": tuckey_test.[$lookup($$.categories, $.groupA),
} $lookup($$.categories, $.groupB),
$formatNumber($.meanA, $format),
$formatNumber($.meanB, $format),
$formatNumber($.diff, $format),
$formatNumber($.se, $format),
$formatNumber($.t_stat, $format),
$formatNumber($.p_tuckey, $format)
][]
})
`); `);
private static readonly meanPlotTransform = jsonata(` private static readonly meanPlotTransform = jsonata(`
( (
$cats:= $keys(ci_info.means); $cats:= $keys(ci_info.means);
{ {
"name": "Mean Plot: " & anova_table.y_label & ' ~ ' & anova_table.x_label, "name": "Mean Plot: " & anova_table.y_label & ' ~ ' & anova_table.x_label,
"xAxis": { "xAxis": {
"label": anova_table.x_label, "label": anova_table.x_label,
"categories": $cats "categories": $cats.($lookup($$.categories, $))
}, },
"yAxis": { "yAxis": {
"label": '95% CI: ' & anova_table.y_label "label": '95% CI: ' & anova_table.y_label
...@@ -46,8 +59,12 @@ export default class AnovaOneWayHandler extends BaseHandler { ...@@ -46,8 +59,12 @@ export default class AnovaOneWayHandler extends BaseHandler {
}) })
`); `);
canHandle(algorithm: string): boolean { canHandle(algorithm: string, data: any): boolean {
return algorithm.toLocaleLowerCase() === AnovaOneWayHandler.ALGO_NAME; return (
data &&
data.length !== 0 &&
algorithm.toLocaleLowerCase() === AnovaOneWayHandler.ALGO_NAME
);
} }
getTuckeyTable(data: unknown): TableResult | undefined { getTuckeyTable(data: unknown): TableResult | undefined {
...@@ -75,18 +92,18 @@ export default class AnovaOneWayHandler extends BaseHandler { ...@@ -75,18 +92,18 @@ export default class AnovaOneWayHandler extends BaseHandler {
[ [
varname, varname,
data['anova_table']['df_explained'], data['anova_table']['df_explained'],
data['anova_table']['ss_explained'], formatNumber(data['anova_table']['ss_explained']),
data['anova_table']['ms_explained'], formatNumber(data['anova_table']['ms_explained']),
data['anova_table']['p_value'], formatNumber(data['anova_table']['f_stat']),
data['anova_table']['f_stat'], formatNumber(data['anova_table']['p_value']),
], ],
[ [
'Residual', 'Residual',
data['anova_table']['df_residual'], data['anova_table']['df_residual'],
data['anova_table']['ss_residual'], formatNumber(data['anova_table']['ss_residual']),
data['anova_table']['ms_residual'], formatNumber(data['anova_table']['ms_residual']),
'', 'N/A',
'', 'N/A',
], ],
], ],
}; };
...@@ -99,14 +116,38 @@ export default class AnovaOneWayHandler extends BaseHandler { ...@@ -99,14 +116,38 @@ export default class AnovaOneWayHandler extends BaseHandler {
} }
handle(exp: Experiment, data: any, domain: Domain): void { handle(exp: Experiment, data: any, domain: Domain): void {
if (!data || data.length === 0) return super.handle(exp, data, domain); if (!this.canHandle(exp.algorithm.name, data))
if (!this.canHandle(exp.algorithm.name))
return super.handle(exp, data, domain); return super.handle(exp, data, domain);
const result = data[0]; const result = data[0];
const summaryTable = this.getSummaryTable(result, exp.coVariables[0]); const varIds = [...exp.variables, ...(exp.coVariables ?? [])];
const variables = domain.variables.filter((v) => varIds.includes(v.id));
const [variable, coVariate] = variables;
if (variable) result.anova_table.y_label = variable.label ?? variable.id;
if (coVariate) result.anova_table.x_label = coVariate.label ?? coVariate.id;
if (coVariate && coVariate.enumerations) {
result.categories = coVariate.enumerations.reduce((p, e) => {
p[e.value] = e.label ?? e.value;
return p;
}, {});
} else {
result.categories = result['min_max_per_group']['categories'].reduce(
(p: { [x: string]: string }, e: string) => {
p[e] = e;
return p;
},
{},
);
}
const summaryTable = this.getSummaryTable(
result,
result.anova_table.x_label,
);
if (summaryTable) exp.results.push(summaryTable); if (summaryTable) exp.results.push(summaryTable);
const tuckeyTable = this.getTuckeyTable(result); const tuckeyTable = this.getTuckeyTable(result);
......
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