Skip to content

Commit

Permalink
fix(types): improve typings and allow typed arrays as inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
targos committed May 18, 2023
1 parent 38b8e04 commit 0e1a4c9
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 81 deletions.
12 changes: 6 additions & 6 deletions src/BasicContourDrawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ export class BasicContourDrawer {
private contour: BasicContour[];
private swapAxes: boolean;

constructor(levels: number[], swapAxes: boolean) {
this.contour = new Array(levels.length);
for (let i = 0; i < levels.length; i++) {
this.contour[i] = {
zValue: levels[i],
constructor(levels: Readonly<number[]>, swapAxes: boolean) {
this.contour = [];
for (const level of levels) {
this.contour.push({
zValue: level,
lines: [],
};
});
}
this.swapAxes = swapAxes;
}
Expand Down
9 changes: 6 additions & 3 deletions src/ContourBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,16 @@
* MODIFICATIONS.
*/
export class ContourBuilder {
level: number[];
level: number;
s: Sequence | null;
private count: number;
constructor(level: number[]) {

constructor(level: number) {
this.level = level;
this.s = null;
this.count = 0;
}

removeSeq(list: Sequence) {
// if list is the first item, static ptr s is updated
if (list.prev) {
Expand All @@ -149,6 +151,7 @@ export class ContourBuilder {
}
--this.count;
}

addSegment(a: Point, b: Point) {
let ss = this.s;
let ma: Sequence | null = null;
Expand Down Expand Up @@ -278,7 +281,7 @@ function pointsEqual(a: Point, b: Point) {
}

function reverseList(list: Sequence) {
let pp = list.head;
let pp: SequenceNode | null = list.head;
let temp;
while (pp) {
// swap prev/next pointers
Expand Down
4 changes: 2 additions & 2 deletions src/ShapeContourDrawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
import { ContourBuilder, Point, SequenceNode } from './ContourBuilder';

export interface ShapeContour {
level: number[];
level: number;
k: number;
lines: Point[];
}
Expand All @@ -78,7 +78,7 @@ export class ShapeContourDrawer {
private contours: ContourBuilder[];
private swapAxes: boolean;

constructor(levels, swapAxes) {
constructor(levels: number[], swapAxes: boolean) {
this.contours = new Array<ContourBuilder>(levels.length);
for (let i = 0; i < levels.length; i++) {
this.contours[i] = new ContourBuilder(levels[i]);
Expand Down
31 changes: 14 additions & 17 deletions src/calculateContour.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ const EPSILON = Number.EPSILON;
const MINUSEPSILON = 0 - EPSILON;

interface CalculateContourOptions {
/**
* Maximum number of ms before returning from the function, default unlimited.
*/
timeout?: number;
ilb?: number;
iub?: number;
Expand All @@ -94,32 +97,26 @@ interface CalculateContourOptions {
* increasing value.
*
* @private
* @param {NumberMatrix} matrix - matrix of data to contour
* @param matrix - matrix of data to contour
*
* The following two, one dimensional arrays (x and y) contain
* the horizontal and vertical coordinates of each sample points.
* @param {NumberArray} x - data matrix column coordinates
* @param {NumberArray} y - data matrix row coordinates
* @param {NumberArray} z - contour levels in increasing order.
* @param {object} contourDrawer object that implements contourDraw for drawing contour. Defaults to a
* @param x - data matrix column coordinates
* @param y - data matrix row coordinates
* @param z - contour levels in increasing order.
* @param contourDrawer object that implements contourDraw for drawing contour. Defaults to a
* custom "contour builder", which populates the
* contours property.
* @param {object} [options={}]
* @param {number} [options.timeout] - maximum number of ms before returning from the function, default unlimited
* @param {number} [options.ilb] - index bounds of data matrix
* @param {number} [options.iub] - index bounds of data matrix
* @param {number} [options.jlb] - index bounds of data matrix
* @param {number} [options.jub] - index bounds of data matrix
* @returns {boolean} - Whether contour generation had to stop early because it reached the timeout
* @returns Whether contour generation had to stop early because it reached the timeout
*/
export function calculateContour(
matrix: NumberMatrix,
x: NumberArray,
y: NumberArray,
z: NumberArray,
matrix: Readonly<NumberMatrix>,
x: Readonly<NumberArray>,
y: Readonly<NumberArray>,
z: Readonly<NumberArray>,
contourDrawer: ContourDrawer,
options: CalculateContourOptions = {},
) {
): boolean {
const {
timeout,
ilb = 0,
Expand Down
77 changes: 28 additions & 49 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,29 @@
import { NumberArray, NumberMatrix } from 'cheminfo-types';

import { BasicContourDrawer } from './BasicContourDrawer';
import { ShapeContourDrawer } from './ShapeContourDrawer';
import { calculateContour } from './calculateContour';

const defaultOptions = {
nbLevels: 10,
timeout: 0,
};
interface ConrecOptions {
xs?: number[];
ys?: number[];
xs?: Readonly<NumberArray>;
ys?: Readonly<NumberArray>;
swapAxes?: boolean;
}

export type ContourDrawer = BasicContourDrawer | ShapeContourDrawer;
/**
*
* @class Conrec
* @param {number[][]} matrix
* @param {number[]} [options.xs]
* @param {number[]} [options.ys]
* @param {boolean} [options.swapAxes]
*/

export class Conrec {
matrix: number[][];
matrix: Readonly<NumberMatrix>;
rows: number;
columns: number;
xs: number[];
ys: number[];
xs: Readonly<NumberArray>;
ys: Readonly<NumberArray>;
swapAxes: boolean;
hasMinMax: boolean;
min: number;
max: number;

constructor(matrix: number[][], options: ConrecOptions = {}) {
constructor(matrix: Readonly<NumberMatrix>, options: ConrecOptions = {}) {
const { swapAxes = false } = options;
this.matrix = matrix;
this.rows = matrix.length;
Expand All @@ -55,46 +47,31 @@ export class Conrec {
this.max = 0;
}

/**
* @typedef {Object} Output
* @property {any} contours
* @property {boolean} timeout - Whether contour generation had to stop early because it reached the timeout
*/

/**
*
* @param {number[]} [options.levels]
* @param {number} [options.nbLevels=10]
* @param {string} [options.contourDrawer='basic'] - 'basic' or 'shape'
* @param {number} [options.timeout=0]
* @return {Output}
*/
drawContour(options: {
levels?: number[];
levels?: readonly number[];
nbLevels?: number;
contourDrawer?: string;
contourDrawer?: 'basic' | 'shape';
timeout?: number;
}) {
const { nbLevels, timeout } = { ...defaultOptions, ...options };
const { nbLevels = 10, timeout = 0, contourDrawer = 'basic' } = options;

let levels: number[];
if (options.levels) {
levels = options.levels.slice();
levels = [...options.levels];
} else {
this._computeMinMax();
const interval = (this.max - this.min) / (nbLevels - 1);
levels = range(this.min, this.max + interval, interval);
}
levels.sort((a, b) => a - b);
let contourDrawer: ContourDrawer | null = null;
const contourDrawerType = options.contourDrawer || 'basic';
if (typeof contourDrawerType === 'string') {
if (contourDrawerType === 'basic') {
contourDrawer = new BasicContourDrawer(levels, this.swapAxes);
} else if (contourDrawerType === 'shape') {
contourDrawer = new ShapeContourDrawer(levels, this.swapAxes);
let contourDrawerInstance: ContourDrawer;
if (typeof contourDrawer === 'string') {
if (contourDrawer === 'basic') {
contourDrawerInstance = new BasicContourDrawer(levels, this.swapAxes);
} else if (contourDrawer === 'shape') {
contourDrawerInstance = new ShapeContourDrawer(levels, this.swapAxes);
} else {
throw new Error(`unknown contour drawer: ${contourDrawerType}`);
throw new Error(`invalid contour drawer: ${String(contourDrawer)}`);
}
} else {
throw new TypeError('contourDrawer must be a string');
Expand All @@ -104,13 +81,13 @@ export class Conrec {
this.xs,
this.ys,
levels,
contourDrawer,
contourDrawerInstance,
{
timeout,
},
);

return { contours: contourDrawer.getContour(), timeout: isTimeout };
return { contours: contourDrawerInstance.getContour(), timeout: isTimeout };
}

_computeMinMax() {
Expand All @@ -123,13 +100,15 @@ export class Conrec {
}
}

function range(from: number, to: number, step: number) {
function range(from: number, to: number, step: number): number[] {
const result: number[] = [];
for (let i = from; i < to; i += step) result.push(i);
for (let i = from; i < to; i += step) {
result.push(i);
}
return result;
}

function minMax(matrix: number[][]) {
function minMax(matrix: Readonly<NumberMatrix>) {
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
for (const row of matrix) {
Expand Down
5 changes: 1 addition & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"moduleResolution": "node",
"noImplicitAny": false,
"moduleResolution": "node16",
"outDir": "lib",
"sourceMap": true,
"strict": true,
Expand Down

0 comments on commit 0e1a4c9

Please sign in to comment.