Skip to content

Commit ed272c8

Browse files
imikejacksonclaude
andcommitted
ENH: ColorKeyKind dispatch on LaueOps; drop HexConvention from IPF color
Per-class color-key selection now flows through a `ColorKeyKind` enum passed at the IPF-color call site instead of a long-lived `m_ColorKey` member. Each LaueOps subclass owns three file-local static singletons (TSL, PUCM, NolzeHielscher) sized to its rotation point group and fundamental sector geometry, so callers can switch styles per pixel / per legend without mutating shared state and without having to know which Laue class they're constructing the key for. API shape: - generateIPFColor(eulers, refDir, deg, ColorKeyKind kind = TSL) - generateRodriguesColor(r1, r2, r3) (was conv-parameterized) - generateIPFTriangleLegend(dim, full, HexConvention conv, ColorKeyKind kind = TSL, bool gridded = false) - computeIPFColor(eulers, refDir, deg, const IColorKey* key) -- public Removed: - LaueOps::setColorKey / getColorKey / setLegendRenderMode - LaueOps::m_ColorKey member - LegendRenderMode enum (subsumed by the `gridded` arg on legend) - generateIPFColorImpl from the 4 hex/trig classes -- IPF color is invariant under HexConvention, so base computeIPFColor via the canonical X||a* getQuatSymOp tables suffices. Audit pattern: - HexConvention gains `NotApplicable = 0` sentinel. - Non-hex/trig overrides default conv to NotApplicable. - Hex/trig overrides drop the default (caller must pass conv). - Base virtuals on conv-dependent methods have no default -- polymorphic callers must choose deliberately. App / test plumbing: - render_ebsd consolidates its local ColorKeyKind enum onto ebsdlib::ColorKeyKind; installColorKey() helper is gone. - make_ipf threads ColorKeyKind through executeAng / executeCtf / GenerateIPFColorsImpl instead of setColorKey-loops over LaueOps. - generate_ipf_legends passes kind=NolzeHielscher + gridded=true to the legend call directly. Tests: - New ColorKeyKindTest pins the new API: enum exists, default is TSL, PUCM/NH differ from TSL across all 11 Laue classes, legend accepts kind + gridded. - TSLColorKeyTest, IPFLegendTest, GriddedColorKeyTest rewritten to use the new API instead of mutating m_ColorKey. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 82fec52 commit ed272c8

42 files changed

Lines changed: 860 additions & 1046 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Source/Apps/generate_ipf_legends.cpp

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ void GeneratePoleFigures(LaueOps& ops, int symType)
280280
// Read in the Quats File
281281
ConvertOrientations convertor;
282282
auto outputOrientations = convertor.execute(k_QuatsFilePath, "eulers_000_1_deg.csv", ",", "qu2eu", true);
283-
auto poleFigureNames = ops.getDefaultPoleFigureNames();
283+
auto poleFigureNames = ops.getDefaultPoleFigureNames(ebsdlib::HexConvention::XParallelAStar);
284284

285285
PoleFigureConfiguration_t config;
286286
config.eulers = outputOrientations.get();
@@ -351,50 +351,40 @@ void GenerateNolzeHielscherLegends(int imageDim)
351351
ebsdlib::FundamentalSectorGeometry::trigonalHigh, // 10: Trigonal_High
352352
};
353353

354+
(void)sectorFactories; // Per-class NH sectors are now baked into each LaueOps subclass.
355+
354356
for(size_t i = 0; i < allOps.size(); i++)
355357
{
356358
auto& ops = *allOps[i];
357359
std::string symName = EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_");
358360

359-
// Set NH color key
360-
auto sector = sectorFactories[i]();
361-
auto nhKey = std::make_shared<ebsdlib::NolzeHielscherColorKey>(sector);
362-
ops.setColorKey(nhKey);
363-
364-
// Generate full-circle legend
365-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
361+
// Generate full-circle NH legend
362+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar, ebsdlib::ColorKeyKind::NolzeHielscher, /*gridded=*/false);
366363
std::stringstream ss;
367364
ss << k_Output_Dir << "/" << symName << "/" << symName << "_NH_FULL.png";
368365
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
369366
std::cout << ops.getSymmetryName() << " NH Full Result: " << result.first << ": " << result.second << std::endl;
370367

371-
// Generate triangle-only legend
372-
legend = ops.generateIPFTriangleLegend(imageDim, false);
368+
// Generate triangle-only NH legend
369+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar, ebsdlib::ColorKeyKind::NolzeHielscher, /*gridded=*/false);
373370
ss.str("");
374371
ss << k_Output_Dir << "/" << symName << "/" << symName << "_NH.png";
375372
result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
376373
std::cout << ops.getSymmetryName() << " NH Triangle Result: " << result.first << ": " << result.second << std::endl;
377374

378-
// Set to grid-interpolated mode (MTEX-style rendering, 0.5 degree grid)
379-
ops.setLegendRenderMode(ebsdlib::LegendRenderMode::GridInterpolated, 0.5);
380-
381-
// Generate gridded legends at higher resolution (2000x2000)
375+
// Generate gridded NH legends (MTEX-style flat shading, 2000x2000)
382376
constexpr int k_GriddedImageDim = 2000;
383-
legend = ops.generateIPFTriangleLegend(k_GriddedImageDim, true);
377+
legend = ops.generateIPFTriangleLegend(k_GriddedImageDim, true, ebsdlib::HexConvention::XParallelAStar, ebsdlib::ColorKeyKind::NolzeHielscher, /*gridded=*/true);
384378
ss.str("");
385379
ss << k_Output_Dir << "/" << symName << "/" << symName << "_NH_GRIDDED_FULL.png";
386380
result = PngWriter::WriteColorImage(ss.str(), k_GriddedImageDim, k_GriddedImageDim, 3, legend->getPointer(0));
387381
std::cout << ops.getSymmetryName() << " NH Gridded Full Result: " << result.first << ": " << result.second << std::endl;
388382

389-
// Generate gridded triangle-only legend
390-
legend = ops.generateIPFTriangleLegend(k_GriddedImageDim, false);
383+
legend = ops.generateIPFTriangleLegend(k_GriddedImageDim, false, ebsdlib::HexConvention::XParallelAStar, ebsdlib::ColorKeyKind::NolzeHielscher, /*gridded=*/true);
391384
ss.str("");
392385
ss << k_Output_Dir << "/" << symName << "/" << symName << "_NH_GRIDDED.png";
393386
result = PngWriter::WriteColorImage(ss.str(), k_GriddedImageDim, k_GriddedImageDim, 3, legend->getPointer(0));
394387
std::cout << ops.getSymmetryName() << " NH Gridded Triangle Result: " << result.first << ": " << result.second << std::endl;
395-
396-
// Reset to TSL for subsequent operations
397-
ops.setColorKey(std::make_shared<ebsdlib::TSLColorKey>());
398388
}
399389
}
400390

@@ -415,13 +405,13 @@ int main(int argc, char* argv[])
415405
int imageDim = 1500;
416406
{
417407
TrigonalOps ops;
418-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
408+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
419409
ss.str("");
420410
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
421411
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
422412
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
423413

424-
legend = ops.generateIPFTriangleLegend(imageDim, false);
414+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
425415
int xStart = imageDim * 0.05F;
426416
int yStart = 0;
427417
int numCols = imageDim * 0.75F;
@@ -449,13 +439,13 @@ int main(int argc, char* argv[])
449439

450440
{
451441
TriclinicOps ops;
452-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
442+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
453443
ss.str("");
454444
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
455445
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
456446
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
457447

458-
legend = ops.generateIPFTriangleLegend(imageDim, false);
448+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
459449
ss.str("");
460450
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << ".png";
461451
result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
@@ -478,13 +468,13 @@ int main(int argc, char* argv[])
478468

479469
{
480470
MonoclinicOps ops;
481-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
471+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
482472
ss.str("");
483473
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
484474
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
485475
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
486476

487-
legend = ops.generateIPFTriangleLegend(imageDim, false);
477+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
488478
int yCropped = imageDim * 0.6F;
489479
legend = ebsdlib::CropRGBImage<uint8_t>(legend, imageDim, imageDim, 0, 0, imageDim, yCropped);
490480
ss.str("");
@@ -510,13 +500,13 @@ int main(int argc, char* argv[])
510500
{
511501
CubicLowOps ops;
512502

513-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
503+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
514504
ss.str("");
515505
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
516506
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
517507
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
518508

519-
legend = ops.generateIPFTriangleLegend(imageDim, false);
509+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
520510
ss.str("");
521511
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << ".png";
522512
result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
@@ -539,13 +529,13 @@ int main(int argc, char* argv[])
539529

540530
{
541531
CubicOps ops;
542-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
532+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
543533
ss.str("");
544534

545535
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
546536
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
547537
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
548-
legend = ops.generateIPFTriangleLegend(imageDim, false);
538+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
549539
ss.str("");
550540
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << ".png";
551541
result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
@@ -568,7 +558,7 @@ int main(int argc, char* argv[])
568558

569559
{
570560
OrthoRhombicOps ops;
571-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
561+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
572562
ss.str("");
573563
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
574564
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
@@ -578,7 +568,7 @@ int main(int argc, char* argv[])
578568
int yStart = 0;
579569
int numCols = imageDim * 0.78F;
580570
int numRows = imageDim * 0.6F;
581-
legend = ops.generateIPFTriangleLegend(imageDim, false);
571+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
582572
legend = ebsdlib::CropRGBImage<uint8_t>(legend, imageDim, imageDim, xStart, yStart, numCols, numRows);
583573
ss.str("");
584574
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << ".png";
@@ -602,7 +592,7 @@ int main(int argc, char* argv[])
602592

603593
{
604594
TetragonalOps ops;
605-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
595+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
606596
ss.str("");
607597

608598
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
@@ -613,7 +603,7 @@ int main(int argc, char* argv[])
613603
int yStart = 0;
614604
int numCols = imageDim * 0.78F;
615605
int numRows = imageDim * 0.6F;
616-
legend = ops.generateIPFTriangleLegend(imageDim, false);
606+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
617607
legend = ebsdlib::CropRGBImage<uint8_t>(legend, imageDim, imageDim, xStart, yStart, numCols, numRows);
618608
ss.str("");
619609
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << ".png";
@@ -637,13 +627,13 @@ int main(int argc, char* argv[])
637627

638628
{
639629
TetragonalLowOps ops;
640-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
630+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
641631
ss.str("");
642632
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
643633
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
644634
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
645635

646-
legend = ops.generateIPFTriangleLegend(imageDim, false);
636+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
647637
int xStart = imageDim * 0.10F;
648638
int yStart = 0;
649639
int numCols = imageDim * 0.70F;
@@ -671,13 +661,13 @@ int main(int argc, char* argv[])
671661

672662
{
673663
HexagonalOps ops;
674-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
664+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
675665
ss.str("");
676666
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
677667
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
678668
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
679669

680-
legend = ops.generateIPFTriangleLegend(imageDim, false);
670+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
681671
int xStart = imageDim * 0.10F;
682672
int yStart = 0;
683673
int numCols = imageDim * 0.80F;
@@ -705,13 +695,13 @@ int main(int argc, char* argv[])
705695

706696
{
707697
HexagonalLowOps ops;
708-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
698+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
709699
ss.str("");
710700
ss << k_Output_Dir << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
711701
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
712702
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
713703

714-
legend = ops.generateIPFTriangleLegend(imageDim, false);
704+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
715705
int xStart = imageDim * 0.10F;
716706
int yStart = 0;
717707
int numCols = imageDim * 0.70F;
@@ -739,13 +729,13 @@ int main(int argc, char* argv[])
739729

740730
{
741731
TrigonalLowOps ops;
742-
auto legend = ops.generateIPFTriangleLegend(imageDim, true);
732+
auto legend = ops.generateIPFTriangleLegend(imageDim, true, ebsdlib::HexConvention::XParallelAStar);
743733
ss.str("");
744734
ss << k_Output_Dir << ops.getSymmetryName() << "/" << EbsdStringUtils::replace(ops.getSymmetryName(), "/", "_") << "_FULL.png";
745735
auto result = PngWriter::WriteColorImage(ss.str(), imageDim, imageDim, 3, legend->getPointer(0));
746736
std::cout << ops.getSymmetryName() << " Result: " << result.first << ": " << result.second << std::endl;
747737

748-
legend = ops.generateIPFTriangleLegend(imageDim, false);
738+
legend = ops.generateIPFTriangleLegend(imageDim, false, ebsdlib::HexConvention::XParallelAStar);
749739
int xStart = imageDim * 0.00F;
750740
int yStart = 0;
751741
int numCols = imageDim * 0.90F;

Source/Apps/generate_pole_figure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ void generatePoleFiguresForPhase(const LaueOps& ops, unsigned int laueOpsIndex,
103103
std::string className = ops.getSymmetryName();
104104
std::cout << "Generating pole figures for phase: " << phaseLabel << " (" << className << ", " << eulers->getNumberOfTuples() << " orientations)" << std::endl;
105105

106-
auto poleFigureNames = ops.getDefaultPoleFigureNames();
106+
auto poleFigureNames = ops.getDefaultPoleFigureNames(ebsdlib::HexConvention::XParallelAStar);
107107

108108
PoleFigureConfiguration_t config;
109109
config.eulers = eulers;

0 commit comments

Comments
 (0)