11 #ifndef PCAnalysis_HPP
12 #define PCAnalysis_HPP
20 #include <QStringList>
38 setName(
"Stack/Shape Analysis/PCAnalysis");
39 setDesc(
"Compute the principle components of the image. If the threshold is -1, then all \n"
40 "the values are used, as is. If 'Draw Result' is set to true, the current mesh \n"
41 "will be erased and replaced with shapes representing the cells fit. 'Splan Correction' \n"
42 "can be either a shape, a single value of a vector of 3 values, corresponding to the \n"
43 "correction to apply for the eigen-values on all three directions.");
44 setIcon(QIcon(
":/images/PCAnalysis.png"));
46 addParm(
"Output",
"File to write the output to",
"output.csv");
47 addParm(
"Span Correction",
"Span correction can be made using pre-computed formula for regular shapes, or a percentage of the PC.",
"Ellipsoid",
48 QStringList() <<
"Ellipsoid" <<
"Cuboid" <<
"Elliptical Cylinder" <<
"Maximum Span");
49 addParm(
"Draw Result",
"Shape used to display the result",
"No", QStringList() <<
"No" <<
"Ellipsoids" <<
"Cuboids" <<
"Cylinder");
50 addParm(
"Threshold",
"If the stack is not labeled, a single volume is considered with all voxels of intensity greater than this threshold.",
"100");
51 addParm(
"Shape Details",
"How finely to draw the shape (for cylinders or ellipsoids)",
"3");
56 if(!checkState().stack())
58 Stack* stk = currentStack();
60 QString fn = parm(
"Output");
61 QString correction = parm(
"Span Correction").trimmed();
63 if(correction ==
"Ellipsoid")
64 correctingFactor = sqrt(5);
65 else if(correction ==
"Cuboid")
66 correctingFactor = sqrt(3);
67 else if(correction ==
"Elliptical Cylinder")
68 correctingFactor =
Point3f(sqrt(3), sqrt(4), sqrt(4));
69 else if(correction ==
"Maximum Span")
71 else if(correction.endsWith(
'%')) {
72 QString cor = correction.left(correction.size() - 1);
74 float cr = cor.toFloat(&ok);
76 correctingFactor = -cr / 100.f;
78 setErrorMessage(QString(
"Error, percentage value is not valid: '%1'").arg(cor));
83 float cr = correction.toFloat(&ok);
85 correctingFactor = cr;
87 QStringList vs = correction.split(QRegExp(
"[ ,-;:-]"));
89 correctingFactor.
x() = vs[0].toFloat(&ok);
91 setErrorMessage(QString(
"Invalid x value for correction factor: '%1'.").arg(vs[0]));
94 correctingFactor.
y() = vs[1].toFloat(&ok);
96 setErrorMessage(QString(
"Invalid y value for correction factor: '%1'.").arg(vs[1]));
99 correctingFactor.
z() = vs[2].toFloat(&ok);
101 setErrorMessage(QString(
"Invalid z value for correction factor: '%1'.").arg(vs[2]));
105 setErrorMessage(QString(
"Invalid correction string '%1', expected one of 'Ellipsoid'"
106 ", 'Cuboid', 'Elliptical Cylinder', Maximum Span', a percentage, a single "
107 "value or three values"));
112 bool draw_result =
false;
113 Mesh* m = mesh(stk->
id());
115 = run(stk, store, m, fn, parm(
"Threshold").toInt(), parm(
"Draw Result"), correctingFactor,
116 parm(
"Shape Details").toInt(), draw_result);
117 if(res and draw_result) {
139 bool run(
Stack* stack,
Store* store,
Mesh* m, QString filename,
int treshold, QString shape,
140 Point3f correctingFactor,
int slices,
bool& draw_result);
156 setName(
"Mesh/Cell Axis/Shape Analysis/Compute Shape Analysis 2D");
157 setDesc(
"Compute the principle components of the image. If the threshold is -1, then all \n"
158 "the values are used, as is. If 'Draw Result' is set to true, the current mesh \n"
159 "will be erased and replaced with shapes representing the cells fit. 'Span Correction' \n"
160 "can be either a shape, a single value of a vector of 3 values, corresponding to the b\n"
161 "correction to apply for the eigen-values on all three directions.");
162 setIcon(QIcon(
":/images/PDG.png"));
164 addParm(
"Output",
"File to write the output to",
"output.csv");
165 addParm(
"Axis Line Scale",
"Amount to scale the axis lines",
"1.0");
166 addParm(
"Axis Line Width",
"",
"2.0");
167 addParm(
"Span Correction",
"Span correction can be made using pre-computed formula for regular shapes, or a percentage of the PC.",
168 "Cuboid", QStringList() <<
"Ellipsoid" <<
"Cuboid");
173 Mesh* m = currentMesh();
175 QString outp =
"None";
178 if(parm(
"Span Correction") ==
"Ellipsoid")
179 correcting_factor = sqrt(5);
180 else if(parm(
"Span Correction") ==
"Cuboid")
181 correcting_factor = sqrt(3);
183 return run(m, parm(
"Output"), parm(
"Axis Line Scale").toDouble(), parm(
"Axis Line Width").toDouble(), outp,
184 correcting_factor, outputHeatMap,
true);
187 bool run(
Mesh* m, QString filename,
double axisLineScale,
double axisLineWidth, QString outp,
198 pAxisColor, pAxisWidth, pAxisScale, pAxisOffset, pAspectRatioThreshold, pCustomShear, pNumParms};
202 setName(
"Mesh/Cell Axis/Shape Analysis/Display Shape Axis");
203 setDesc(
"Display the principle growth directions");
204 setIcon(QIcon(
":/images/PDG.png"));
206 addParm(
"Heatmap",
"Display as a color map PCA values in max or min direction, or max*min, or max/min.",
"Product Max*Min",
207 QStringList() <<
"None" <<
"Max" <<
"Min" <<
"Ratio Max/Min" <<
"Product Max*Min" <<
"Anisotropy Max/(Max+Min)" <<
"CustomX" <<
"CustomY");
208 addParm(
"ScaleHeat",
"Scale heat map",
"Auto", QStringList() <<
"None" <<
"Auto" <<
"Manual");
209 addParm(
"Heat min",
"High bound heat map",
"1");
210 addParm(
"Heat max",
"Low bound heat map",
"3");
211 addParm(
"Show Axis",
"Draw pca directions as vectors.",
"Both",
212 QStringList() <<
"Both" <<
"Max" <<
"Min" <<
"CustomX" <<
"CustomY" <<
"BothCustom" <<
"None");
213 addParm(
"Axis Color",
"Color used to draw pca",
"white", QColor::colorNames());
214 addParm(
"Line Width",
"Line Width",
"2.0");
215 addParm(
"Line Scale",
"Length of the vectors = Scale * Strain.",
"1.0");
216 addParm(
"Line Offset",
"Draw the vector ends a bit tilted up for proper display on surfaces.",
"0.0");
217 addParm(
"Threshold",
"Minimal value of aspect ratio (= PCAMax/PCAMin) required for drawing PCA.",
"0.0");
218 addParm(
"Create Attr Maps",
"Create Attr Maps",
"No",QStringList() << booleanChoice());
221 bool initialize( QWidget* parent);
228 if(!checkState().mesh(MESH_NON_EMPTY))
230 return run(currentMesh());
236 return run(mesh, DisplayHeatMap, scaleHeatMap, RangeHeat, DisplayAxis,
237 AxisColor, AxisWidth, AxisScale, AxisOffset, AspectRatioThreshold, CustomShear, CreateAttrs);
240 bool run(
Mesh* mesh,
const QString displayHeatMap,
const QString scaleHeatMap,
const Point2d &rangeHeat,
241 const QString displayPCA,
const QColor& axisColor,
float axisLineWidth,
242 float scaleAxisLength,
float axisOffset,
float aspectRatioThreshold,
bool customShear,
bool createAttrMaps);
245 QString DisplayHeatMap;
246 QString scaleHeatMap;
253 float AspectRatioThreshold;
264 pAxisColor, pAxisWidth, pAxisScale, pAxisOffset, pAspectRatioThreshold, pCustomShear, pNumParms};
268 setName(
"Mesh/Cell Axis/Experimental/Shape Analysis/Display Shape Axis New");
269 setDesc(
"Display the principle growth directions");
270 setIcon(QIcon(
":/images/PDG.png"));
272 addParm(
"Heatmap",
"Display as a color map PCA values in max or min direction, or max*min, or max/min.",
"Product Max*Min",
273 QStringList() <<
"None" <<
"Max" <<
"Min" <<
"Ratio Max/Min" <<
"Product Max*Min" <<
"Anisotropy Max/(Max+Min)" <<
"CustomX" <<
"CustomY");
274 addParm(
"ScaleHeat",
"Scale heat map",
"Auto", QStringList() <<
"None" <<
"Auto" <<
"Manual");
275 addParm(
"Heat min",
"High bound heat map",
"1");
276 addParm(
"Heat max",
"Low bound heat map",
"3");
277 addParm(
"Show Axis",
"Draw pca directions as vectors.",
"Both",
278 QStringList() <<
"Both" <<
"Max" <<
"Min" <<
"CustomX" <<
"CustomY" <<
"BothCustom" <<
"None");
279 addParm(
"Axis Color",
"Color used to draw pca",
"white", QColor::colorNames());
280 addParm(
"Line Width",
"Line Width",
"2.0");
281 addParm(
"Line Scale",
"Length of the vectors = Scale * Strain.",
"1.0");
282 addParm(
"Line Offset",
"Draw the vector ends a bit tilted up for proper display on surfaces.",
"0.0");
283 addParm(
"Threshold",
"Minimal value of aspect ratio (= PCAMax/PCAMin) required for drawing PCA.",
"0.0");
284 addParm(
"Create Attr Maps",
"Create Attr Maps",
"No",QStringList() << booleanChoice());
292 if(!checkState().mesh(MESH_NON_EMPTY))
294 return run(currentMesh());
299 DisplayHeatMap = parm(
"Heatmap");
300 scaleHeatMap = parm(
"ScaleHeat");
301 RangeHeat =
Point2d(parm(
"Heat min").toDouble(), parm(
"Heat max").toDouble());
302 DisplayAxis = parm(
"Show Axis");
303 AxisColor = parm(
"Axis Color");
304 AxisWidth = parm(
"Line Width").toFloat();
305 AxisScale = parm(
"Line Scale").toFloat();
306 AxisOffset = parm(
"Line Offset").toFloat();
307 AspectRatioThreshold = parm(
"Threshold").toFloat();
309 return run(mesh, DisplayHeatMap, scaleHeatMap, RangeHeat, DisplayAxis,
310 AxisColor, AxisWidth, AxisScale, AxisOffset, AspectRatioThreshold, CustomShear, CreateAttrs);
313 bool run(
Mesh* mesh,
const QString displayHeatMap,
const QString scaleHeatMap,
const Point2d &rangeHeat,
314 const QString displayPCA,
const QColor& axisColor,
float axisLineWidth,
315 float scaleAxisLength,
float axisOffset,
float aspectRatioThreshold,
bool customShear,
bool createAttrMaps);
318 QString DisplayHeatMap;
319 QString scaleHeatMap;
326 float AspectRatioThreshold;
345 setName(
"Mesh/Cell Axis 3D/Shape Analysis/Compute Shape Analysis 3D");
346 setDesc(
"Compute the PCA of the cell shapes");
347 setIcon(QIcon(
":/images/PDG.png"));
349 addParm(
"Input",
"Input",
"Mesh Triangles", QStringList() <<
"Stack Voxels" <<
"Mesh Triangles");
350 addParm(
"Span Correction",
"Span correction can be made using pre-computed formula for regular shapes, or a percentage of the PC.",
351 "Ellipsoid", QStringList() <<
"Ellipsoid" <<
"Cuboid" <<
"Elliptical Cylinder" <<
"Maximum Span");
359 QString correction = parm(
"Span Correction").trimmed();
361 if(correction ==
"Ellipsoid")
362 correctingFactor = sqrt(5);
363 else if(correction ==
"Cuboid")
364 correctingFactor = sqrt(3);
365 else if(correction ==
"Elliptical Cylinder")
366 correctingFactor =
Point3d(sqrt(3), sqrt(4), sqrt(4));
367 else if(correction ==
"Maximum Span")
368 correctingFactor = 0;
369 else if(correction.endsWith(
'%')) {
370 QString cor = correction.left(correction.size() - 1);
372 float cr = cor.toFloat(&ok);
374 correctingFactor = -cr / 100.f;
376 setErrorMessage(QString(
"Error, percentage value is not valid: '%1'").arg(cor));
381 float cr = correction.toFloat(&ok);
383 correctingFactor = cr;
385 QStringList vs = correction.split(QRegExp(
"[ ,-;:-]"));
387 correctingFactor.
x() = vs[0].toDouble(&ok);
389 setErrorMessage(QString(
"Invalid x value for correction factor: '%1'.").arg(vs[0]));
392 correctingFactor.
y() = vs[1].toDouble(&ok);
394 setErrorMessage(QString(
"Invalid y value for correction factor: '%1'.").arg(vs[1]));
397 correctingFactor.
z() = vs[2].toDouble(&ok);
399 setErrorMessage(QString(
"Invalid z value for correction factor: '%1'.").arg(vs[2]));
403 setErrorMessage(QString(
"Invalid correction string '%1', expected one of 'Ellipsoid'"
404 ", 'Cuboid', 'Elliptical Cylinder', Maximum Span', a percentage, a single "
405 "value or three values"));
410 bool draw_result =
false;
411 Mesh* m = currentMesh();
412 bool res = run(m, correctingFactor, parm(
"Input"));
413 if(res and draw_result) {
420 bool run(
Mesh* m,
Point3d correctingFactor, QString inputMode);
431 pAxisColor, pAxisWidth, pAxisScale, pAxisOffset, pAspectRatioThreshold, pNumParms};
435 setName(
"Mesh/Cell Axis 3D/Shape Analysis/Display Shape Axis 3D");
436 setDesc(
"Display the PCA based shape axes directions");
437 setIcon(QIcon(
":/images/PDG.png"));
439 addParm(
"Heatmap",
"Display shape values as a heat map. Product = Max*Mid*Min",
"Product",
440 QStringList() <<
"None" <<
"Max" <<
"Mid" <<
"Min" <<
"Elongation (Max/Mid)" <<
"Flatness (Mid/Min)" <<
"Max/Min"
441 <<
"Product" <<
"Shape Anisotropy" <<
"Custom X" <<
"Custom Y" <<
"Custom Z");
442 addParm(
"ScaleHeat",
"Scale heat map",
"Auto", QStringList() <<
"None" <<
"Auto" <<
"Manual");
443 addParm(
"Heat min",
"High bound heat map",
"1");
444 addParm(
"Heat max",
"Low bound heat map",
"3");
445 addParm(
"Show Axis",
"Draw pca directions as vectors.",
"All", QStringList()
446 <<
"All" <<
"Max" <<
"Mid" <<
"Min" <<
"Custom All" <<
"Custom X" <<
"Custom Y" <<
"Custom Z" <<
"None");
447 addParm(
"Axis Color",
"Color used to draw pca",
"white", QColor::colorNames());
448 addParm(
"Line Width",
"Line Width",
"2.0");
449 addParm(
"Line Scale",
"Length of the vectors = Scale * Strain.",
"1.0");
450 addParm(
"Line Offset",
"Draw the vector ends a bit tilted up for proper display on surfaces.",
"0.0");
451 addParm(
"Threshold",
"Minimal value of aspect ratio (= PCAMax/PCAMin) required for drawing PCA.",
"0.0");
452 addParm(
"Create Attr Maps",
"Create Attribute Maps for all heat map options",
"No", booleanChoice());
460 if(!checkState().mesh(MESH_NON_EMPTY))
462 return run(currentMesh());
468 return run(mesh, DisplayHeatMap,
ScaleHeatMap, RangeHeat, DisplayAxis,
469 AxisColor, AxisWidth, AxisScale, AxisOffset, AspectRatioThreshold, attrMaps);
472 bool run(
Mesh* mesh,
const QString displayHeatMap,
const QString scaleHeatMap,
const Point2d &rangeHeat,
473 const QString displayPCA,
const QColor& axisColor,
float axisLineWidth,
474 float scaleAxisLength,
float axisOffset,
float aspectRatioThreshold,
bool attrMaps);
477 QString DisplayHeatMap;
485 float AspectRatioThreshold;