Skip to content

Commit

Permalink
Merge pull request #48 from AUS-DOH-Safety-and-Quality/tooltip-displa…
Browse files Browse the repository at this point in the history
…y-truncs

Tooltip display truncs
  • Loading branch information
andrjohns authored Jul 19, 2022
2 parents 862abf5 + 79f75db commit b005b46
Show file tree
Hide file tree
Showing 23 changed files with 163 additions and 72 deletions.
12 changes: 12 additions & 0 deletions capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@
"type": {
"text": true
}
},
"ll_truncate": {
"displayName": "Truncate Lower Limits at:",
"type": {
"numeric": true
}
},
"ul_truncate": {
"displayName": "Truncate Upper Limits at:",
"type": {
"numeric": true
}
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion pbiviz.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"displayName":"SPC Charts",
"guid":"PBISPC",
"visualClassName":"Visual",
"version":"1.1.2",
"version":"1.1.3",
"description":"A PowerBI custom visual for SPC charts",
"supportUrl":"https://github.com/AUS-DOH-Safety-and-Quality/PowerBI-SPC",
"gitHubUrl":"https://github.com/AUS-DOH-Safety-and-Quality/PowerBI-SPC"
Expand Down
2 changes: 1 addition & 1 deletion src/Classes/axisLimits.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as d3 from "d3";
import controlLimits from "../Type Definitions/controlLimits"
import controlLimits from "./controlLimits"
import settingsObject from "./settingsObject";
import dataObject from "./dataObject"
import truncate from "../Functions/truncate";
Expand Down
23 changes: 14 additions & 9 deletions src/Classes/chartObject.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as limitFunctions from "../Limit Calculations"
import dataObject from "./dataObject";
import settingsObject from "./settingsObject";
import controlLimits from "../Type Definitions/controlLimits";
import controlLimits from "./controlLimits";
import { multiply } from "../Function Broadcasting/BinaryFunctions";
import truncate from "../Functions/truncate"

type chartObjectConstructor = {
inputData: dataObject;
Expand All @@ -18,7 +19,7 @@ class chartObject {
let calcLimits: controlLimits;
let rebaselineLimits: boolean;
let split_vals: string[];

if (this.inputSettings.spc.denom_split.value !== null) {
let split_vals_raw: string[] = this.inputSettings.spc.denom_split.value.split(",")
split_vals = split_vals_raw.filter(d => this.inputData.keys.map(d2 => d2.label).includes(d));
Expand All @@ -31,7 +32,7 @@ class chartObject {
let indexes: number[] = split_vals.map(d => this.inputData.keys.map(d2 => d2.label).indexOf(d))
.concat([this.inputData.keys.length - 1])
.sort((a,b) => a - b);

let groupedData: dataObject[] = indexes.map((d, idx) => {
// Force a deep copy
let data = JSON.parse(JSON.stringify(this.inputData));
Expand All @@ -46,7 +47,7 @@ class chartObject {
}
return data;
})

let calcLimitsGrouped: controlLimits[] = groupedData.map(d => this.limitFunction(d));

calcLimits = calcLimitsGrouped.reduce((all: controlLimits, curr: controlLimits) => {
Expand All @@ -66,12 +67,16 @@ class chartObject {
// Scale limits using provided multiplier
let multiplier: number = this.inputData.multiplier;
calcLimits.values = multiply(calcLimits.values, multiplier);
calcLimits.ll99 = multiply(calcLimits.ll99, multiplier);
calcLimits.ll95 = multiply(calcLimits.ll95, multiplier);
calcLimits.ul95 = multiply(calcLimits.ul95, multiplier);
calcLimits.ul99 = multiply(calcLimits.ul99, multiplier);
calcLimits.ll99 = truncate(multiply(calcLimits.ll99, multiplier),
this.inputData.limit_truncs);
calcLimits.ll95 = truncate(multiply(calcLimits.ll95, multiplier),
this.inputData.limit_truncs);
calcLimits.ul95 = truncate(multiply(calcLimits.ul95, multiplier),
this.inputData.limit_truncs);
calcLimits.ul99 = truncate(multiply(calcLimits.ul99, multiplier),
this.inputData.limit_truncs);
calcLimits.targets = multiply(calcLimits.targets, multiplier);

console.log("inputData: ", this.inputData);
console.log("calcLimits: ", calcLimits)
return calcLimits;
Expand Down
48 changes: 48 additions & 0 deletions src/Classes/controlLimits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import plotKey from "../Type Definitions/plotKey"

type controlLimitsArgs = {
keys: plotKey[];
values: number[];
numerators?: number[];
denominators?: number[];
targets: number[];
ll99: number[];
ll95: number[];
ul95: number[];
ul99: number[];
count?: number[];
}

class controlLimits {
keys: plotKey[];
values: number[];
numerators?: number[];
denominators?: number[];
targets: number[];
ll99: number[];
ll95: number[];
ul95: number[];
ul99: number[];
count?: number[];

constructor(args: controlLimitsArgs) {
this.keys = args.keys;
this.values = args.values;
if (args.numerators || !(args.numerators === null || args.numerators === undefined)) {
this.numerators = args.numerators;
}
if (args.denominators || !(args.denominators === null || args.denominators === undefined)) {
this.denominators = args.denominators;
}
this.targets = args.targets;
this.ll99 = args.ll99;
this.ll95 = args.ll95;
this.ul95 = args.ul95;
this.ul99 = args.ul99;
if (args.count || !(args.count === null || args.count === undefined)) {
this.count = args.count;
}
}
}

export default controlLimits
5 changes: 5 additions & 0 deletions src/Classes/dataObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class dataObject {
multiplier: number;
highlights: powerbi.PrimitiveValue[];
categories: powerbi.DataViewCategoryColumn;
limit_truncs: {lower?: number, upper?: number};

constructor(args: dataObjectConstructor) {
if (args.empty) {
Expand Down Expand Up @@ -74,6 +75,10 @@ class dataObject {
this.multiplier = multiplier;
this.highlights = numerators_raw.highlights ? extractValues(numerators_raw.highlights, valid_ids) : numerators_raw.highlights;
this.categories = args.inputView.categories[0]
this.limit_truncs = {
lower: args.inputSettings.spc.ll_truncate.value,
upper: args.inputSettings.spc.ul_truncate.value
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/Classes/settingsObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@ class spcSettings {
chart_type: settingsPair<string>;
multiplier: settingsPair<number>;
denom_split: settingsPair<string>;
ll_truncate: settingsPair<number>;
ul_truncate: settingsPair<number>;

constructor() {
this.chart_type = new settingsPair("i");
this.multiplier = new settingsPair(1);
this.denom_split = new settingsPair(null);
this.ul_truncate = new settingsPair(null);
this.ll_truncate = new settingsPair(null);
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/Classes/viewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import chartObject from "./chartObject"
import settingsObject from "./settingsObject";
import dataObject from "./dataObject";
import lineData from "./lineData"
import controlLimits from "../Type Definitions/controlLimits";
import controlLimits from "./controlLimits";
import plotData from "./plotData"
import checkInvalidDataView from "../Functions/checkInvalidDataView"
import buildTooltip from "../Functions/buildTooltip"
Expand Down Expand Up @@ -44,6 +44,8 @@ class viewModelObject {
highlighted: this.inputData.highlights ? (this.inputData.highlights[index] ? true : false) : false,
tooltip: buildTooltip({date: this.calculatedLimits.keys[i].label,
value: this.calculatedLimits.values[i],
numerator: this.calculatedLimits.numerators ? this.calculatedLimits.numerators[i] : null,
denominator: this.calculatedLimits.denominators ? this.calculatedLimits.denominators[i] : null,
target: this.calculatedLimits.targets[i],
limits: {
ll99: this.calculatedLimits.ll99[i],
Expand Down Expand Up @@ -130,6 +132,7 @@ class viewModelObject {
this.calculatedLimits = this.chartBase.getLimits();
console.log(this.calculatedLimits)
this.plotPoints = this.getPlotData();
console.log("Got plot data")
this.plotPoints.forEach((point, idx) => {
point.identity = args.host
.createSelectionIdBuilder()
Expand All @@ -138,9 +141,11 @@ class viewModelObject {
.createSelectionId()
})
this.groupedLines = this.getGroupedLines();
console.log("Grouped lines for plotting")
this.axisLimits = new axisLimits({ inputData: this.inputData,
inputSettings: this.inputSettings,
calculatedLimits: this.calculatedLimits });
console.log("Made axis limits")
this.displayPlot = this.plotPoints.length > 1;
this.percentLabels = ["p", "pp"].includes(this.inputData.chart_type)
&& this.inputData.multiplier == 1
Expand Down
11 changes: 10 additions & 1 deletion src/Functions/buildTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ let valueNames = {
}

function buildTooltip(args: tooltipArgs): VisualTooltipDataItem[] {
console.log(args)
let tooltip: VisualTooltipDataItem[] = new Array<VisualTooltipDataItem>();
tooltip.push({
displayName: "Date",
Expand All @@ -41,7 +42,15 @@ function buildTooltip(args: tooltipArgs): VisualTooltipDataItem[] {
? (args.value * 100).toFixed(2) + "%"
: args.value.toFixed(4)
})
if(args.denominator) {
if(args.numerator || !(args.numerator === null || args.numerator === undefined)) {
console.log("push num")
tooltip.push({
displayName: "Numerator",
value: (args.numerator).toFixed(2)
})
}
if(args.denominator || !(args.denominator === null || args.denominator === undefined)) {
console.log("push denom")
tooltip.push({
displayName: "Denominator",
value: (args.denominator).toFixed(2)
Expand Down
6 changes: 3 additions & 3 deletions src/Limit Calculations/c.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import * as d3 from "d3";
import rep from "../Functions/rep";
import dataObject from "../Classes/dataObject"
import controlLimits from "../Type Definitions/controlLimits"
import controlLimits from "../Classes/controlLimits"

function cLimits(inputData: dataObject): controlLimits {
let cl: number = d3.mean(inputData.numerators);
let sigma: number = Math.sqrt(cl);

return {
return new controlLimits({
keys: inputData.keys,
values: inputData.numerators,
targets: rep(cl, inputData.keys.length),
ll99: rep(Math.max(cl - 3 * sigma, 0), inputData.keys.length),
ll95: rep(Math.max(cl - 2 * sigma, 0), inputData.keys.length),
ul95: rep(cl + 2*sigma, inputData.keys.length),
ul99: rep(cl + 3*sigma, inputData.keys.length),
};
});
}

export default cLimits;
6 changes: 3 additions & 3 deletions src/Limit Calculations/g.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import * as d3 from "d3";
import { sqrt } from "../Function Broadcasting/UnaryFunctions";
import rep from "../Functions/rep";
import dataObject from "../Classes/dataObject";
import controlLimits from "../Type Definitions/controlLimits";
import controlLimits from "../Classes/controlLimits";

function gLimits(inputData: dataObject): controlLimits {
let cl: number = d3.mean(inputData.numerators);
let sigma: number = sqrt(cl * (cl + 1));

return {
return new controlLimits({
keys: inputData.keys,
values: inputData.numerators,
targets: rep(cl, inputData.keys.length),
ll99: rep(0, inputData.keys.length),
ll95: rep(0, inputData.keys.length),
ul95: rep(cl + 2*sigma, inputData.keys.length),
ul99: rep(cl + 3*sigma, inputData.keys.length)
};
});
}

export default gLimits;
11 changes: 7 additions & 4 deletions src/Limit Calculations/i.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import rep from "../Functions/rep";
import { abs } from "../Function Broadcasting/UnaryFunctions"
import { divide } from "../Function Broadcasting/BinaryFunctions";
import dataObject from "../Classes/dataObject";
import controlLimits from "../Type Definitions/controlLimits";
import controlLimits from "../Classes/controlLimits";

function iLimits(inputData: dataObject): controlLimits {
let ratio: number[] = (inputData.denominators && inputData.denominators.length > 0)
let useRatio: boolean = (inputData.denominators && inputData.denominators.length > 0);
let ratio: number[] = useRatio
? divide(inputData.numerators, inputData.denominators)
: inputData.numerators;

Expand All @@ -19,15 +20,17 @@ function iLimits(inputData: dataObject): controlLimits {

let sigma: number = d3.mean(consec_diff_valid) / 1.128;

return {
return new controlLimits({
keys: inputData.keys,
values: ratio.map(d => isNaN(d) ? 0 : d),
numerators: useRatio ? inputData.numerators : undefined,
denominators: useRatio ? inputData.denominators : undefined,
targets: rep(cl, inputData.keys.length),
ll99: rep(cl - 3 * sigma, inputData.keys.length),
ll95: rep(cl - 2 * sigma, inputData.keys.length),
ul95: rep(cl + 2 * sigma, inputData.keys.length),
ul99: rep(cl + 3 * sigma, inputData.keys.length)
};
});
}

export default iLimits;
18 changes: 9 additions & 9 deletions src/Limit Calculations/mr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@ import rep from "../Functions/rep";
import { abs } from "../Function Broadcasting/UnaryFunctions"
import { divide } from "../Function Broadcasting/BinaryFunctions";
import dataObject from "../Classes/dataObject";
import controlLimits from "../Type Definitions/controlLimits";
import controlLimits from "../Classes/controlLimits";

function mrLimits(inputData: dataObject): controlLimits {
let ratio: number[];
if (inputData.denominators == null) {
ratio = inputData.numerators;
} else {
ratio = divide(inputData.numerators, inputData.denominators);
}
let useRatio: boolean = (inputData.denominators && inputData.denominators.length > 0);
let ratio: number[] = useRatio
? divide(inputData.numerators, inputData.denominators)
: inputData.numerators;

let consec_diff: number[] = abs(diff(ratio));
let cl: number = d3.mean(consec_diff);

return {
return new controlLimits({
keys: inputData.keys,
values: consec_diff,
numerators: useRatio ? inputData.numerators : null,
denominators: useRatio ? inputData.denominators : null,
targets: rep(cl, inputData.keys.length),
ll99: rep(0, inputData.keys.length),
ll95: rep(0, inputData.keys.length),
ul95: rep((3.267 / 3) * 2 * cl, inputData.keys.length),
ul99: rep(3.267 * cl, inputData.keys.length)
};
});
}

export default mrLimits;
8 changes: 5 additions & 3 deletions src/Limit Calculations/p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@ import * as d3 from "d3";
import rep from "../Functions/rep";
import { sqrt } from "../Function Broadcasting/UnaryFunctions";
import { subtract, add, divide, multiply } from "../Function Broadcasting/BinaryFunctions";
import controlLimits from "../Type Definitions/controlLimits";
import controlLimits from "../Classes/controlLimits";
import dataObject from "../Classes/dataObject";
import truncate from "../Functions/truncate"

function pLimits(inputData: dataObject): controlLimits {
let cl: number = d3.sum(inputData.numerators) / d3.sum(inputData.denominators);
let sigma: number[] = sqrt(divide(cl * (1 - cl), inputData.denominators));

return {
return new controlLimits({
keys: inputData.keys,
values: divide(inputData.numerators, inputData.denominators),
numerators: inputData.numerators,
denominators: inputData.denominators,
targets: rep(cl, inputData.keys.length),
ll99: truncate(subtract(cl, multiply(3, sigma)), {lower: 0}),
ll95: truncate(subtract(cl, multiply(2, sigma)), {lower: 0}),
ul95: truncate(add(cl, multiply(2, sigma)), {upper: 1}),
ul99: truncate(add(cl, multiply(3, sigma)), {upper: 1})
}
});
}

export default pLimits;
Loading

0 comments on commit b005b46

Please sign in to comment.