Skip to content

Commit 2adb2e4

Browse files
authored
POL5773 volumetric regression unit tests (PolusAI#279)
1 parent 114fc29 commit 2adb2e4

38 files changed

+4087
-2108
lines changed

README.md

Lines changed: 785 additions & 847 deletions
Large diffs are not rendered by default.

docs/source/featurelist.rst

Lines changed: 743 additions & 853 deletions
Large diffs are not rendered by default.

src/nyx/dirs_and_files.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,15 @@ namespace Nyxus
9191
}
9292
else
9393
{
94-
// read segmentation counterparts
95-
readDirectoryFiles_2D(dirLabels, filePatt, labelFiles, purefnames_m);
96-
9794
if (!wholeslide && !existsOnFilesystem(dirLabels))
9895
{
9996
err = "cannot access directory " + dirLabels;
10097
return 1;
10198
}
10299

100+
// read segmentation counterparts
101+
readDirectoryFiles_2D(dirLabels, filePatt, labelFiles, purefnames_m);
102+
103103
// Check if the dataset is meaningful
104104
if (intensFiles.size() == 0 || labelFiles.size() == 0)
105105
{

src/nyx/env_features.cpp

Lines changed: 25 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -336,64 +336,40 @@ bool Environment::expand_3D_featuregroup (const std::string& s)
336336
// mutually exclusive groups:
337337
if ((Fgroup3D)fgcode == Fgroup3D::FG3_ALL)
338338
{
339-
340-
#if 0
341-
// 3D features planned for a future PR
342-
343-
Feature3D::AREA,
344-
Feature3D::MESH_VOLUME,
345-
Feature3D::VOLUME_CONVEXHULL,
346-
Feature3D::DIAMETER_EQUAL_AREA,
347-
Feature3D::DIAMETER_EQUAL_VOLUME,
348-
349-
Feature3D::VOLUME_PIXELS,
350-
Feature3D::CENTROID_X,
351-
Feature3D::CENTROID_Y,
352-
Feature3D::CENTROID_Z,
353-
Feature3D::BBOX_XMIN,
354-
Feature3D::BBOX_YMIN,
355-
Feature3D::BBOX_ZMIN,
356-
Feature3D::BBOX_HEIGHT,
357-
Feature3D::BBOX_WIDTH,
358-
Feature3D::BBOX_DEPTH,
359-
360-
// Neighbor features
361-
Feature3D::NUM_NEIGHBORS,
362-
Feature3D::PERCENT_TOUCHING,
363-
Feature3D::CLOSEST_NEIGHBOR1_DIST,
364-
Feature3D::CLOSEST_NEIGHBOR1_ANG,
365-
Feature3D::CLOSEST_NEIGHBOR2_DIST,
366-
Feature3D::CLOSEST_NEIGHBOR2_ANG,
367-
Feature3D::ANG_BW_NEIGHBORS_MEAN,
368-
Feature3D::ANG_BW_NEIGHBORS_STDDEV,
369-
Feature3D::ANG_BW_NEIGHBORS_MODE,
370-
371-
// Spatial (raw) moments
372-
Feature3D::SPAT_MOMENT_00,
373-
Feature3D::SPAT_MOMENT_01,
374-
Feature3D::SPAT_MOMENT_02,
375-
Feature3D::SPAT_MOMENT_03,
376-
Feature3D::SPAT_MOMENT_10,
377-
Feature3D::SPAT_MOMENT_11,
378-
Feature3D::SPAT_MOMENT_12,
379-
Feature3D::SPAT_MOMENT_13,
380-
Feature3D::SPAT_MOMENT_20,
381-
Feature3D::SPAT_MOMENT_21,
382-
Feature3D::SPAT_MOMENT_22,
383-
Feature3D::SPAT_MOMENT_23,
384-
Feature3D::SPAT_MOMENT_30
385-
#endif
386-
387-
theFeatureSet.enableFeatures (D3_PixelIntensityFeatures::featureset, enable);
339+
theFeatureSet.enableFeatures (D3_VoxelIntensityFeatures::featureset, enable);
340+
theFeatureSet.enableFeatures (D3_SurfaceFeature::featureset, enable);
388341
theFeatureSet.enableFeatures (D3_GLCM_feature::featureset, enable);
389342
theFeatureSet.enableFeatures (D3_GLDM_feature::featureset, enable);
390343
theFeatureSet.enableFeatures (D3_GLDZM_feature::featureset, enable);
391344
theFeatureSet.enableFeatures (D3_GLRLM_feature::featureset, enable);
392345
theFeatureSet.enableFeatures (D3_GLSZM_feature::featureset, enable);
393346
theFeatureSet.enableFeatures (D3_NGLDM_feature::featureset, enable);
394347
theFeatureSet.enableFeatures (D3_NGTDM_feature::featureset, enable);
348+
349+
return true;
350+
}
351+
352+
if ((Fgroup3D)fgcode == Fgroup3D::FG3_INTENSITY)
353+
{
354+
theFeatureSet.enableFeatures (D3_VoxelIntensityFeatures::featureset, enable);
355+
return true;
356+
}
357+
358+
if ((Fgroup3D)fgcode == Fgroup3D::FG3_MORPHOLOGY)
359+
{
395360
theFeatureSet.enableFeatures (D3_SurfaceFeature::featureset, enable);
361+
return true;
362+
}
396363

364+
if ((Fgroup3D)fgcode == Fgroup3D::FG3_TEXTURE)
365+
{
366+
theFeatureSet.enableFeatures (D3_GLCM_feature::featureset, enable);
367+
theFeatureSet.enableFeatures (D3_GLDM_feature::featureset, enable);
368+
theFeatureSet.enableFeatures (D3_GLDZM_feature::featureset, enable);
369+
theFeatureSet.enableFeatures (D3_GLRLM_feature::featureset, enable);
370+
theFeatureSet.enableFeatures (D3_GLSZM_feature::featureset, enable);
371+
theFeatureSet.enableFeatures (D3_NGLDM_feature::featureset, enable);
372+
theFeatureSet.enableFeatures (D3_NGTDM_feature::featureset, enable);
397373
return true;
398374
}
399375

src/nyx/feature_mgr_init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ FeatureManager::FeatureManager()
7777
register_feature (new ZernikeFeature());
7878
register_feature (new RadialDistributionFeature());
7979
// 3D
80-
register_feature (new D3_PixelIntensityFeatures());
80+
register_feature (new D3_VoxelIntensityFeatures());
8181
register_feature (new D3_SurfaceFeature());
8282
register_feature (new D3_GLCM_feature());
8383
register_feature (new D3_GLDM_feature());

src/nyx/features/3d_intensity.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66

77
using namespace Nyxus;
88

9-
bool D3_PixelIntensityFeatures::required (const FeatureSet & fs)
9+
bool D3_VoxelIntensityFeatures::required (const FeatureSet & fs)
1010
{
11-
return fs.anyEnabled ({D3_PixelIntensityFeatures::featureset});
11+
return fs.anyEnabled ({D3_VoxelIntensityFeatures::featureset});
1212
}
1313

14-
D3_PixelIntensityFeatures::D3_PixelIntensityFeatures() : FeatureMethod("PixelIntensityFeatures_3D")
14+
D3_VoxelIntensityFeatures::D3_VoxelIntensityFeatures() : FeatureMethod("PixelIntensityFeatures_3D")
1515
{
16-
provide_features ({D3_PixelIntensityFeatures::featureset});
16+
provide_features ({D3_VoxelIntensityFeatures::featureset});
1717
}
1818

19-
void D3_PixelIntensityFeatures::calculate(LR& r)
19+
void D3_VoxelIntensityFeatures::calculate(LR& r)
2020
{
2121
// --MIN, MAX
2222
val_MIN = r.aux_min;
@@ -137,10 +137,10 @@ void D3_PixelIntensityFeatures::calculate(LR& r)
137137
val_HYPERFLATNESS = denom == 0. ? 0. : sumPow6 / denom;
138138
}
139139

140-
void D3_PixelIntensityFeatures::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity)
140+
void D3_VoxelIntensityFeatures::osized_add_online_pixel(size_t x, size_t y, uint32_t intensity)
141141
{}
142142

143-
void D3_PixelIntensityFeatures::osized_calculate(LR& r, ImageLoader& imloader)
143+
void D3_VoxelIntensityFeatures::osized_calculate(LR& r, ImageLoader& imloader)
144144
{
145145
// --MIN, MAX
146146
val_MIN = r.aux_min;
@@ -256,7 +256,7 @@ void D3_PixelIntensityFeatures::osized_calculate(LR& r, ImageLoader& imloader)
256256
val_HYPERFLATNESS = mom.hyperflatness();
257257
}
258258

259-
void D3_PixelIntensityFeatures::save_value(std::vector<std::vector<double>>& fvals)
259+
void D3_VoxelIntensityFeatures::save_value(std::vector<std::vector<double>>& fvals)
260260
{
261261
fvals[(int)Feature3D::INTEGRATED_INTENSITY][0] = val_INTEGRATED_INTENSITY;
262262
fvals[(int)Feature3D::MEAN][0] = val_MEAN;
@@ -297,15 +297,15 @@ void D3_PixelIntensityFeatures::save_value(std::vector<std::vector<double>>& fva
297297
fvals[(int)Feature3D::VARIANCE_BIASED][0] = val_VARIANCE_BIASED;
298298
}
299299

300-
void D3_PixelIntensityFeatures::parallel_process(std::vector<int>& roi_labels, std::unordered_map <int, LR>& roiData, int n_threads)
300+
void D3_VoxelIntensityFeatures::parallel_process(std::vector<int>& roi_labels, std::unordered_map <int, LR>& roiData, int n_threads)
301301
{
302302
size_t jobSize = roi_labels.size(),
303303
workPerThread = jobSize / n_threads;
304304

305-
runParallel(D3_PixelIntensityFeatures::parallel_process_1_batch, n_threads, workPerThread, jobSize, &roi_labels, &roiData);
305+
runParallel(D3_VoxelIntensityFeatures::parallel_process_1_batch, n_threads, workPerThread, jobSize, &roi_labels, &roiData);
306306
}
307307

308-
void D3_PixelIntensityFeatures::parallel_process_1_batch(size_t firstitem, size_t lastitem, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
308+
void D3_VoxelIntensityFeatures::parallel_process_1_batch(size_t firstitem, size_t lastitem, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
309309
{
310310
// Calculate the feature for each batch ROI item
311311
for (auto i = firstitem; i < lastitem; i++)
@@ -319,25 +319,25 @@ void D3_PixelIntensityFeatures::parallel_process_1_batch(size_t firstitem, size_
319319
continue;
320320

321321
// Calculate the feature and save it in ROI's csv-friendly buffer 'fvals'
322-
D3_PixelIntensityFeatures f;
322+
D3_VoxelIntensityFeatures f;
323323
f.calculate(r);
324324
f.save_value(r.fvals);
325325
}
326326
}
327327

328-
void D3_PixelIntensityFeatures::reduce(size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
328+
void D3_VoxelIntensityFeatures::reduce(size_t start, size_t end, std::vector<int>* ptrLabels, std::unordered_map <int, LR>* ptrLabelData)
329329
{
330330
for (auto i = start; i < end; i++)
331331
{
332332
int lab = (*ptrLabels)[i];
333333
LR& r = (*ptrLabelData)[lab];
334-
D3_PixelIntensityFeatures f;
334+
D3_VoxelIntensityFeatures f;
335335
f.calculate(r);
336336
f.save_value(r.fvals);
337337
}
338338
}
339339

340-
void D3_PixelIntensityFeatures::cleanup_instance()
340+
void D3_VoxelIntensityFeatures::cleanup_instance()
341341
{
342342
val_INTEGRATED_INTENSITY = 0;
343343
val_MEAN = 0;

src/nyx/features/3d_intensity.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#pragma once
22
#include "../feature_method.h"
33

4-
class D3_PixelIntensityFeatures : public FeatureMethod
4+
class D3_VoxelIntensityFeatures : public FeatureMethod
55
{
66
public:
7-
D3_PixelIntensityFeatures();
7+
D3_VoxelIntensityFeatures();
88
void calculate(LR& r);
99
void osized_add_online_pixel(size_t x, size_t y, uint32_t intensity);
1010
void osized_calculate(LR& r, ImageLoader& imloader);

src/nyx/features/3d_surface.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ void D3_SurfaceFeature::build_surface (LR & r)
278278
Points P;
279279
for (auto& plane : r.contours_3D)
280280
{
281-
for (auto ip : plane.second)
281+
for (auto ip : plane)
282282
{
283283
auto v = r.raw_pixels_3D[ip];
284284
P.push_back (std::array<float, 3>({ (float)v.x, (float)v.y, (float)v.z }));
@@ -324,17 +324,33 @@ void D3_SurfaceFeature::calculate (LR& r)
324324

325325
// surface
326326

327+
// -- order z-planes' indices
328+
std::vector<int> zindices;
329+
for (auto& plane : r.zplanes)
330+
zindices.push_back (plane.first);
331+
std::sort (zindices.begin(), zindices.end());
332+
327333
// -- calculate contours
328334
r.contours_3D.clear();
329335

330-
for (auto& plane : r.zplanes)
336+
for (auto zi : zindices)
331337
{
338+
auto& planeVoxs = r.zplanes[zi]; // deterministically indexed plane
339+
332340
// skinny contour
333341
std::vector<size_t> K; // indices in the cloud
334-
build_contour_imp (K, r.raw_pixels_3D, plane.second, plane.first, r.aabb.get_width(), r.aabb.get_height(), r.aabb.get_xmin(), r.aabb.get_ymin());
342+
build_contour_imp (
343+
K,
344+
r.raw_pixels_3D,
345+
planeVoxs,
346+
zi,
347+
r.aabb.get_width(),
348+
r.aabb.get_height(),
349+
r.aabb.get_xmin(),
350+
r.aabb.get_ymin());
335351

336352
// store it
337-
r.contours_3D[plane.first] = K;
353+
r.contours_3D.push_back (K);
338354
}
339355

340356
// -- build the hull complex
@@ -369,7 +385,7 @@ void D3_SurfaceFeature::calculate (LR& r)
369385
size_t hullCloudLen = 0;
370386
for (auto& plane : r.contours_3D)
371387
{
372-
for (auto ip : plane.second)
388+
for (auto ip : plane)
373389
{
374390
auto v = r.raw_pixels_3D[ip];
375391
cx += v.x;

0 commit comments

Comments
 (0)