1 | import { DOMAIN } from '../constants.js'
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | export function normalizeIndexSubsetConstraints (domain, constraints) {
|
9 |
|
10 | let normalizedConstraints = {}
|
11 | for (let axisName in constraints) {
|
12 | if (!domain.axes.has(axisName)) {
|
13 |
|
14 | continue
|
15 | }
|
16 | if (constraints[axisName] === undefined || constraints[axisName] === null) {
|
17 | continue
|
18 | }
|
19 | if (typeof constraints[axisName] === 'number') {
|
20 | let constraint = constraints[axisName]
|
21 | normalizedConstraints[axisName] = {start: constraint, stop: constraint + 1}
|
22 | } else {
|
23 | normalizedConstraints[axisName] = constraints[axisName]
|
24 | }
|
25 |
|
26 | let { start = 0, stop = domain.axes.get(axisName).values.length, step = 1 } = normalizedConstraints[axisName]
|
27 | if (step <= 0) {
|
28 | throw new Error(`Invalid constraint for ${axisName}: step=${step} must be > 0`)
|
29 | }
|
30 | if (start >= stop || start < 0) {
|
31 | throw new Error(`Invalid constraint for ${axisName}: stop=${stop} must be > start=${start} and both >= 0`)
|
32 | }
|
33 | normalizedConstraints[axisName] = {start, stop, step}
|
34 | }
|
35 | for (let axisName of domain.axes.keys()) {
|
36 | if (!(axisName in normalizedConstraints)) {
|
37 | let len = domain.axes.get(axisName).values.length
|
38 | normalizedConstraints[axisName] = {start: 0, stop: len, step: 1}
|
39 | }
|
40 | }
|
41 | return normalizedConstraints
|
42 | }
|
43 |
|
44 | export function subsetDomainByIndex (domain, constraints) {
|
45 | constraints = normalizeIndexSubsetConstraints(domain, constraints)
|
46 |
|
47 |
|
48 | let newdomain = {
|
49 | type: DOMAIN,
|
50 | domainType: domain.domainType,
|
51 | axes: new Map(domain.axes),
|
52 | referencing: domain.referencing
|
53 | }
|
54 |
|
55 | for (let axisName of Object.keys(constraints)) {
|
56 | let axis = domain.axes.get(axisName)
|
57 | let coords = axis.values
|
58 | let bounds = axis.bounds
|
59 | let constraint = constraints[axisName]
|
60 | let newcoords
|
61 | let newbounds
|
62 |
|
63 | let {start, stop, step} = constraint
|
64 | if (start === 0 && stop === coords.length && step === 1) {
|
65 | newcoords = coords
|
66 | newbounds = bounds
|
67 | } else if (step === 1) {
|
68 |
|
69 | if (coords.subarray) {
|
70 | newcoords = coords.subarray(start, stop)
|
71 | } else {
|
72 | newcoords = coords.slice(start, stop)
|
73 | }
|
74 | if (bounds) {
|
75 | newbounds = {
|
76 | get: i => bounds.get(start + i)
|
77 | }
|
78 | }
|
79 | } else {
|
80 | let q = Math.trunc((stop - start) / step)
|
81 | let r = (stop - start) % step
|
82 | let len = q + r
|
83 | newcoords = new coords.constructor(len)
|
84 | for (let i = start, j = 0; i < stop; i += step, j++) {
|
85 | newcoords[j] = coords[i]
|
86 | }
|
87 | if (bounds) {
|
88 | newbounds = {
|
89 | get: i => bounds.get(start + i * step)
|
90 | }
|
91 | }
|
92 | }
|
93 |
|
94 | let newaxis = {
|
95 | dataType: axis.dataType,
|
96 | coordinates: axis.coordinates,
|
97 | values: newcoords,
|
98 | bounds: newbounds
|
99 | }
|
100 | newdomain.axes.set(axisName, newaxis)
|
101 | }
|
102 |
|
103 | return newdomain
|
104 | }
|