Skip to content

Commit

Permalink
Merge pull request #228 from AUS-DOH-Safety-and-Quality/add-facets-arg
Browse files Browse the repository at this point in the history
Add data argument for grouping control limits
  • Loading branch information
andrjohns authored Jan 25, 2024
2 parents e52f631 + 40df6fa commit 8c99fd5
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 6 deletions.
2 changes: 2 additions & 0 deletions capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
{ "displayName": "Outcome/Numerator", "name": "numerators", "kind": "Measure" },
{ "displayName": "Denominator", "name": "denominators", "kind": "Measure" },
{ "displayName": "ID Key (Date)", "name": "key", "kind": "Grouping" },
{ "displayName": "Facets", "name": "facets", "kind": "Measure" },
{ "displayName": "SD (for xbar)", "name": "xbar_sds", "kind": "Measure" },
{ "displayName": "Tooltips", "name": "tooltips", "kind": "Measure" }
],
Expand Down Expand Up @@ -615,6 +616,7 @@
"select": [
{ "bind": { "to": "numerators" } },
{ "bind": { "to": "denominators" } },
{ "bind": { "to": "facets" } },
{ "bind": { "to": "xbar_sds" } },
{ "bind": { "to": "tooltips" } }
]
Expand Down
7 changes: 5 additions & 2 deletions src/Classes/viewModelClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export default class viewModelClass {
const split_indexes: string = <string>(options.dataViews[0]?.metadata?.objects?.split_indexes_storage?.split_indexes) ?? "[]";
this.splitIndexes = JSON.parse(split_indexes);
this.inputData = extractInputData(options.dataViews[0].categorical, this.inputSettings.settings);

this.calculateLimits();
this.scaleAndTruncateLimits();
this.flagOutliers();
Expand All @@ -112,9 +113,11 @@ export default class viewModelClass {
const limitFunction: (args: controlLimitsArgs) => controlLimitsObject
= limitFunctions[this.inputSettings.settings.spc.chart_type];

if (this.splitIndexes.length > 0) {
if (this.splitIndexes.length > 0 || this.inputData.facetIndexes.length > 0) {
const indexes: number[] = this.splitIndexes
.concat(this.inputData.facetIndexes)
.concat([this.inputData.limitInputArgs.keys.length - 1])
.filter((d, idx, arr) => arr.indexOf(d) === idx)
.sort((a,b) => a - b);
const groupedData: dataObject[] = indexes.map((d, idx) => {
// Force a deep copy
Expand Down Expand Up @@ -210,7 +213,7 @@ export default class viewModelClass {
labels.forEach(label => {
// By adding an additional null line value at each re-baseline point
// we avoid rendering a line joining each segment
if (this.splitIndexes.includes(i - 1)) {
if (this.splitIndexes.includes(i - 1) || this.inputData.facetIndexes.includes(i - 1)) {
formattedLines.push({
x: this.controlLimits.keys[i].x,
line_value: null,
Expand Down
5 changes: 4 additions & 1 deletion src/Functions/extractDataColumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ export default function extractDataColumn<T extends TargetT>(inputView: DataView
return extractTooltips(inputView, inputSettings) as Extract<T, VisualTooltipDataItem[][]>;
}

// Assumed that any other requested columns are numeric columns for plotting
const columnRaw = inputView.values.filter(viewColumn => viewColumn?.source?.roles?.[name]) as DataViewValueColumn[];
if (name === "facets") {
return columnRaw?.[0]?.values?.map(d => d === null ? null : String(d)) as T
}
// Assumed that any other requested columns are numeric columns for plotting
return columnRaw?.[0]?.values?.map(d => d === null ? null : Number(d)) as T
}
19 changes: 17 additions & 2 deletions src/Functions/extractInputData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export type dataObject = {
highlights: PrimitiveValue[];
anyHighlights: boolean;
categories: DataViewCategoryColumn;
facets: string[];
facetIndexes: number[];
scatter_formatting: defaultSettingsType["scatter"][];
tooltips: VisualTooltipDataItem[][];
warningMessage: string;
Expand All @@ -23,9 +25,10 @@ export default function extractInputData(inputView: DataViewCategorical, inputSe
const keys: string[] = extractDataColumn<string[]>(inputView, "key", inputSettings);
const scatter_cond = extractConditionalFormatting(inputView, "scatter", inputSettings) as defaultSettingsType["scatter"][];
const tooltips = extractDataColumn<VisualTooltipDataItem[][]>(inputView, "tooltips", inputSettings);
const facets: string[] = extractDataColumn<string[]>(inputView, "facets", inputSettings);
const highlights: powerbi.PrimitiveValue[] = inputView.values[0].highlights;

const inputValidStatus: string[] = validateInputData(keys, numerators, denominators, xbar_sds, inputSettings.spc.chart_type);
const inputValidStatus: string[] = validateInputData(keys, numerators, denominators, xbar_sds, facets, inputSettings.spc.chart_type);

const valid_ids: number[] = new Array<number>();
const valid_keys: { x: number, id: number, label: string }[] = new Array<{ x: number, id: number, label: string }>();
Expand All @@ -41,7 +44,17 @@ export default function extractInputData(inputView: DataViewCategorical, inputSe
removalMessages.push(`${groupVarName} ${keys[i]} removed due to: ${inputValidStatus[i]}.`)
}
}


const valid_facets: string[] = extractValues(facets, valid_ids);
const facetIndexes: number[] = new Array<number>();
let current_facet: string = valid_facets[0];
valid_facets.forEach((d, idx) => {
if (d !== current_facet) {
facetIndexes.push(idx - 1);
current_facet = d;
}
})

return {
limitInputArgs: {
keys: valid_keys,
Expand All @@ -54,6 +67,8 @@ export default function extractInputData(inputView: DataViewCategorical, inputSe
highlights: extractValues(highlights, valid_ids),
anyHighlights: highlights != null,
categories: inputView.categories[0],
facets: valid_facets,
facetIndexes: facetIndexes,
scatter_formatting: extractValues(scatter_cond, valid_ids),
warningMessage: removalMessages.length >0 ? removalMessages.join("\n") : ""
}
Expand Down
10 changes: 9 additions & 1 deletion src/Functions/validateInputData.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import rep from "./rep";
import { validationErrorClass } from "../Classes";

export default function validateInputData(keys: string[], numerators: number[], denominators: number[], xbar_sds: number[], data_type: string): string[] {
export default function validateInputData(keys: string[],
numerators: number[],
denominators: number[],
xbar_sds: number[],
facets: string[],
data_type: string): string[] {
const denominatorConstraintRequired: string[] = ["p", "pp", "u", "up"];
const denominatorRequired: string[] = ["p", "pp", "u", "up", "xbar", "s"];
const denominatorOptional: string[] = ["i", "run", "mr"];
Expand All @@ -12,6 +17,9 @@ export default function validateInputData(keys: string[], numerators: number[],
}
const numeratorNonNegativeRequired: string[] = ["p", "pp", "u", "up", "s", "c", "g", "t"];
const status: string[] = rep("", keys.length);
if (!(facets === null || facets === undefined)) {
facets.forEach((d, idx) => status[idx] = status[idx] === "" ? ((d != null) ? "" : "Facet missing") : status[idx]);
}
keys.forEach((d, idx) => status[idx] = status[idx] === "" ? ((d != null) ? "" : "Date missing") : status[idx]);
if (!status.some(d => d == "")) {
throw(new validationErrorClass("All dates/IDs are missing or null!"))
Expand Down

0 comments on commit 8c99fd5

Please sign in to comment.