Skip to content

Commit

Permalink
Adjust fractional part of VAF cart ticks
Browse files Browse the repository at this point in the history
to be able to distinquish tick labels
  • Loading branch information
Ruslan Forostianov authored and pvannierop committed Oct 26, 2020
1 parent 3600072 commit 036ff5d
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 4 deletions.
31 changes: 31 additions & 0 deletions src/pages/patientView/timeline2/VAFChartUtils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
IPoint,
numLeadingDecimalZeros,
round10,
minimalDistinctTickStrings,
yValueScaleFunction,
} from './VAFChartUtils';
import { GROUP_BY_NONE } from '../timeline2/VAFChartControls';
Expand Down Expand Up @@ -940,6 +941,36 @@ describe('VAFChartUtils', () => {
});
});

describe('minimalDistinctTickStrings', () => {
it('works with empty array', () => {
assert.deepEqual(minimalDistinctTickStrings([]), []);
});
it('converts to string', () => {
assert.deepEqual(minimalDistinctTickStrings([1]), ['1']);
});
it('deduplicate numbers', () => {
assert.deepEqual(minimalDistinctTickStrings([1, 1]), ['1']);
});
it('shows equals digits in fractional part', () => {
assert.deepEqual(minimalDistinctTickStrings([1, 1.1]), [
'1.0',
'1.1',
]);
});
it('shows just enough numbers in fractional part to distinguish number', () => {
assert.deepEqual(
minimalDistinctTickStrings([0.01, 0.002, 0.0003]),
['0.010', '0.002', '0.000']
);
});
it('falls back on the scientific notation of original numbers if 3 decimal digits are not enough to distinguish', () => {
assert.deepEqual(minimalDistinctTickStrings([0.0001, 0.000201]), [
'1e-4',
'2.01e-4',
]);
});
});

describe('yValueScaleFunction', () => {
it('handles linear scale, zero minY tickmark', () => {
const yPadding = 10;
Expand Down
28 changes: 28 additions & 0 deletions src/pages/patientView/timeline2/VAFChartUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,31 @@ export function numLeadingDecimalZeros(y: number) {
if (y == 0 || y >= 0.1) return 0;
return numberOfLeadingDecimalZeros(y);
}

/**
* Try to return tick labels with fractional part just long enogh to disttinguish them.
* It tries up to 3th positions in fractional part. Otherwise return scientific representation of original numbers.
* Function returns distinct labels.
* If input contains duplicates function deduplicates and return less labels that amount of input numbers.
* @param nums array of ticks as numbers
*/
export function minimalDistinctTickStrings(nums: number[]): string[] {
const distinctNums = nums.filter((v, i, a) => a.indexOf(v) === i);

const fractionalNumbersToShow = distinctNums.map(num =>
Number.isInteger(num) ? 0 : numLeadingDecimalZeros(num) + 1
);

const fromPos = Math.min(...fractionalNumbersToShow);
const toPos = 3;

for (let pos = fromPos; pos <= toPos; pos++) {
const labels = distinctNums
.map(num => num.toFixed(pos))
.filter((v, i, a) => a.indexOf(v) === i);
if (labels.length === distinctNums.length) {
return labels;
}
}
return distinctNums.map(num => num.toExponential());
}
13 changes: 9 additions & 4 deletions src/pages/patientView/timeline2/VAFChartWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
IPoint,
numLeadingDecimalZeros,
yValueScaleFunction,
minimalDistinctTickStrings,
} from './VAFChartUtils';
import { VAFChartHeader } from './VAFChartHeader';
import {
Expand Down Expand Up @@ -123,14 +124,18 @@ export default class VAFChartWrapper extends React.Component<
}

@computed get ticks(): { label: string; value: number; offset: number }[] {
const tickmarkValues = getYAxisTickmarks(
let tickmarkValues = getYAxisTickmarks(
this.minYTickmarkValue,
this.maxYTickmarkValue
);
const numDecimals = numLeadingDecimalZeros(this.minYTickmarkValue) + 1;
return _.map(tickmarkValues, (v: number) => {
const labels = minimalDistinctTickStrings(tickmarkValues);
const ticksHasDuplicates = tickmarkValues.length !== labels.length;
if (ticksHasDuplicates) {
tickmarkValues = labels.map(label => Number(label));
}
return _.map(tickmarkValues, (v: number, indx: number) => {
return {
label: v.toFixed(numDecimals),
label: labels[indx],
value: v,
offset: this.scaleYValue(v),
};
Expand Down

0 comments on commit 036ff5d

Please sign in to comment.