Skip to content

Commit 37b09b8

Browse files
committed
Revert "ENH: Add SST-zoomed mapping to computeIPFIntensity for properly filled density images"
This reverts commit 238756a.
1 parent c0b0913 commit 37b09b8

3 files changed

Lines changed: 100 additions & 149 deletions

File tree

Source/EbsdLib/LaueOps/LaueOps.cpp

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
#include <canvas_ity.hpp>
5858

5959
#include <algorithm> // for std::max
60-
#include <array>
6160
#include <chrono>
6261
#include <exception>
6362
#include <iomanip>
@@ -944,21 +943,29 @@ ebsdlib::Rgb LaueOps::generateMisorientationColor(const QuatD& q, const QuatD& r
944943
}
945944

946945
// -----------------------------------------------------------------------------
947-
std::array<float, 2> LaueOps::adjustFigureOrigin(std::array<float, 2> figureOrigin, int legendWidth, int legendHeight, const std::vector<float>& margins, float fontPtSize,
948-
bool generateEntirePlane) const
946+
std::array<float, 2> LaueOps::adjustFigureOrigin(
947+
std::array<float, 2> figureOrigin,
948+
int legendWidth, int legendHeight,
949+
const std::vector<float>& margins, float fontPtSize,
950+
bool generateEntirePlane) const
949951
{
950952
return figureOrigin;
951953
}
952954

953955
// -----------------------------------------------------------------------------
954-
UInt8ArrayType::Pointer LaueOps::annotateIPFImage(UInt8ArrayType::Pointer triangleImage, int imageDim, int canvasDim, const std::string& title, bool generateEntirePlane) const
956+
UInt8ArrayType::Pointer LaueOps::annotateIPFImage(
957+
UInt8ArrayType::Pointer triangleImage,
958+
int imageDim,
959+
int canvasDim,
960+
const std::string& title,
961+
bool generateEntirePlane) const
955962
{
956963
const float fontPtSize = static_cast<float>(canvasDim) / 24.0f;
957964
const std::vector<float> margins = {
958-
fontPtSize * 3, // Top
959-
static_cast<float>(canvasDim / 7.0f), // Right
960-
fontPtSize * 2, // Bottom
961-
static_cast<float>(canvasDim / 7.0f) // Left
965+
fontPtSize * 3, // Top
966+
static_cast<float>(canvasDim / 7.0f), // Right
967+
fontPtSize * 2, // Bottom
968+
static_cast<float>(canvasDim / 7.0f) // Left
962969
};
963970

964971
int legendHeight = canvasDim - static_cast<int>(margins[0]) - static_cast<int>(margins[2]);
@@ -1006,7 +1013,10 @@ UInt8ArrayType::Pointer LaueOps::annotateIPFImage(UInt8ArrayType::Pointer triang
10061013
context.fill();
10071014

10081015
// Draw the triangle image onto the canvas
1009-
context.draw_image(image->getPointer(0), imageDim, imageDim, imageDim * image->getNumberOfComponents(), figureOrigin[0], figureOrigin[1], static_cast<float>(legendWidth),
1016+
context.draw_image(image->getPointer(0), imageDim, imageDim,
1017+
imageDim * image->getNumberOfComponents(),
1018+
figureOrigin[0], figureOrigin[1],
1019+
static_cast<float>(legendWidth),
10101020
static_cast<float>(legendHeight));
10111021

10121022
// Draw title
@@ -1018,14 +1028,20 @@ UInt8ArrayType::Pointer LaueOps::annotateIPFImage(UInt8ArrayType::Pointer triang
10181028
drawIPFAnnotations(context, canvasDim, fontPtSize, margins, figureOrigin, figureCenter, generateEntirePlane);
10191029

10201030
// Extract rendered pixels and remove alpha channel
1021-
ebsdlib::UInt8ArrayType::Pointer rgbaCanvasImage = ebsdlib::UInt8ArrayType::CreateArray(canvasDim * canvasDim, {4ULL}, "Annotated IPF", true);
1031+
ebsdlib::UInt8ArrayType::Pointer rgbaCanvasImage = ebsdlib::UInt8ArrayType::CreateArray(
1032+
canvasDim * canvasDim, {4ULL}, "Annotated IPF", true);
10221033
context.get_image_data(rgbaCanvasImage->getPointer(0), canvasDim, canvasDim, canvasDim * 4, 0, 0);
10231034

10241035
return ebsdlib::RemoveAlphaChannel(rgbaCanvasImage.get());
10251036
}
10261037

10271038
// -----------------------------------------------------------------------------
1028-
UInt8ArrayType::Pointer LaueOps::drawColorBar(UInt8ArrayType::Pointer image, int canvasDim, int numColors, double minValue, double maxValue, bool isMRD) const
1039+
UInt8ArrayType::Pointer LaueOps::drawColorBar(
1040+
UInt8ArrayType::Pointer image,
1041+
int canvasDim,
1042+
int numColors,
1043+
double minValue, double maxValue,
1044+
bool isMRD) const
10291045
{
10301046
const float fontPtSize = static_cast<float>(canvasDim) / 24.0f;
10311047

@@ -1048,7 +1064,10 @@ UInt8ArrayType::Pointer LaueOps::drawColorBar(UInt8ArrayType::Pointer image, int
10481064

10491065
canvas_ity::canvas context(canvasDim, canvasDim);
10501066
// Put the existing image onto the canvas
1051-
context.draw_image(rgbaImage->getPointer(0), canvasDim, canvasDim, canvasDim * 4, 0.0f, 0.0f, static_cast<float>(canvasDim), static_cast<float>(canvasDim));
1067+
context.draw_image(rgbaImage->getPointer(0), canvasDim, canvasDim,
1068+
canvasDim * 4, 0.0f, 0.0f,
1069+
static_cast<float>(canvasDim),
1070+
static_cast<float>(canvasDim));
10521071

10531072
// Color bar dimensions
10541073
const float barLeft = static_cast<float>(canvasDim) * 0.80f;
@@ -1118,7 +1137,9 @@ UInt8ArrayType::Pointer LaueOps::drawColorBar(UInt8ArrayType::Pointer image, int
11181137
}
11191138

11201139
// -----------------------------------------------------------------------------
1121-
std::vector<UInt8ArrayType::Pointer> LaueOps::generateAnnotatedIPFDensity(InversePoleFigureConfiguration_t& config, std::pair<double, double>* outMinMax) const
1140+
std::vector<UInt8ArrayType::Pointer> LaueOps::generateAnnotatedIPFDensity(
1141+
InversePoleFigureConfiguration_t& config,
1142+
std::pair<double, double>* outMinMax) const
11221143
{
11231144
// Validate square images
11241145
if(config.imageWidth != config.imageHeight)
@@ -1151,29 +1172,10 @@ std::vector<UInt8ArrayType::Pointer> LaueOps::generateAnnotatedIPFDensity(Invers
11511172
ebsdlib::FloatArrayType::Pointer dirs1 = InversePoleFigureUtilities::computeIPFDirections(*this, config.eulers, config.sampleDirections[1]);
11521173
ebsdlib::FloatArrayType::Pointer dirs2 = InversePoleFigureUtilities::computeIPFDirections(*this, config.eulers, config.sampleDirections[2]);
11531174

1154-
// Step 2: Compute SST bounding box for zoomed density images
1155-
// getIpfColorAngleLimits returns {etaMin, etaMax, chiMax(eta)} in radians.
1156-
auto angleLimits = getIpfColorAngleLimits(0.0);
1157-
double etaMin = angleLimits[0];
1158-
double etaMax = angleLimits[1];
1159-
1160-
// Get chiMax at etaMax (gives the largest chiMax for cubic; same for others)
1161-
auto angleLimitsAtMax = getIpfColorAngleLimits(etaMax);
1162-
double chiMax = angleLimitsAtMax[2];
1163-
1164-
// Also check chiMax at etaMin in case it's larger
1165-
auto angleLimitsAtMin = getIpfColorAngleLimits(etaMin);
1166-
if(angleLimitsAtMin[2] > chiMax)
1167-
{
1168-
chiMax = angleLimitsAtMin[2];
1169-
}
1170-
1171-
std::array<double, 4> sstBBox = {etaMin, etaMax, 0.0, chiMax};
1172-
1173-
// Compute intensity images with SST-zoomed mapping
1174-
ebsdlib::DoubleArrayType::Pointer intensity0 = InversePoleFigureUtilities::computeIPFIntensity(*this, dirs0.get(), imageDim, imageDim, config.lambertDim, config.normalizeMRD, &sstBBox);
1175-
ebsdlib::DoubleArrayType::Pointer intensity1 = InversePoleFigureUtilities::computeIPFIntensity(*this, dirs1.get(), imageDim, imageDim, config.lambertDim, config.normalizeMRD, &sstBBox);
1176-
ebsdlib::DoubleArrayType::Pointer intensity2 = InversePoleFigureUtilities::computeIPFIntensity(*this, dirs2.get(), imageDim, imageDim, config.lambertDim, config.normalizeMRD, &sstBBox);
1175+
// Step 2: Compute intensity images
1176+
ebsdlib::DoubleArrayType::Pointer intensity0 = InversePoleFigureUtilities::computeIPFIntensity(*this, dirs0.get(), imageDim, imageDim, config.lambertDim, config.normalizeMRD);
1177+
ebsdlib::DoubleArrayType::Pointer intensity1 = InversePoleFigureUtilities::computeIPFIntensity(*this, dirs1.get(), imageDim, imageDim, config.lambertDim, config.normalizeMRD);
1178+
ebsdlib::DoubleArrayType::Pointer intensity2 = InversePoleFigureUtilities::computeIPFIntensity(*this, dirs2.get(), imageDim, imageDim, config.lambertDim, config.normalizeMRD);
11771179

11781180
// Step 3: Find global min/max
11791181
double globalMax = std::numeric_limits<double>::lowest();

Source/EbsdLib/Utilities/InversePoleFigureUtilities.cpp

Lines changed: 50 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ ebsdlib::FloatArrayType::Pointer InversePoleFigureUtilities::computeIPFDirection
137137

138138
// -----------------------------------------------------------------------------
139139
ebsdlib::DoubleArrayType::Pointer InversePoleFigureUtilities::computeIPFIntensity(const LaueOps& ops, ebsdlib::FloatArrayType* ipfDirections, int imageWidth, int imageHeight, int lambertDim,
140-
bool normalizeMRD, const std::array<double, 4>* sstBoundingBox)
140+
bool normalizeMRD)
141141
{
142142
// Step 1: Bin the crystal directions into the Lambert projection
143143
float sphereRadius = 1.0f;
@@ -169,112 +169,66 @@ ebsdlib::DoubleArrayType::Pointer InversePoleFigureUtilities::computeIPFIntensit
169169
// If not MRD, leave as raw counts
170170
}
171171

172-
// Step 3: Create the output intensity image
172+
// Step 3: Create the output intensity image using equal-area projection
173173
std::vector<size_t> tDims = {static_cast<size_t>(imageWidth * imageHeight)};
174174
std::vector<size_t> cDims = {1};
175175
ebsdlib::DoubleArrayType::Pointer intensity = ebsdlib::DoubleArrayType::CreateArray(tDims, cDims, "IPF_Intensity", true);
176176
double* intensityPtr = intensity->getPointer(0);
177177

178-
if(sstBoundingBox != nullptr)
179-
{
180-
// SST-zoomed mode: map pixels directly to (eta, chi) within the bounding box
181-
double etaMin = (*sstBoundingBox)[0];
182-
double etaMax = (*sstBoundingBox)[1];
183-
double chiMin = (*sstBoundingBox)[2];
184-
double chiMax = (*sstBoundingBox)[3];
178+
// Lambert azimuthal equal-area projection centered on north pole
179+
// Maps the upper hemisphere (z >= 0) to a disk of radius sqrt(2)
180+
float unitRadius = std::sqrt(2.0f);
181+
float span = 2.0f * unitRadius;
182+
float xres = span / static_cast<float>(imageWidth);
183+
float yres = span / static_cast<float>(imageHeight);
184+
185+
int halfWidth = imageWidth / 2;
186+
int halfHeight = imageHeight / 2;
185187

186-
for(int y = 0; y < imageHeight; y++)
188+
for(int y = 0; y < imageHeight; y++)
189+
{
190+
for(int x = 0; x < imageWidth; x++)
187191
{
188-
for(int x = 0; x < imageWidth; x++)
192+
int index = y * imageWidth + x;
193+
194+
// Map pixel to equal-area projection coordinates
195+
float xtmp = static_cast<float>(x - halfWidth) * xres + (xres * 0.5f);
196+
float ytmp = static_cast<float>(y - halfHeight) * yres + (yres * 0.5f);
197+
198+
float rhoSq = xtmp * xtmp + ytmp * ytmp;
199+
200+
// Check if within hemisphere disk
201+
if(rhoSq > 2.0f)
189202
{
190-
int index = y * imageWidth + x;
191-
192-
// Map pixel to (eta, chi) within the bounding box
193-
// x maps to eta (left=etaMin, right=etaMax)
194-
// y maps to chi (top=chiMin, bottom=chiMax)
195-
double eta = etaMin + (static_cast<double>(x) + 0.5) / static_cast<double>(imageWidth) * (etaMax - etaMin);
196-
double chi = chiMin + (static_cast<double>(y) + 0.5) / static_cast<double>(imageHeight) * (chiMax - chiMin);
197-
198-
if(!ops.inUnitTriangle(eta, chi))
199-
{
200-
intensityPtr[index] = -1.0;
201-
continue;
202-
}
203-
204-
// Convert (eta, chi) to unit sphere xyz
205-
double sinChi = std::sin(chi);
206-
std::array<float, 3> xyz = {static_cast<float>(sinChi * std::cos(eta)), static_cast<float>(sinChi * std::sin(eta)), static_cast<float>(std::cos(chi))};
207-
208-
// Look up intensity from Lambert bins
209-
std::array<float, 2> sqCoord = {0.0f, 0.0f};
210-
bool isNorth = lambert->getSquareCoord(xyz.data(), sqCoord.data());
211-
if(isNorth)
212-
{
213-
intensityPtr[index] = lambert->getInterpolatedValue(ModifiedLambertProjection::NorthSquare, sqCoord.data());
214-
}
215-
else
216-
{
217-
intensityPtr[index] = lambert->getInterpolatedValue(ModifiedLambertProjection::SouthSquare, sqCoord.data());
218-
}
203+
intensityPtr[index] = -1.0; // Outside hemisphere
204+
continue;
219205
}
220-
}
221-
}
222-
else
223-
{
224-
// Default full Lambert hemisphere disk mapping
225-
float unitRadius = std::sqrt(2.0f);
226-
float span = 2.0f * unitRadius;
227-
float xres = span / static_cast<float>(imageWidth);
228-
float yres = span / static_cast<float>(imageHeight);
229206

230-
int halfWidth = imageWidth / 2;
231-
int halfHeight = imageHeight / 2;
207+
// Inverse Lambert azimuthal equal-area projection (north pole centered)
208+
float t = std::sqrt(1.0f - rhoSq / 4.0f);
209+
std::array<float, 3> xyz = {xtmp * t, ytmp * t, 1.0f - rhoSq / 2.0f};
232210

233-
for(int y = 0; y < imageHeight; y++)
234-
{
235-
for(int x = 0; x < imageWidth; x++)
211+
// Compute chi (polar angle from z-axis) and eta (azimuthal angle)
212+
double chi = std::acos(static_cast<double>(xyz[2]));
213+
double eta = std::atan2(static_cast<double>(xyz[1]), static_cast<double>(xyz[0]));
214+
215+
// Check if direction is inside the Standard Stereographic Triangle
216+
if(!ops.inUnitTriangle(eta, chi))
217+
{
218+
intensityPtr[index] = -1.0; // Outside SST
219+
continue;
220+
}
221+
222+
// Look up the interpolated intensity from the Lambert projection
223+
std::array<float, 2> sqCoord = {0.0f, 0.0f};
224+
bool isNorth = lambert->getSquareCoord(xyz.data(), sqCoord.data());
225+
if(isNorth)
226+
{
227+
intensityPtr[index] = lambert->getInterpolatedValue(ModifiedLambertProjection::NorthSquare, sqCoord.data());
228+
}
229+
else
236230
{
237-
int index = y * imageWidth + x;
238-
239-
// Map pixel to equal-area projection coordinates
240-
float xtmp = static_cast<float>(x - halfWidth) * xres + (xres * 0.5f);
241-
float ytmp = static_cast<float>(y - halfHeight) * yres + (yres * 0.5f);
242-
243-
float rhoSq = xtmp * xtmp + ytmp * ytmp;
244-
245-
// Check if within hemisphere disk
246-
if(rhoSq > 2.0f)
247-
{
248-
intensityPtr[index] = -1.0; // Outside hemisphere
249-
continue;
250-
}
251-
252-
// Inverse Lambert azimuthal equal-area projection (north pole centered)
253-
float t = std::sqrt(1.0f - rhoSq / 4.0f);
254-
std::array<float, 3> xyz = {xtmp * t, ytmp * t, 1.0f - rhoSq / 2.0f};
255-
256-
// Compute chi (polar angle from z-axis) and eta (azimuthal angle)
257-
double chi = std::acos(static_cast<double>(xyz[2]));
258-
double eta = std::atan2(static_cast<double>(xyz[1]), static_cast<double>(xyz[0]));
259-
260-
// Check if direction is inside the Standard Stereographic Triangle
261-
if(!ops.inUnitTriangle(eta, chi))
262-
{
263-
intensityPtr[index] = -1.0; // Outside SST
264-
continue;
265-
}
266-
267-
// Look up the interpolated intensity from the Lambert projection
268-
std::array<float, 2> sqCoord = {0.0f, 0.0f};
269-
bool isNorth = lambert->getSquareCoord(xyz.data(), sqCoord.data());
270-
if(isNorth)
271-
{
272-
intensityPtr[index] = lambert->getInterpolatedValue(ModifiedLambertProjection::NorthSquare, sqCoord.data());
273-
}
274-
else
275-
{
276-
intensityPtr[index] = lambert->getInterpolatedValue(ModifiedLambertProjection::SouthSquare, sqCoord.data());
277-
}
231+
intensityPtr[index] = lambert->getInterpolatedValue(ModifiedLambertProjection::SouthSquare, sqCoord.data());
278232
}
279233
}
280234
}
@@ -283,8 +237,7 @@ ebsdlib::DoubleArrayType::Pointer InversePoleFigureUtilities::computeIPFIntensit
283237
}
284238

285239
// -----------------------------------------------------------------------------
286-
void InversePoleFigureUtilities::createIPFColorImage(ebsdlib::DoubleArrayType* intensity, int imageWidth, int imageHeight, int numColors, double minScale, double maxScale,
287-
ebsdlib::UInt8ArrayType* rgba)
240+
void InversePoleFigureUtilities::createIPFColorImage(ebsdlib::DoubleArrayType* intensity, int imageWidth, int imageHeight, int numColors, double minScale, double maxScale, ebsdlib::UInt8ArrayType* rgba)
288241
{
289242
// Initialize the image with all zeros
290243
rgba->initializeWithZeros();

Source/EbsdLib/Utilities/InversePoleFigureUtilities.h

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,17 @@ class LaueOps; // Forward declaration
5656
*/
5757
struct InversePoleFigureConfiguration_t
5858
{
59-
ebsdlib::FloatArrayType* eulers; ///<* The Euler Angles (in Radians) to use for the inverse pole figure
60-
std::array<Matrix3X1D, 3> sampleDirections; ///<* 3 orthogonal sample reference directions (e.g., RD, TD, ND)
61-
int imageWidth; ///<* The width of the generated inverse pole figure image in pixels
62-
int imageHeight; ///<* The height of the generated inverse pole figure image in pixels
63-
int lambertDim; ///<* The dimensions in voxels of the Lambert Square used for binning/smoothing
64-
int numColors; ///<* The number of colors to use in the color map
65-
std::string colorMap; ///<* Name of the ColorMap to use
66-
bool normalizeMRD; ///<* true=normalize to MRD (Multiples of Random Distribution), false=raw counts
67-
std::vector<std::string> labels; ///<* The labels for each of the 3 inverse pole figures (e.g., "RD", "TD", "ND")
68-
std::string phaseName; ///<* The name of the phase
69-
bool FlipFinalImage; ///<* If TRUE, the final image will be flipped across the X Axis so that +Y axis points UP
59+
ebsdlib::FloatArrayType* eulers; ///<* The Euler Angles (in Radians) to use for the inverse pole figure
60+
std::array<Matrix3X1D, 3> sampleDirections; ///<* 3 orthogonal sample reference directions (e.g., RD, TD, ND)
61+
int imageWidth; ///<* The width of the generated inverse pole figure image in pixels
62+
int imageHeight; ///<* The height of the generated inverse pole figure image in pixels
63+
int lambertDim; ///<* The dimensions in voxels of the Lambert Square used for binning/smoothing
64+
int numColors; ///<* The number of colors to use in the color map
65+
std::string colorMap; ///<* Name of the ColorMap to use
66+
bool normalizeMRD; ///<* true=normalize to MRD (Multiples of Random Distribution), false=raw counts
67+
std::vector<std::string> labels; ///<* The labels for each of the 3 inverse pole figures (e.g., "RD", "TD", "ND")
68+
std::string phaseName; ///<* The name of the phase
69+
bool FlipFinalImage; ///<* If TRUE, the final image will be flipped across the X Axis so that +Y axis points UP
7070
};
7171

7272
/**
@@ -104,13 +104,9 @@ class EbsdLib_EXPORT InversePoleFigureUtilities
104104
* @param imageHeight Output image height in pixels
105105
* @param lambertDim Lambert square dimension for binning/smoothing
106106
* @param normalizeMRD true to normalize to MRD, false for raw counts
107-
* @param sstBoundingBox Optional SST bounding box {etaMin, etaMax, chiMin, chiMax} in radians.
108-
* When provided, pixels map to only this region in (eta, chi) space, making the SST fill the image.
109-
* When nullptr, uses the default full Lambert hemisphere disk mapping.
110107
* @return DoubleArrayType intensity image (imageWidth * imageHeight). Pixels outside SST have value -1.0.
111108
*/
112-
static ebsdlib::DoubleArrayType::Pointer computeIPFIntensity(const LaueOps& ops, ebsdlib::FloatArrayType* ipfDirections, int imageWidth, int imageHeight, int lambertDim, bool normalizeMRD,
113-
const std::array<double, 4>* sstBoundingBox = nullptr);
109+
static ebsdlib::DoubleArrayType::Pointer computeIPFIntensity(const LaueOps& ops, ebsdlib::FloatArrayType* ipfDirections, int imageWidth, int imageHeight, int lambertDim, bool normalizeMRD);
114110

115111
/**
116112
* @brief Converts an intensity image to RGBA with SST masking. Pixels inside the SST

0 commit comments

Comments
 (0)