image-js 0.35.2 → 0.35.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/index.d.ts +3 -10
  2. package/lib/browser/environment.js +0 -6
  3. package/lib/browser/worker/extend.js +0 -3
  4. package/lib/browser/worker/process/background.js +0 -12
  5. package/lib/browser/worker/worker.js +0 -17
  6. package/lib/image/Image.js +18 -51
  7. package/lib/image/compute/colorHistogram.js +0 -8
  8. package/lib/image/compute/countAlphaPixels.js +0 -3
  9. package/lib/image/compute/extendedPoints.js +2 -7
  10. package/lib/image/compute/histogram.js +6 -25
  11. package/lib/image/compute/localMaxima.js +2 -10
  12. package/lib/image/compute/max.js +0 -5
  13. package/lib/image/compute/mean.js +0 -4
  14. package/lib/image/compute/median.js +0 -4
  15. package/lib/image/compute/min.js +0 -5
  16. package/lib/image/compute/minimalBoundingRectangle.js +5 -18
  17. package/lib/image/compute/moment.js +0 -3
  18. package/lib/image/compute/monotoneChainConvexHull.js +0 -3
  19. package/lib/image/compute/points.js +0 -3
  20. package/lib/image/compute/relativePosition.js +2 -8
  21. package/lib/image/compute/sum.js +0 -5
  22. package/lib/image/core/bitMethods.js +0 -11
  23. package/lib/image/core/checkProcessable.js +0 -13
  24. package/lib/image/core/environment.js +0 -8
  25. package/lib/image/core/export.js +0 -38
  26. package/lib/image/core/extend.js +0 -13
  27. package/lib/image/core/getRGBAData.js +0 -15
  28. package/lib/image/core/kind.js +4 -28
  29. package/lib/image/core/kindNames.js +1 -0
  30. package/lib/image/core/load.js +1 -53
  31. package/lib/image/core/mediaTypes.js +0 -2
  32. package/lib/image/core/valueMethods.js +0 -13
  33. package/lib/image/extend.js +7 -83
  34. package/lib/image/filter/abs.js +0 -3
  35. package/lib/image/filter/add.js +2 -8
  36. package/lib/image/filter/background.js +0 -9
  37. package/lib/image/filter/blurFilter.js +0 -6
  38. package/lib/image/filter/divide.js +0 -8
  39. package/lib/image/filter/flipX.js +0 -5
  40. package/lib/image/filter/flipY.js +0 -4
  41. package/lib/image/filter/gaussianFilter.js +0 -5
  42. package/lib/image/filter/gradientFilter.js +0 -11
  43. package/lib/image/filter/hypotenuse.js +0 -13
  44. package/lib/image/filter/invert.js +0 -9
  45. package/lib/image/filter/level.js +1 -19
  46. package/lib/image/filter/medianFilter.js +0 -15
  47. package/lib/image/filter/multiply.js +0 -10
  48. package/lib/image/filter/scharrFilter.js +0 -4
  49. package/lib/image/filter/sobelFilter.js +0 -4
  50. package/lib/image/filter/subtract.js +0 -8
  51. package/lib/image/filter/subtractImage.js +0 -10
  52. package/lib/image/internal/checks.js +1 -9
  53. package/lib/image/internal/clamp.js +0 -1
  54. package/lib/image/internal/copy.js +0 -2
  55. package/lib/image/internal/copyAlphaChannel.js +0 -1
  56. package/lib/image/internal/getImageParameters.js +0 -1
  57. package/lib/image/internal/getOutputImage.js +1 -13
  58. package/lib/image/model/model.js +1 -1
  59. package/lib/image/morphology/blackHat.js +0 -5
  60. package/lib/image/morphology/close.js +0 -5
  61. package/lib/image/morphology/dilate.js +0 -40
  62. package/lib/image/morphology/erode.js +0 -40
  63. package/lib/image/morphology/morphologicalGradient.js +0 -5
  64. package/lib/image/morphology/open.js +0 -5
  65. package/lib/image/morphology/topHat.js +0 -5
  66. package/lib/image/operator/cannyEdge.js +0 -3
  67. package/lib/image/operator/convolution.js +9 -34
  68. package/lib/image/operator/convolutionSeparable.js +0 -10
  69. package/lib/image/operator/extract.js +4 -13
  70. package/lib/image/operator/floodFill.js +2 -15
  71. package/lib/image/operator/getSeparatedKernel.js +0 -2
  72. package/lib/image/operator/paintLabels.js +2 -13
  73. package/lib/image/operator/paintMasks.js +2 -12
  74. package/lib/image/operator/paintPoints.js +0 -9
  75. package/lib/image/operator/paintPolygon.js +0 -14
  76. package/lib/image/operator/paintPolygons.js +0 -4
  77. package/lib/image/operator/paintPolyline.js +0 -7
  78. package/lib/image/operator/paintPolylines.js +0 -4
  79. package/lib/image/roi/Roi.js +27 -208
  80. package/lib/image/roi/RoiLayer.js +1 -22
  81. package/lib/image/roi/RoiMap.js +5 -38
  82. package/lib/image/roi/creator/fromMask.js +4 -22
  83. package/lib/image/roi/creator/fromMaskConnectedComponentLabelingAlgorithm.js +2 -20
  84. package/lib/image/roi/creator/fromMaxima.js +10 -43
  85. package/lib/image/roi/creator/fromPoints.js +2 -10
  86. package/lib/image/roi/creator/fromWaterShed.js +6 -17
  87. package/lib/image/roi/feretDiameters.js +9 -21
  88. package/lib/image/roi/manager.js +30 -119
  89. package/lib/image/roi/util/commonBorderLength.js +5 -16
  90. package/lib/image/roi/util/mergeRoi.js +2 -21
  91. package/lib/image/transform/cmyk.js +0 -9
  92. package/lib/image/transform/colorDepth.js +0 -12
  93. package/lib/image/transform/crop.js +0 -20
  94. package/lib/image/transform/cropAlpha.js +0 -11
  95. package/lib/image/transform/grey.js +0 -17
  96. package/lib/image/transform/greyAlgorithms.js +1 -24
  97. package/lib/image/transform/hsl.js +0 -16
  98. package/lib/image/transform/hsv.js +0 -15
  99. package/lib/image/transform/insert.js +0 -6
  100. package/lib/image/transform/mask/huang.js +3 -18
  101. package/lib/image/transform/mask/intermodes.js +3 -14
  102. package/lib/image/transform/mask/isodata.js +0 -14
  103. package/lib/image/transform/mask/li.js +12 -42
  104. package/lib/image/transform/mask/mask.js +1 -13
  105. package/lib/image/transform/mask/maxEntropy.js +8 -25
  106. package/lib/image/transform/mask/mean.js +1 -3
  107. package/lib/image/transform/mask/minError.js +10 -21
  108. package/lib/image/transform/mask/minimum.js +0 -20
  109. package/lib/image/transform/mask/moments.js +4 -17
  110. package/lib/image/transform/mask/otsu.js +1 -7
  111. package/lib/image/transform/mask/percentile.js +0 -8
  112. package/lib/image/transform/mask/renyiEntropy.js +8 -34
  113. package/lib/image/transform/mask/shanbhag.js +8 -25
  114. package/lib/image/transform/mask/thresholdAlgorithms.js +1 -17
  115. package/lib/image/transform/mask/triangle.js +13 -29
  116. package/lib/image/transform/mask/yen.js +2 -14
  117. package/lib/image/transform/pad.js +0 -20
  118. package/lib/image/transform/resize/nearestNeighbor.js +0 -6
  119. package/lib/image/transform/resize/resize.js +0 -16
  120. package/lib/image/transform/rgba.js +0 -9
  121. package/lib/image/transform/rgba8.js +0 -3
  122. package/lib/image/transform/rotate.js +0 -29
  123. package/lib/image/transform/rotateFree.js +0 -31
  124. package/lib/image/transform/warping.js +2 -35
  125. package/lib/image/utility/combineChannels.js +0 -11
  126. package/lib/image/utility/getBestMatch.js +2 -13
  127. package/lib/image/utility/getChannel.js +0 -10
  128. package/lib/image/utility/getClosestCommonParent.js +6 -23
  129. package/lib/image/utility/getColumn.js +0 -4
  130. package/lib/image/utility/getIntersection.js +2 -18
  131. package/lib/image/utility/getMatrix.js +0 -7
  132. package/lib/image/utility/getPixelsArray.js +0 -5
  133. package/lib/image/utility/getPixelsGrid.js +0 -11
  134. package/lib/image/utility/getRow.js +0 -4
  135. package/lib/image/utility/getSimilarity.js +3 -17
  136. package/lib/image/utility/getThreshold.js +0 -4
  137. package/lib/image/utility/setBorder.js +0 -16
  138. package/lib/image/utility/setChannel.js +0 -6
  139. package/lib/image/utility/setMatrix.js +3 -6
  140. package/lib/image/utility/split.js +2 -15
  141. package/lib/index.js +0 -12
  142. package/lib/kernel/kernel.js +0 -3
  143. package/lib/kernel/laplacianOfGaussian.js +1 -7
  144. package/lib/node_modules/test/binary.js +0 -3
  145. package/lib/node_modules/test/oneRoi.js +0 -2
  146. package/lib/stack/Stack.js +2 -35
  147. package/lib/stack/compute/histogram.js +0 -4
  148. package/lib/stack/compute/histograms.js +0 -4
  149. package/lib/stack/compute/max.js +0 -3
  150. package/lib/stack/compute/median.js +0 -4
  151. package/lib/stack/compute/min.js +0 -3
  152. package/lib/stack/extend.js +1 -11
  153. package/lib/stack/transform/matchAndCrop.js +6 -19
  154. package/lib/stack/utility/averageImage.js +0 -9
  155. package/lib/stack/utility/maxImage.js +0 -7
  156. package/lib/stack/utility/minImage.js +0 -7
  157. package/lib/util/Shape.js +3 -40
  158. package/lib/util/base64.js +3 -14
  159. package/lib/util/channel.js +1 -35
  160. package/lib/util/color.js +1 -25
  161. package/lib/util/converter.js +1 -13
  162. package/lib/util/deepValue.js +0 -3
  163. package/lib/util/histogram.js +1 -12
  164. package/lib/util/kernel.js +2 -12
  165. package/lib/util/matrix.js +0 -13
  166. package/lib/util/points.js +12 -35
  167. package/lib/util/value.js +0 -7
  168. package/lib/util/zerosMatrix.js +0 -3
  169. package/package.json +1 -1
  170. package/src/image/utility/setMatrix.js +4 -0
@@ -4,29 +4,17 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _jsQuantities = _interopRequireDefault(require("js-quantities"));
9
-
10
8
  var _deepValue = _interopRequireDefault(require("../../util/deepValue"));
11
-
12
9
  var _Image = _interopRequireDefault(require("../Image"));
13
-
14
10
  var _RoiLayer = _interopRequireDefault(require("./RoiLayer"));
15
-
16
11
  var _RoiMap = _interopRequireDefault(require("./RoiMap"));
17
-
18
12
  var _fromMask = _interopRequireDefault(require("./creator/fromMask"));
19
-
20
13
  var _fromMaskConnectedComponentLabelingAlgorithm = _interopRequireDefault(require("./creator/fromMaskConnectedComponentLabelingAlgorithm"));
21
-
22
14
  var _fromMaxima = _interopRequireDefault(require("./creator/fromMaxima"));
23
-
24
15
  var _fromPoints = _interopRequireDefault(require("./creator/fromPoints"));
25
-
26
16
  var _fromWaterShed = _interopRequireDefault(require("./creator/fromWaterShed"));
27
-
28
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
-
30
18
  /**
31
19
  * A manager of Regions of Interest. A RoiManager is related to a specific Image
32
20
  * and may contain multiple layers. Each layer is characterized by a label whose is
@@ -39,130 +27,107 @@ class RoiManager {
39
27
  constructor(image, options = {}) {
40
28
  this._image = image;
41
29
  this._options = options;
42
-
43
30
  if (!this._options.label) {
44
31
  this._options.label = 'default';
45
32
  }
46
-
47
33
  this._layers = {};
48
34
  this._painted = null;
49
- } // docs is in the corresponding file
50
-
35
+ }
51
36
 
37
+ // docs is in the corresponding file
52
38
  fromMaxima(options = {}) {
53
39
  let opt = Object.assign({}, this._options, options);
54
-
55
40
  let roiMap = _fromMaxima.default.call(this._image, options);
56
-
57
41
  this._layers[opt.label] = new _RoiLayer.default(roiMap, opt);
58
- } // docs is in the corresponding file
59
-
42
+ }
60
43
 
44
+ // docs is in the corresponding file
61
45
  fromPoints(points, options = {}) {
62
46
  let opt = Object.assign({}, this._options, options);
63
-
64
47
  let roiMap = _fromPoints.default.call(this._image, points, options);
65
-
66
48
  this._layers[opt.label] = new _RoiLayer.default(roiMap, opt);
67
49
  return this;
68
50
  }
51
+
69
52
  /**
70
53
  * @param {number[]} map
71
54
  * @param {object} [options]
72
55
  * @return {this}
73
56
  */
74
-
75
-
76
57
  putMap(map, options = {}) {
77
58
  let roiMap = new _RoiMap.default(this._image, map);
78
59
  let opt = Object.assign({}, this._options, options);
79
60
  this._layers[opt.label] = new _RoiLayer.default(roiMap, opt);
80
61
  return this;
81
- } // docs is in the corresponding file
82
-
62
+ }
83
63
 
64
+ // docs is in the corresponding file
84
65
  fromWaterShed(options = {}) {
85
66
  let opt = Object.assign({}, this._options, options);
86
-
87
67
  let roiMap = _fromWaterShed.default.call(this._image, options);
88
-
89
68
  this._layers[opt.label] = new _RoiLayer.default(roiMap, opt);
90
- } // docs is in the corresponding file
91
-
69
+ }
92
70
 
71
+ // docs is in the corresponding file
93
72
  fromMask(mask, options = {}) {
94
73
  let opt = Object.assign({}, this._options, options);
95
-
96
74
  let roiMap = _fromMask.default.call(this._image, mask, options);
97
-
98
75
  this._layers[opt.label] = new _RoiLayer.default(roiMap, opt);
99
76
  return this;
100
77
  }
101
-
102
78
  fromMaskConnectedComponentLabelingAlgorithm(mask, options = {}) {
103
79
  let opt = Object.assign({}, this._options, options);
104
-
105
80
  let roiMap = _fromMaskConnectedComponentLabelingAlgorithm.default.call(this._image, mask, options);
106
-
107
81
  this._layers[opt.label] = new _RoiLayer.default(roiMap, opt);
108
82
  return this;
109
83
  }
84
+
110
85
  /**
111
86
  *
112
87
  * @param {object} [options]
113
88
  * @return {RoiMap}
114
89
  */
115
-
116
-
117
90
  getMap(options = {}) {
118
91
  let opt = Object.assign({}, this._options, options);
119
-
120
92
  this._assertLayerWithLabel(opt.label);
121
-
122
93
  return this._layers[opt.label].roiMap;
123
94
  }
95
+
124
96
  /**
125
97
  * Return statistics about rows
126
98
  * @param {object} [options]
127
99
  * @return {object[]}
128
100
  */
129
-
130
-
131
101
  rowsInfo(options = {}) {
132
102
  return this.getMap(options).rowsInfo();
133
103
  }
104
+
134
105
  /**
135
106
  * Return statistics about columns
136
107
  * @param {object} [options]
137
108
  * @return {object[]}
138
109
  */
139
-
140
-
141
110
  colsInfo(options = {}) {
142
111
  return this.getMap(options).rowsInfo();
143
112
  }
113
+
144
114
  /**
145
115
  * Return the IDs of the Regions Of Interest (Roi) as an array of number
146
116
  * @param {object} [options]
147
117
  * @return {number[]}
148
118
  */
149
-
150
-
151
119
  getRoiIds(options = {}) {
152
120
  let rois = this.getRois(options);
153
-
154
121
  if (rois) {
155
122
  let ids = new Array(rois.length);
156
-
157
123
  for (let i = 0; i < rois.length; i++) {
158
124
  ids[i] = rois[i].id;
159
125
  }
160
-
161
126
  return ids;
162
127
  }
163
-
164
128
  throw new Error('ROIs not found');
165
129
  }
130
+
166
131
  /**
167
132
  * Allows to select ROI based on size, label and sign.
168
133
  * @param {object} [options={}]
@@ -179,8 +144,6 @@ class RoiManager {
179
144
  * @param {number} [options.maxRatio=Number.POSITIVE_INFINITY]
180
145
  * @return {Roi[]}
181
146
  */
182
-
183
-
184
147
  getRois(options = {}) {
185
148
  let {
186
149
  label = this._options.label,
@@ -195,22 +158,19 @@ class RoiManager {
195
158
  minRatio = 0,
196
159
  maxRatio = Number.POSITIVE_INFINITY
197
160
  } = options;
198
-
199
161
  if (!this._layers[label]) {
200
162
  throw new Error(`this Roi layer (${label}) does not exist`);
201
163
  }
202
-
203
164
  const allRois = this._layers[label].roi;
204
165
  const rois = [];
205
-
206
166
  for (const roi of allRois) {
207
167
  if ((roi.id < 0 && negative || roi.id > 0 && positive) && roi.surface >= minSurface && roi.surface <= maxSurface && roi.width >= minWidth && roi.width <= maxWidth && roi.height >= minHeight && roi.height <= maxHeight && roi.ratio >= minRatio && roi.ratio <= maxRatio) {
208
168
  rois.push(roi);
209
169
  }
210
170
  }
211
-
212
171
  return rois;
213
172
  }
173
+
214
174
  /**
215
175
  * Get an ROI by its id.
216
176
  * @param {number} roiId
@@ -218,51 +178,41 @@ class RoiManager {
218
178
  * @param {string} [options.label='default'] Label of the layer containing the ROI
219
179
  * @return {Roi}
220
180
  */
221
-
222
-
223
181
  getRoi(roiId, options = {}) {
224
182
  const {
225
183
  label = this._options.label
226
184
  } = options;
227
-
228
185
  if (!this._layers[label]) {
229
186
  throw new Error(`this Roi layer (${label}) does not exist`);
230
187
  }
231
-
232
188
  const roi = this._layers[label].roi.find(roi => roi.id === roiId);
233
-
234
189
  if (!roi) {
235
190
  throw new Error(`found no Roi with id ${roiId}`);
236
191
  }
237
-
238
192
  return roi;
239
193
  }
194
+
240
195
  /**
241
196
  * Returns an array of masks
242
197
  * See {@link Roi.getMask} for the options
243
198
  * @param {object} [options]
244
199
  * @return {Image[]} Retuns an array of masks (1 bit Image)
245
200
  */
246
-
247
-
248
201
  getMasks(options = {}) {
249
202
  let rois = this.getRois(options);
250
203
  let masks = new Array(rois.length);
251
-
252
204
  for (let i = 0; i < rois.length; i++) {
253
205
  masks[i] = rois[i].getMask(options);
254
206
  }
255
-
256
207
  return masks;
257
208
  }
209
+
258
210
  /**
259
211
  * Returns an array of masks
260
212
  * See {@link Roi.getAnalysisMasks} for the options
261
213
  * @param {object} [options]
262
214
  * @return {Image[]} Retuns an array of masks (1 bit Image)
263
215
  */
264
-
265
-
266
216
  getAnalysisMasks(options = {}) {
267
217
  const {
268
218
  analysisProperty
@@ -272,20 +222,18 @@ class RoiManager {
272
222
  if (rois.length === 0 || !rois[0][maskProperty]) return [];
273
223
  return rois.map(roi => roi[maskProperty]);
274
224
  }
225
+
275
226
  /**
276
227
  *
277
228
  * @param {object} [options]
278
229
  * @return {number[]}
279
230
  */
280
-
281
-
282
231
  getData(options = {}) {
283
232
  let opt = Object.assign({}, this._options, options);
284
-
285
233
  this._assertLayerWithLabel(opt.label);
286
-
287
234
  return this._layers[opt.label].roiMap.data;
288
235
  }
236
+
289
237
  /**
290
238
  * Paint the ROI on a copy of the image and return this image.
291
239
  * For painting options {@link Image.paintMasks}
@@ -298,48 +246,37 @@ class RoiManager {
298
246
  * @param {string} [options.unit="pixel"] Unit in which to display the values
299
247
  * @return {Image} - The painted RGBA 8 bits image
300
248
  */
301
-
302
-
303
249
  paint(options = {}) {
304
250
  let {
305
251
  labelProperty,
306
252
  analysisProperty
307
253
  } = options;
308
-
309
254
  if (!this._painted) {
310
255
  this._painted = this._image.rgba8();
311
256
  }
312
-
313
257
  let masks = this.getMasks(options);
314
-
315
258
  if (labelProperty) {
316
259
  const rois = this.getRois(options);
317
260
  options.labels = rois.map(roi => (0, _deepValue.default)(roi, labelProperty));
318
261
  const max = Math.max(...options.labels);
319
262
  let isSurface = false;
320
263
  let isDistance = false;
321
-
322
264
  if (labelProperty.includes('surface')) {
323
265
  isSurface = true;
324
266
  } else if (/(?:perimeter|min|max|external|width|height|length)/.test(labelProperty)) {
325
267
  isDistance = true;
326
268
  }
327
-
328
269
  if (isFinite(max)) {
329
270
  let unitLabel = '';
330
-
331
271
  if (options.unit !== 'pixel' && options.pixelSize && (isDistance || isSurface)) {
332
272
  unitLabel = isSurface ? `${options.unit}^2` : options.unit;
333
273
  let siLabel = isSurface ? 'm^2' : 'm';
334
274
  let factor = isSurface ? options.pixelSize ** 2 : options.pixelSize;
335
-
336
275
  const convert = _jsQuantities.default.swiftConverter(siLabel, unitLabel);
337
-
338
276
  options.labels = options.labels.map(value => {
339
277
  return convert(factor * value);
340
278
  });
341
279
  }
342
-
343
280
  if (max > 50) {
344
281
  options.labels = options.labels.map(number => Math.round(number) + unitLabel);
345
282
  } else if (max > 10) {
@@ -348,33 +285,28 @@ class RoiManager {
348
285
  options.labels = options.labels.map(number => number.toFixed(2) + unitLabel);
349
286
  }
350
287
  }
351
-
352
288
  options.labelsPosition = rois.map(roi => [roi.meanX, roi.meanY]);
353
289
  }
354
-
355
290
  this._painted.paintMasks(masks, options);
356
-
357
291
  if (analysisProperty) {
358
292
  let analysisMasks = this.getAnalysisMasks(options);
359
-
360
293
  this._painted.paintMasks(analysisMasks, {
361
294
  color: options.analysisColor,
362
295
  alpha: options.analysisAlpha
363
296
  });
364
297
  }
365
-
366
298
  return this._painted;
367
- } // return a mask corresponding to all the selected masks
368
-
299
+ }
369
300
 
301
+ // return a mask corresponding to all the selected masks
370
302
  getMask(options = {}) {
371
303
  let mask = new _Image.default(this._image.width, this._image.height, {
372
304
  kind: 'BINARY'
373
305
  });
374
306
  let masks = this.getMasks(options);
375
-
376
307
  for (let i = 0; i < masks.length; i++) {
377
- let roi = masks[i]; // we need to find the parent image to calculate the relative position
308
+ let roi = masks[i];
309
+ // we need to find the parent image to calculate the relative position
378
310
 
379
311
  for (let x = 0; x < roi.width; x++) {
380
312
  for (let y = 0; y < roi.height; y++) {
@@ -384,9 +316,9 @@ class RoiManager {
384
316
  }
385
317
  }
386
318
  }
387
-
388
319
  return mask;
389
320
  }
321
+
390
322
  /**
391
323
  * Reset the changes to the current painted iamge to the image that was
392
324
  * used during the creation of the RoiManager except if a new image is
@@ -394,19 +326,17 @@ class RoiManager {
394
326
  * @param {object} [options]
395
327
  * @param {Image} [options.image] A new iamge that you would like to sue for painting over
396
328
  */
397
-
398
-
399
329
  resetPainted(options = {}) {
400
330
  const {
401
331
  image
402
332
  } = options;
403
-
404
333
  if (image) {
405
334
  this._painted = this.image.rgba8();
406
335
  } else {
407
336
  this._painted = this._image.rgba8();
408
337
  }
409
338
  }
339
+
410
340
  /**
411
341
  * In place modification of the roiMap that joins regions of interest
412
342
  * @param {object} [options]
@@ -420,54 +350,46 @@ class RoiManager {
420
350
  * @param {number} [options.maxCommonBorderRatio=1] maximal common border ratio for merging
421
351
  * @return {this}
422
352
  */
423
-
424
-
425
353
  mergeRoi(options = {}) {
426
354
  const roiMap = this.getMap(options);
427
355
  roiMap.mergeRoi(options);
428
356
  this.putMap(roiMap.data, options);
429
357
  return this;
430
358
  }
359
+
431
360
  /**
432
361
  * Merge multiple rois into one.
433
362
  * All rois in the provided array will be merged into the first one.
434
363
  * @param {Array<number>} roiIds - A list of Roi ids to merge
435
364
  * @param {object} [options]
436
365
  */
437
-
438
-
439
366
  mergeRois(roiIds, options = {}) {
440
367
  if (!Array.isArray(roiIds) || roiIds.some(id => !Number.isInteger(id))) {
441
368
  throw new Error('Roi ids must be an array of integers');
442
369
  }
443
-
444
370
  if (roiIds.length < 2) {
445
371
  throw new Error('Roi ids must have at least two elements');
446
372
  }
447
-
448
373
  if (new Set(roiIds).size !== roiIds.length) {
449
374
  throw new Error('Roi ids must be all different');
450
- } // Throws if one of the ids is wrong
451
-
452
-
375
+ }
376
+ // Throws if one of the ids is wrong
453
377
  roiIds.forEach(roiId => this.getRoi(roiId));
454
378
  const roiMap = this.getMap(options);
455
379
  roiMap.mergeRois(roiIds);
456
380
  this.putMap(roiMap.data, options);
457
381
  return this;
458
382
  }
383
+
459
384
  /**
460
385
  * Finds all corresponding ROIs for all ROIs in the manager
461
386
  * @param {number[]} roiMap
462
387
  * @param {object} [options]
463
388
  * @return {Array} array of objects returned in correspondingRoisInformation
464
389
  */
465
-
466
-
467
390
  findCorrespondingRoi(roiMap, options = {}) {
468
391
  let allRois = this.getRois(options);
469
392
  let allRelated = [];
470
-
471
393
  for (let i = 0; i < allRois.length; i++) {
472
394
  let currentRoi = allRois[i];
473
395
  let x = currentRoi.minX;
@@ -477,17 +399,15 @@ class RoiManager {
477
399
  let currentRelated = correspondingRoisInformation(x, y, allPoints, roiMap, roiSign);
478
400
  allRelated.push(currentRelated);
479
401
  }
480
-
481
402
  return allRelated;
482
403
  }
483
-
484
404
  _assertLayerWithLabel(label) {
485
405
  if (!this._layers[label]) {
486
406
  throw new Error(`no layer with label ${label}`);
487
407
  }
488
408
  }
489
-
490
409
  }
410
+
491
411
  /**
492
412
  * For a given ROI, find corresponding ROIs and properties in given ROIMap.
493
413
  * Returns an object containing the ID of ROIs, the surface shared by given and corresponding ROIs,
@@ -501,10 +421,7 @@ class RoiManager {
501
421
  * @return {object} {{id: Array, surface: Array, roiSurfaceCovered: Array, same: number, opposite: number, total: number}}
502
422
  * @private
503
423
  */
504
-
505
-
506
424
  exports.default = RoiManager;
507
-
508
425
  function correspondingRoisInformation(x, y, points, roiMap, roiSign) {
509
426
  let correspondingRois = {
510
427
  id: [],
@@ -514,14 +431,12 @@ function correspondingRoisInformation(x, y, points, roiMap, roiSign) {
514
431
  opposite: 0,
515
432
  total: 0
516
433
  };
517
-
518
434
  for (let i = 0; i < points.length; i++) {
519
435
  let currentPoint = points[i];
520
436
  let currentX = currentPoint[0];
521
437
  let currentY = currentPoint[1];
522
438
  let correspondingRoiMapIndex = currentX + x + (currentY + y) * roiMap.width;
523
439
  let value = roiMap.data[correspondingRoiMapIndex];
524
-
525
440
  if (value > 0 || value < 0) {
526
441
  if (correspondingRois.id.includes(value)) {
527
442
  correspondingRois.surface[correspondingRois.id.indexOf(value)] += 1;
@@ -531,19 +446,15 @@ function correspondingRoisInformation(x, y, points, roiMap, roiSign) {
531
446
  }
532
447
  }
533
448
  }
534
-
535
449
  for (let i = 0; i < correspondingRois.id.length; i++) {
536
450
  let currentSign = Math.sign(correspondingRois.id[i]);
537
-
538
451
  if (currentSign === roiSign) {
539
452
  correspondingRois.same += correspondingRois.surface[i];
540
453
  } else {
541
454
  correspondingRois.opposite += correspondingRois.surface[i];
542
455
  }
543
-
544
456
  correspondingRois.roiSurfaceCovered[i] = correspondingRois.surface[i] / points.length;
545
457
  }
546
-
547
458
  correspondingRois.total = correspondingRois.opposite + correspondingRois.same;
548
459
  return correspondingRois;
549
460
  }
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = commonBorderLength;
7
-
8
7
  // We calculate all the border length with the neighbours
8
+
9
9
  function commonBorderLength(roiMap) {
10
10
  let data = roiMap.data;
11
11
  let dx = [+1, 0, -1, 0];
@@ -14,34 +14,26 @@ function commonBorderLength(roiMap) {
14
14
  let shift = -minMax.min;
15
15
  let max = minMax.max + shift;
16
16
  let borderInfo = [];
17
-
18
17
  for (let i = 0; i <= max; i++) {
19
18
  borderInfo.push(Object.create(null));
20
19
  }
21
-
22
20
  for (let x = 0; x < roiMap.width; x++) {
23
21
  for (let y = 0; y < roiMap.height; y++) {
24
22
  let target = x + y * roiMap.width;
25
23
  let currentRoiID = data[target];
26
-
27
24
  if (currentRoiID !== 0) {
28
25
  // each pixel may only contribute one time to a border
29
26
  let used = Object.create(null);
30
27
  let isBorder = false;
31
-
32
28
  for (let dir = 0; dir < 4; dir++) {
33
29
  let newX = x + dx[dir];
34
30
  let newY = y + dy[dir];
35
-
36
31
  if (newX >= 0 && newY >= 0 && newX < roiMap.width && newY < roiMap.height) {
37
32
  let neighbourRoiID = data[newX + newY * roiMap.width];
38
-
39
33
  if (currentRoiID !== neighbourRoiID) {
40
34
  isBorder = true;
41
-
42
35
  if (neighbourRoiID !== 0 && used[neighbourRoiID] === undefined) {
43
36
  used[neighbourRoiID] = true;
44
-
45
37
  if (!borderInfo[neighbourRoiID + shift][currentRoiID]) {
46
38
  borderInfo[neighbourRoiID + shift][currentRoiID] = 1;
47
39
  } else {
@@ -52,9 +44,8 @@ function commonBorderLength(roiMap) {
52
44
  } else {
53
45
  isBorder = true;
54
46
  }
55
- } // we will also add an information to specify the border length
56
-
57
-
47
+ }
48
+ // we will also add an information to specify the border length
58
49
  if (isBorder) {
59
50
  if (!borderInfo[currentRoiID + shift][currentRoiID]) {
60
51
  borderInfo[currentRoiID + shift][currentRoiID] = 1;
@@ -64,16 +55,14 @@ function commonBorderLength(roiMap) {
64
55
  }
65
56
  }
66
57
  }
67
- } // we convert now the result to an object for fast lookup and we will reshift the result
68
-
58
+ }
69
59
 
60
+ // we convert now the result to an object for fast lookup and we will reshift the result
70
61
  let result = {};
71
-
72
62
  for (let i = 0; i < borderInfo.length; i++) {
73
63
  if (Object.keys(borderInfo[i]).length > 0) {
74
64
  result[i - shift] = borderInfo[i];
75
65
  }
76
66
  }
77
-
78
67
  return result;
79
68
  }
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = mergeRoi;
7
-
8
7
  /**
9
8
  * In place modification of the roiMap that joins regions of interest
10
9
  * @param {object} [options]
@@ -27,31 +26,25 @@ function mergeRoi(options = {}) {
27
26
  minCommonBorderRatio = 0.3,
28
27
  maxCommonBorderRatio = 1
29
28
  } = options;
30
-
31
29
  let checkFunction = function (currentInfo, currentID, neighbourID) {
32
30
  return currentInfo[neighbourID] >= minCommonBorderLength && currentInfo[neighbourID] <= maxCommonBorderLength;
33
31
  };
34
-
35
32
  if (typeof algorithm === 'function') {
36
33
  checkFunction = algorithm;
37
34
  }
38
-
39
35
  if (algorithm.toLowerCase() === 'commonborderratio') {
40
36
  checkFunction = function (currentInfo, currentID, neighbourID) {
41
37
  let ratio = Math.min(currentInfo[neighbourID] / currentInfo[currentID], 1);
42
38
  return ratio >= minCommonBorderRatio && ratio <= maxCommonBorderRatio;
43
39
  };
44
40
  }
45
-
46
41
  const roiMap = this;
47
42
  const borderLengths = roiMap.commonBorderLength;
48
43
  let newMap = {};
49
44
  let oldToNew = {};
50
-
51
45
  for (let currentID of Object.keys(borderLengths)) {
52
46
  let currentInfo = borderLengths[currentID];
53
47
  let neighbourIDs = Object.keys(currentInfo);
54
-
55
48
  for (let neighbourID of neighbourIDs) {
56
49
  if (neighbourID !== currentID) {
57
50
  // it is not myself ...
@@ -61,25 +54,20 @@ function mergeRoi(options = {}) {
61
54
  if (oldToNew[neighbourID]) newNeighbourID = oldToNew[neighbourID];
62
55
  let newCurrentID = currentID;
63
56
  if (oldToNew[currentID]) newCurrentID = oldToNew[currentID];
64
-
65
57
  if (Number(newNeighbourID) !== newCurrentID) {
66
58
  let smallerID = Math.min(newNeighbourID, newCurrentID);
67
59
  let largerID = Math.max(newNeighbourID, newCurrentID);
68
-
69
60
  if (!newMap[smallerID]) {
70
61
  newMap[smallerID] = {};
71
62
  }
72
-
73
63
  newMap[smallerID][largerID] = true;
74
64
  oldToNew[largerID] = smallerID;
75
-
76
65
  if (newMap[largerID]) {
77
66
  // need to put everything to smallerID and remove property
78
67
  for (let id of Object.keys(newMap[largerID])) {
79
68
  newMap[smallerID][id] = true;
80
69
  oldToNew[id] = smallerID;
81
70
  }
82
-
83
71
  delete newMap[largerID];
84
72
  }
85
73
  }
@@ -87,31 +75,24 @@ function mergeRoi(options = {}) {
87
75
  }
88
76
  }
89
77
  }
90
-
91
78
  let minMax = roiMap.minMax;
92
79
  let shift = -minMax.min;
93
80
  let max = minMax.max + shift;
94
81
  let oldToNewArray = new Array(max + 1).fill(0);
95
-
96
82
  for (let key of Object.keys(oldToNew)) {
97
83
  oldToNewArray[Number(key) + shift] = oldToNew[key];
98
- } // time to change the roiMap
99
-
100
-
84
+ }
85
+ // time to change the roiMap
101
86
  let data = roiMap.data;
102
-
103
87
  for (let i = 0; i < data.length; i++) {
104
88
  let currentValue = data[i];
105
-
106
89
  if (currentValue !== 0) {
107
90
  let newValue = oldToNewArray[currentValue + shift];
108
-
109
91
  if (newValue !== 0) {
110
92
  data[i] = newValue;
111
93
  }
112
94
  }
113
95
  }
114
-
115
96
  roiMap.computed = {};
116
97
  return roiMap;
117
98
  }