Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
4440594
BUG: Fix axis normalization typo in TrigonalLowOps::getMDFFZRod
imikejackson Jul 22, 2026
4046d27
BUG: Fix getMDFFZRod fundamental zone folds for six Laue classes
imikejackson Jul 22, 2026
e86bb6a
ENH: Implement getMDFFZRod for Triclinic/Monoclinic/OrthoRhombic + fu…
imikejackson Jul 22, 2026
a9b1cb3
ENH: Add de la Vallee Poussin SO(3) kernel class
imikejackson Jul 23, 2026
637636d
ENH: Add analytic random misorientation angle distribution
imikejackson Jul 23, 2026
1310090
ENH: Add misorientation kernel density estimator on the miso-bin grid
imikejackson Jul 23, 2026
353282b
ENH: Add MDF angle-distribution curve extraction to MisorientationKDE
imikejackson Jul 23, 2026
41fb464
TEST: Add correlated-twin MDF regression guard for MisorientationKDE
imikejackson Jul 23, 2026
e0993dd
STY: Add BSD headers to Texture MDF files, fix stale doc/comment/include
imikejackson Jul 23, 2026
b5ed6c6
BUG: (fix) Correct hexagonal MDF angle-distribution under-estimate at…
imikejackson Jul 24, 2026
eea4b63
BUG: Fix NaN ODF dimension constant in TetragonalLowOps
imikejackson Jul 24, 2026
fcaa1de
STY: Update clang-format version to 16
imikejackson Aug 18, 2026
4a56725
BUG: Use exact sqrt(3)/sqrt(2) normalizers in CubicOps::getSchmidFact…
imikejackson Aug 21, 2026
2c84f2a
BUG: Define every getSchmidFactorAndSS output on all paths
imikejackson Aug 21, 2026
539ddfc
TEST: Lock the stub Laue classes' Schmid outputs to zero
imikejackson Aug 21, 2026
754b74e
STY: Update clang-format version to 19
imikejackson Aug 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,28 @@ on:

jobs:
clang_format_pr:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 2
- name: Add Problem Matcher
uses: ammaraskar/gcc-problem-matcher@a141586609e2a558729b99a8c574c048f7f56204
- name: Install clang-format-19
run: |
sudo apt-get update
sudo apt-get install clang-format-19
clang-format-19 --version
- name: Check Formatting
id: check_format
continue-on-error: true
run: |
python3 scripts/clang_format.py --format-version 15 --commits HEAD^ HEAD
python3 scripts/clang_format.py --format-version 19 --commits HEAD^ HEAD
- name: Apply Formatting
if: steps.check_format.outcome != 'success'
run: |
python3 scripts/clang_format.py --format-version 15 --modify --commits HEAD^ HEAD
python3 scripts/clang_format.py --format-version 19 --modify --commits HEAD^ HEAD
- name: Add Suggestions
if: steps.check_format.outcome != 'success'
uses: reviewdog/action-suggester@v1
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/format_push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: clang-format

on:
push:
branches:
- develop
- master

jobs:
clang_format:
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@v2
- name: Add Problem Matcher
uses: ammaraskar/gcc-problem-matcher@a141586609e2a558729b99a8c574c048f7f56204
- name: Install clang-format-19
run: |
sudo apt-get update
sudo apt-get install clang-format-19
clang-format-19 --version
- name: Check Formatting
run: |
python3 scripts/clang_format.py --format-version 19
4 changes: 2 additions & 2 deletions Source/EbsdLib/Core/EbsdDataArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
#define EBSD_BYTE_SWAP_32(x) _byteswap_ulong(x)
#define EBSD_BYTE_SWAP_64(x) _byteswap_uint64(x)

#elif(defined(__clang__) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
#if(defined(__clang__) && __has_builtin(__builtin_bswap16)) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
#elif (defined(__clang__) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64)) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
#if (defined(__clang__) && __has_builtin(__builtin_bswap16)) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
#define EBSD_BYTE_SWAP_16(x) __builtin_bswap16(x)
#else
#define EBSD_BYTE_SWAP_16(x) __builtin_bswap32((x) << 16)
Expand Down
4 changes: 2 additions & 2 deletions Source/EbsdLib/Core/EbsdLibDLLExport.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ building on Windows.
#if defined(EbsdLib_EXPORTS) /* Compiling the EbsdLib DLL/Dylib */
#if defined(_MSC_VER) /* MSVC Compiler Case */
#define EbsdLib_EXPORT __declspec(dllexport)
#elif(__GNUC__ >= 4) /* GCC 4.x has support for visibility options */
#elif (__GNUC__ >= 4) /* GCC 4.x has support for visibility options */
#define EbsdLib_EXPORT __attribute__((visibility("default")))
#endif
#else /* Importing the DLL into another project */
#if defined(_MSC_VER) /* MSVC Compiler Case */
#define EbsdLib_EXPORT __declspec(dllimport)
#elif(__GNUC__ >= 4) /* GCC 4.x has support for visibility options */
#elif (__GNUC__ >= 4) /* GCC 4.x has support for visibility options */
#define EbsdLib_EXPORT __attribute__((visibility("default")))
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions Source/EbsdLib/IO/HKL/H5CtfImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ int H5CtfImporter::writeSliceData(hid_t fileId, CtfReader& reader, int z, int ac
if(nullptr == dataPtr)
{
assert(false);
} // We are going to crash here. I would rather crash than have bad data
} // We are going to crash here. I would rather crash than have bad data
dataPtr = dataPtr + (actualSlice * dims[0]); // Put the pointer at the proper offset into the larger array
WRITE_EBSD_DATA_ARRAY(reader, int, gid, name);
}
Expand All @@ -342,7 +342,7 @@ int H5CtfImporter::writeSliceData(hid_t fileId, CtfReader& reader, int z, int ac
if(nullptr == dataPtr)
{
assert(false);
} // We are going to crash here. I would rather crash than have bad data
} // We are going to crash here. I would rather crash than have bad data
dataPtr = dataPtr + (actualSlice * dims[0]); // Put the pointer at the proper offset into the larger array
WRITE_EBSD_DATA_ARRAY(reader, float, gid, name);
}
Expand Down
46 changes: 12 additions & 34 deletions Source/EbsdLib/LaueOps/CubicLowOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,48 +316,26 @@ RodriguesDType CubicLowOps::getMDFFZRod(const RodriguesDType& inRod) const
double n1 = ax[0];
double n2 = ax[1], n3 = ax[2], w = ax[3];

double FZn1 = w, FZn2 = 0.0, FZn3 = 0.0, FZw = 0.0;
double FZn1 = 0.0, FZn2 = 0.0, FZn3 = 0.0;
double FZw = w;

n1 = fabs(n1);
n2 = fabs(n2);
n3 = fabs(n3);
if(n1 > n2)
// The tetrahedral rotation group only provides the <111> 3-fold axes, so only
// cyclic permutations of the axis components are symmetry-equivalent. Rotate
// cyclically so the largest component is first; n2/n3 must NOT be sorted.
if(n2 >= n1 && n2 >= n3)
{
if(n1 > n3)
{
FZn1 = n1;
if(n2 > n3)
{
FZn2 = n2, FZn3 = n3;
}
else
{
FZn2 = n3, FZn3 = n2;
}
}
else
{
FZn1 = n3, FZn2 = n1, FZn3 = n2;
}
FZn1 = n2, FZn2 = n3, FZn3 = n1;
}
else if(n3 >= n1 && n3 >= n2)
{
FZn1 = n3, FZn2 = n1, FZn3 = n2;
}
else
{
if(n2 > n3)
{
FZn1 = n2;
if(n1 > n3)
{
FZn2 = n1, FZn3 = n3;
}
else
{
FZn2 = n3, FZn3 = n1;
}
}
else
{
FZn1 = n3, FZn2 = n2, FZn3 = n1;
}
FZn1 = n1, FZn2 = n2, FZn3 = n3;
}

return AxisAngleDType(FZn1, FZn2, FZn3, FZw).toRodrigues();
Expand Down
20 changes: 10 additions & 10 deletions Source/EbsdLib/LaueOps/CubicOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -846,25 +846,25 @@ void CubicOps::getSchmidFactorAndSS(double load[3], double& schmidfactor, double

double mag = loadx * loadx + loady * loady + loadz * loadz;
mag = std::sqrt(mag);
theta1 = (loadx + loady + loadz) / (mag * 1.732f);
theta1 = (loadx + loady + loadz) / (mag * ebsdlib::constants::k_Sqrt3D);
theta1 = std::fabs(theta1);
theta2 = (loadx + loady - loadz) / (mag * 1.732f);
theta2 = (loadx + loady - loadz) / (mag * ebsdlib::constants::k_Sqrt3D);
theta2 = std::fabs(theta2);
theta3 = (loadx - loady + loadz) / (mag * 1.732f);
theta3 = (loadx - loady + loadz) / (mag * ebsdlib::constants::k_Sqrt3D);
theta3 = std::fabs(theta3);
theta4 = (-loadx + loady + loadz) / (mag * 1.732f);
theta4 = (-loadx + loady + loadz) / (mag * ebsdlib::constants::k_Sqrt3D);
theta4 = std::fabs(theta4);
lambda1 = (loadx + loady) / (mag * 1.414f);
lambda1 = (loadx + loady) / (mag * ebsdlib::constants::k_Sqrt2D);
lambda1 = std::fabs(lambda1);
lambda2 = (loadx + loadz) / (mag * 1.414f);
lambda2 = (loadx + loadz) / (mag * ebsdlib::constants::k_Sqrt2D);
lambda2 = std::fabs(lambda2);
lambda3 = (loadx - loady) / (mag * 1.414f);
lambda3 = (loadx - loady) / (mag * ebsdlib::constants::k_Sqrt2D);
lambda3 = std::fabs(lambda3);
lambda4 = (loadx - loadz) / (mag * 1.414f);
lambda4 = (loadx - loadz) / (mag * ebsdlib::constants::k_Sqrt2D);
lambda4 = std::fabs(lambda4);
lambda5 = (loady + loadz) / (mag * 1.414f);
lambda5 = (loady + loadz) / (mag * ebsdlib::constants::k_Sqrt2D);
lambda5 = std::fabs(lambda5);
lambda6 = (loady - loadz) / (mag * 1.414f);
lambda6 = (loady - loadz) / (mag * ebsdlib::constants::k_Sqrt2D);
lambda6 = std::fabs(lambda6);
schmid1 = theta1 * lambda6;
schmid2 = theta1 * lambda4;
Expand Down
31 changes: 15 additions & 16 deletions Source/EbsdLib/LaueOps/HexagonalLowOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,24 +386,14 @@ RodriguesDType HexagonalLowOps::getMDFFZRod(const RodriguesDType& inRod) const
FZn1 = n1;
FZn2 = n2;
FZn3 = n3;
if(angle > 30.0)
// The 6/m rotation group is only the 6-fold about c (no in-plane 2-folds), so the
// axis azimuth folds into a plain 60 degree wedge with no mirror alternation
{
n1n2mag = std::sqrt(n1 * n1 + n2 * n2);
if(int(angle / 30) % 2 == 0)
{
FZw = angle - (30.0 * int(angle / 30.0));
FZw = FZw * ebsdlib::constants::k_PiOver180D;
FZn1 = n1n2mag * std::cos(FZw);
FZn2 = n1n2mag * std::sin(FZw);
}
else
{
FZw = angle - (30.0 * int(angle / 30.0));
FZw = 30.0f - FZw;
FZw = FZw * ebsdlib::constants::k_PiOver180D;
FZn1 = n1n2mag * std::cos(FZw);
FZn2 = n1n2mag * std::sin(FZw);
}
FZw = std::fmod(static_cast<double>(angle), 60.0);
FZw = FZw * ebsdlib::constants::k_PiOver180D;
FZn1 = n1n2mag * std::cos(FZw);
FZn2 = n1n2mag * std::sin(FZw);
}

return AxisAngleDType(FZn1, FZn2, FZn3, w).toRodrigues();
Expand Down Expand Up @@ -532,6 +522,15 @@ int HexagonalLowOps::getOdfBin(const RodriguesDType& rod) const

void HexagonalLowOps::getSchmidFactorAndSS(double load[3], double& schmidfactor, double angleComps[2], int& slipsys) const
{
// Every output must be defined before the schmid comparison chain below, which only assigns to
// them when a candidate beats the incumbent. Without these, schmidfactor was READ uninitialized
// by the first `if(schmid1 > schmidfactor)`, and slipsys/angleComps were left untouched whenever
// no candidate won.
schmidfactor = 0.0;
slipsys = 0;
angleComps[0] = 0.0;
angleComps[1] = 0.0;

double theta1, theta2, theta3, theta4, theta5, theta6, theta7, theta8, theta9;
double lambda1, lambda2, lambda3, lambda4, lambda5, lambda6, lambda7, lambda8, lambda9, lambda10;
double schmid1, schmid2, schmid3, schmid4, schmid5, schmid6;
Expand Down
11 changes: 9 additions & 2 deletions Source/EbsdLib/LaueOps/HexagonalOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ namespace HexagonalHigh
{
constexpr std::array<size_t, 3> k_OdfNumBins = {36, 36, 12}; // Represents a 5Deg bin in homochoric space

static const std::array<double, 3> k_OdfDimInitValue = {std::pow((0.75 * (((ebsdlib::constants::k_PiOver2D)) - std::sin(((ebsdlib::constants::k_PiOver2D))))), (1.0 / 3.0)),
std::pow((0.75 * (((ebsdlib::constants::k_PiOver2D)) - std::sin(((ebsdlib::constants::k_PiOver2D))))), (1.0 / 3.0)),
static const std::array<double, 3> k_OdfDimInitValue = {std::pow((0.75 * (((ebsdlib::constants::k_PiOver2D))-std::sin(((ebsdlib::constants::k_PiOver2D))))), (1.0 / 3.0)),
std::pow((0.75 * (((ebsdlib::constants::k_PiOver2D))-std::sin(((ebsdlib::constants::k_PiOver2D))))), (1.0 / 3.0)),
std::pow((0.75 * ((ebsdlib::constants::k_PiD / 6.0) - std::sin(ebsdlib::constants::k_PiD / 6.0))), (1.0 / 3.0))};
static const std::array<double, 3> k_OdfDimStepValue = {k_OdfDimInitValue[0] / static_cast<double>(k_OdfNumBins[0] / 2), k_OdfDimInitValue[1] / static_cast<double>(k_OdfNumBins[1] / 2),
k_OdfDimInitValue[2] / static_cast<double>(k_OdfNumBins[2] / 2)};
Expand Down Expand Up @@ -610,7 +610,14 @@ int HexagonalOps::getOdfBin(const RodriguesDType& rod) const

void HexagonalOps::getSchmidFactorAndSS(double load[3], double& schmidfactor, double angleComps[2], int& slipsys) const
{
// schmidfactor was already seeded here, but slipsys and angleComps were not: the comparison chain
// below only assigns to them when a candidate beats the incumbent, so a load direction for which
// every candidate is 0 left both outputs holding whatever the caller passed in.
schmidfactor = 0.0;
slipsys = 0;
angleComps[0] = 0.0;
angleComps[1] = 0.0;

double theta1, theta2, theta3, theta4, theta5, theta6, theta7, theta8, theta9;
double lambda1, lambda2, lambda3, lambda4, lambda5, lambda6, lambda7, lambda8, lambda9, lambda10;
double schmid1, schmid2, schmid3, schmid4, schmid5, schmid6;
Expand Down
41 changes: 29 additions & 12 deletions Source/EbsdLib/LaueOps/MonoclinicOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,19 +247,31 @@ RodriguesDType MonoclinicOps::getODFFZRod(const RodriguesDType& rod) const
// -----------------------------------------------------------------------------
RodriguesDType MonoclinicOps::getMDFFZRod(const RodriguesDType& inRod) const
{
throw ebsdlib::method_not_implemented("MonoclinicOps::getMDFFZRod not implemented");
// /// FIXME: Are we missing code for MonoclinicOps MDF FZ Rodrigues calculation?
RodriguesDType rod = LaueOps::_calcRodNearestOrigin(inRod);
AxisAngleDType ax = rod.toAxisAngle();

// double w = 0.0, n1 = 0.0, n2 = 0.0, n3 = 0.0;
// double FZw = 0.0, FZn1 = 0.0, FZn2 = 0.0, FZn3 = 0.0;
//
// OrientationType rod = LaueOps::_calcRodNearestOrigin(inRod);
// AxisAngleDType ax = rod.toAxisAngle();
// n1 = ax[0];
// n2 = ax[1], n3 = ax[2], w = ax[3];
//
//
// return AxisAngleDType(FZn1, FZn2, FZn3, FZw).toRodrigues();
// The 2/m rotation group is the single 2-fold about b (Y). Conjugation maps the
// misorientation axis (n1, n2, n3) to (-n1, n2, -n3) and switching symmetry
// negates it, so the fundamental sector is n2 >= 0 and n3 >= 0 with n1 free.
if(ax[1] < 0.0)
{
// combined 2-fold conjugation + switching: flips n2 only
ax[1] = -ax[1];
}
if(ax[2] < 0.0)
{
// 2-fold conjugation: flips n1 and n3, leaves n2
ax[0] = -ax[0];
ax[2] = -ax[2];
}
else if(ax[2] == 0.0 && ax[0] < 0.0)
{
// Equator tie-break: the 2-fold conjugation still relates (n1, n2, 0) and
// (-n1, n2, 0); pick the half-plane with n1 >= 0
ax[0] = -ax[0];
}

return AxisAngleDType(ax[0], ax[1], ax[2], ax[3]).toRodrigues();
}

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -386,8 +398,13 @@ int MonoclinicOps::getOdfBin(const RodriguesDType& rod) const

void MonoclinicOps::getSchmidFactorAndSS(double load[3], double& schmidfactor, double angleComps[2], int& slipsys) const
{
// No slip systems are enumerated for this Laue class. Zero EVERY output, angleComps
// included: leaving them untouched handed the caller back whatever it passed in, which for
// a caller that reuses one angleComps buffer across a loop is the PREVIOUS entry's angles.
schmidfactor = 0;
slipsys = 0;
angleComps[0] = 0;
angleComps[1] = 0;
}

void MonoclinicOps::getSchmidFactorAndSS(double load[3], double plane[3], double direction[3], double& schmidfactor, double angleComps[2], int& slipsys) const
Expand Down
20 changes: 9 additions & 11 deletions Source/EbsdLib/LaueOps/OrthoRhombicOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,20 +258,13 @@ RodriguesDType OrthoRhombicOps::getODFFZRod(const RodriguesDType& rod) const
// -----------------------------------------------------------------------------
RodriguesDType OrthoRhombicOps::getMDFFZRod(const RodriguesDType& inRod) const
{
throw ebsdlib::method_not_implemented("OrthoRhombicOps::getMDFFZRod not implemented");

double FZn1 = 0.0f, FZn2 = 0.0f, FZn3 = 0.0f, FZw = 0.0f;

RodriguesDType rod = _calcRodNearestOrigin(inRod);
AxisAngleDType ax = rod.toAxisAngle();
// double n1 = ax[0];
// double n2 = ax[1];
// double n3 = ax[2];
// double w = ax[3];

/// FIXME: Are we missing code for OrthoRhombic MDF FZ Rodrigues calculation?

return AxisAngleDType(FZn1, FZn2, FZn3, FZw).toRodrigues();
// The 222 rotation group's three orthogonal 2-folds combined with switching
// symmetry generate every sign combination of the misorientation axis, so the
// fundamental sector is the first octant.
return AxisAngleDType(std::fabs(ax[0]), std::fabs(ax[1]), std::fabs(ax[2]), ax[3]).toRodrigues();
}

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -397,8 +390,13 @@ int OrthoRhombicOps::getOdfBin(const RodriguesDType& rod) const

void OrthoRhombicOps::getSchmidFactorAndSS(double load[3], double& schmidfactor, double angleComps[2], int& slipsys) const
{
// No slip systems are enumerated for this Laue class. Zero EVERY output, angleComps
// included: leaving them untouched handed the caller back whatever it passed in, which for
// a caller that reuses one angleComps buffer across a loop is the PREVIOUS entry's angles.
schmidfactor = 0;
slipsys = 0;
angleComps[0] = 0;
angleComps[1] = 0;
}

void OrthoRhombicOps::getSchmidFactorAndSS(double load[3], double plane[3], double direction[3], double& schmidfactor, double angleComps[2], int& slipsys) const
Expand Down
Loading
Loading