3939#include " features/3d_gldzm.h"
4040#include " features/3d_glrlm.h"
4141#include " features/3d_glszm.h"
42+ #include " features/radial_distribution.h"
4243#include " features/roi_radius.h"
44+ #include " features/zernike.h"
4345#include " helpers/helpers.h"
4446#include " helpers/system_resource.h"
4547#include " helpers/timing.h"
4648#include " version.h"
4749
4850using namespace Nyxus ;
4951
50- bool Environment::spellcheck_raw_featurelist (const std::string& comma_separated_fnames, std::vector<std::string>& fnames)
52+ // The purpose of this methos is checking user's feature request but not changing the state of the Environment instance.
53+ // Specifically, it:
54+ // (1) splits 'comma_separated_fnames' into identifiers,
55+ // (2) checks if they are known feature and group names in the corresponding context (2D or 3D), and
56+ // (3) saves them in vector 'fnames'
57+ bool Environment::spellcheck_raw_featurelist (const std::string & comma_separated_fnames, std::vector<std::string> & fnames)
5158{
5259 fnames.clear ();
5360
@@ -76,58 +83,59 @@ bool Environment::spellcheck_raw_featurelist(const std::string& comma_separated_
7683
7784 }
7885
79- // Chop the CS- list
86+ // Chop the comma-separated feature list
8087 bool success = true ;
8188 std::vector<std::string> strings;
82- parse_delimited_string (comma_separated_fnames, " ," , strings);
89+ parse_delimited_string (comma_separated_fnames, " ," , strings);
8390
8491 // Check names of features and feature-groups
85- for (const std::string& s : strings)
92+ for (const std::string & s : strings)
8693 {
8794 // Forgive user's typos of consecutive commas e.g. MIN,MAX,,MEDIAN
8895 if (s.empty ())
8996 continue ;
9097
9198 auto s_uppr = Nyxus::toupper (s);
99+
92100 if (dim () == 2 )
93101 {
94- // Is feature found among 2D features?
95- int fg; // signed Fgroup2D
96- bool gnameExists = theFeatureSet.find_2D_GroupByString (s_uppr, fg);
97-
98- // Intercept an error: 2D feature group exists but requested in the non-2D mode
99- if (gnameExists && dim () != 2 )
102+ // ==== feature group ?
103+
104+ int _; // feature code, unused
105+ bool gfound1 = theFeatureSet.find_2D_GroupByString (s_uppr, _),
106+ gfound2 = theFeatureSet.find_IMQ_GroupByString (s_uppr, _);
107+
108+ // if 's' is recognized as a group, register it and skip checking it as an individual feature name
109+ if (gfound1 || gfound2)
100110 {
101- success = false ;
102- std::cerr << " Error: 2D feature group '" << s << " ' in non-2D mode\n " ;
103- continue ;
104- }
111+ // set the IMQ flag if applicable
112+ if (gfound2)
113+ theEnvironment.set_imq (true );
105114
106- // If a group is found, register it
107- if (gnameExists)
108- {
109- fnames.push_back (s_uppr);
115+ fnames.push_back (s_uppr);
110116 continue ;
111117 }
112118
113- int fcode; // signed Feature2D
114- bool fnameExists = theFeatureSet.find_2D_FeatureByString (s_uppr, fcode);
119+ // ==== individual feature ?
115120
116- // 2D feature group requested on a non-2D mode ?
117- if (fnameExists && dim () != 2 )
118- {
119- success = false ;
120- std::cerr << " Error: 2D feature '" << s << " ' in non-2D mode\n " ;
121- continue ;
122- }
121+ bool ffound1 = theFeatureSet.find_2D_FeatureByString (s_uppr, _),
122+ ffound2 = theFeatureSet.find_IMQ_FeatureByString (s_uppr, _);
123123
124- if (!fnameExists)
124+ // if a feature is found, register it
125+ if (! (ffound1 || ffound2))
125126 {
126127 success = false ;
127- std::cerr << " Error: expecting ' " + s + " ' to be a proper 2D feature name or feature file path\n " ;
128+ std::cerr << " Error: expecting " + s + " to be a proper 2D feature name or feature file path\n " ;
128129 }
129130 else
131+ {
132+ // set the IMQ flag if applicable
133+ if (ffound2)
134+ theEnvironment.set_imq (true );
135+
130136 fnames.push_back (s_uppr);
137+ }
138+
131139 } // 2D
132140
133141 if (dim () == 3 )
@@ -136,39 +144,23 @@ bool Environment::spellcheck_raw_featurelist(const std::string& comma_separated_
136144 int afg; // signed Fgroup3D
137145 bool gnameExists = theFeatureSet.find_3D_GroupByString (s_uppr, afg);
138146
139- // Intercept an error: 3D feature group exists but requested in the non-3D mode
140- if (gnameExists && dim () != 3 )
141- {
142- success = false ;
143- std::cerr << " Error: 3D feature group '" << s << " ' in non-3D mode\n " ;
144- continue ;
145- }
146-
147147 // If a group is found, register it
148148 if (gnameExists)
149149 {
150- fnames.push_back (s_uppr);
150+ fnames.push_back (s_uppr);
151151 continue ;
152152 }
153153
154154 int af; // signed Feature3D
155155 bool fnameExists = theFeatureSet.find_3D_FeatureByString (s_uppr, af);
156156
157- // 3D feature group requested on a non-3D mode ?
158- if (fnameExists && dim () != 3 )
159- {
160- success = false ;
161- std::cerr << " Error: 3D feature '" << s << " ' in non-3D mode\n " ;
162- continue ;
163- }
164-
165- if (!fnameExists)
157+ if (! fnameExists)
166158 {
167159 success = false ;
168160 std::cerr << " Error: expecting '" << s << " ' to be a proper 3D feature name or feature file path\n " ;
169161 }
170162 else
171- fnames.push_back (s_uppr);
163+ fnames.push_back (s_uppr);
172164 } // 3D
173165 }
174166
@@ -204,51 +196,26 @@ bool Environment::expand_2D_featuregroup (const std::string & s)
204196
205197 if ((Fgroup2D)fgcode == Fgroup2D::FG2_ALL)
206198 {
207- Nyxus::theFeatureSet.enableAll (enable);
199+ // enable just the 2D part of the feature set
200+ for (int i = (int ) Nyxus::Feature2D::_FIRST_; i < (int ) Nyxus::Feature2D::_COUNT_; i++)
201+ Nyxus::theFeatureSet.enableFeature (i);
208202 return true ;
209203 }
210204
211205 if ((Fgroup2D)fgcode == Fgroup2D::FG2_WHOLESLIDE)
212206 {
213- Nyxus::theFeatureSet.enableAll (enable);
214-
215- // Handle whole-slide mode differently: disable features irrelevant to this mode (shape, neighbors, etc)
216- std::cout << box_text (
217- " Activating whole slide (aka single-ROI) mode\n "
218- " Using GPU is advised!\n "
219- " ATTENTION: disabling inappplicable and time-sonsuming features:\n "
220- " - morphological features\n "
221- " - neighbor features\n "
222- " - GLDZM" );
223-
224- theFeatureSet.disableFeatures (BasicMorphologyFeatures::featureset);
225- theFeatureSet.disableFeatures (EnclosingInscribingCircumscribingCircleFeature::featureset);
226- // enabling ContourFeature (builds a special trivial wholeslide contour)
227- theFeatureSet.disableFeatures (ConvexHullFeature::featureset); // depends on ContourFeature
228- theFeatureSet.disableFeatures (FractalDimensionFeature::featureset); // depends on ContourFeature
229- theFeatureSet.disableFeatures (GeodeticLengthThicknessFeature::featureset); // depends on ContourFeature
230- theFeatureSet.disableFeatures (NeighborsFeature::featureset); // no neighbors for whole slide; depends on ContourFeature
231- theFeatureSet.disableFeatures (RoiRadiusFeature::featureset); // depends on ContourFeature
232- theFeatureSet.disableFeatures (EllipseFittingFeature::featureset);
233- theFeatureSet.disableFeatures (EulerNumberFeature::featureset);
234- theFeatureSet.disableFeatures (ExtremaFeature::featureset);
235- theFeatureSet.disableFeatures (ErosionPixelsFeature::featureset);
236- theFeatureSet.disableFeatures (CaliperFeretFeature::featureset);
237- theFeatureSet.disableFeatures (CaliperMartinFeature::featureset);
238- theFeatureSet.disableFeatures (CaliperNassensteinFeature::featureset);
239- theFeatureSet.disableFeatures (ChordsFeature::featureset);
240-
241- // enabling GaborFeature
242- // enabling only intensity image moments
243- theFeatureSet.disableFeatures (Smoms2D_feature::featureset);
244- // enabling GLCMFeature
245- // enabling GLDMFeature
246- theFeatureSet.disableFeatures (GLDZMFeature::featureset); // costs about 82 %
247- // enabling GLRLMFeature
248- // enabling GLSZMFeature
249- // enabling NGLDMfeature
250- // enabling NGTDMFeature
251-
207+ theFeatureSet.enableFeatures (ContourFeature::featureset, enable);
208+ theFeatureSet.enableFeatures (PixelIntensityFeatures::featureset, enable);
209+ theFeatureSet.enableFeatures (GLCMFeature::featureset, enable);
210+ theFeatureSet.enableFeatures (GLDMFeature::featureset, enable);
211+ theFeatureSet.enableFeatures (GLRLMFeature::featureset, enable);
212+ theFeatureSet.enableFeatures (GLSZMFeature::featureset, enable);
213+ theFeatureSet.enableFeatures (NGLDMfeature::featureset, enable);
214+ theFeatureSet.enableFeatures (NGTDMFeature::featureset, enable);
215+ theFeatureSet.enableFeatures (GaborFeature::featureset, enable);
216+ theFeatureSet.enableFeatures (Imoms2D_feature::featureset, enable);
217+ theFeatureSet.enableFeatures (RadialDistributionFeature::featureset, enable);
218+ theFeatureSet.enableFeatures (ZernikeFeature::featureset, enable);
252219 return true ;
253220 }
254221
@@ -533,11 +500,11 @@ void Environment::expand_featuregroups()
533500 if (expand_IMQ_featuregroup (s))
534501 return ;
535502
536- FeatureIMQ a;
503+ int a;
537504 if (!theFeatureSet.find_IMQ_FeatureByString (s, a))
538505 throw std::invalid_argument (" Error: '" + s + " ' is not a valid Image Quality feature name \n " );
539506
540- theFeatureSet.enableFeature (int (a) );
507+ theFeatureSet.enableFeature (a );
541508 continue ;
542509 }
543510
@@ -571,10 +538,9 @@ void Environment::expand_featuregroups()
571538 if (dim () == 3 )
572539 {
573540 int a; // signed Feature3D
574- if (!Nyxus:: theFeatureSet.find_3D_FeatureByString (s, a))
541+ if (!theFeatureSet.find_3D_FeatureByString (s, a))
575542 throw std::invalid_argument (" Error: '" + s + " ' is not a valid 3D feature name \n " );
576-
577- Nyxus::theFeatureSet.enableFeature (int (a));
543+ theFeatureSet.enableFeature (a);
578544 continue ;
579545 }
580546 }
0 commit comments