|
6 | 6 |
|
7 | 7 | **Architecture:** The heavy lifting is consolidated into a single reusable LibMTRSim entry point `simulateMTR()` that runs PGRF → orientation sampling → per-voxel assignment and returns results in **SIMPLNX z,y,x voxel order**. LibMTRSim Catch2 tests (in `tests/`) cover the numerics (deterministic helpers + a statistical end-to-end test reusing the ODF exemplar). The filter is a thin SIMPLNX wrapper (`MTRSimFilter` + `MTRSim` algorithm) whose tests (in `test/`) only verify the filter's value-add: parameter→params mapping, ODF-geometry→component reconstruction, array creation/types/names/1-based ids, seed handling, preflight validation, and the optional color array. |
8 | 8 |
|
9 | | -**Tech Stack:** C++17, Eigen, simplnx filter framework, Catch2 v2 (note: `Catch::Approx`, not `Approx`), CMake, GitHub Actions. |
| 9 | +**Tech Stack:** C++17, Eigen, simplnx filter framework, Catch2 v2 (this repo uses the **bare `Approx`** matcher — `Approx` does NOT compile here), CMake, GitHub Actions. |
| 10 | + |
| 11 | +> **Correction applied during execution:** all Catch2 tests in this plan use |
| 12 | +> bare `Approx(...)`, not `Approx(...)`. The standalone LibMTRSim source |
| 13 | +> list is in `src/LibMTRSim/CMakeLists.txt` (not `LibMTRSim.cmake`). |
10 | 14 |
|
11 | 15 | --- |
12 | 16 |
|
@@ -69,7 +73,7 @@ simplnx checkout is at `/Users/mjackson/Workspace7/simplnx`): |
69 | 73 | - `src/app/main.cpp` — call `simulateMTR()` instead of inline orchestration. |
70 | 74 | - `MTRSimPlugin.cmake` — add `MTRSimDriver.{hpp,cpp}` to LibMTRSim sources; |
71 | 75 | add `MTRSimFilter`/`MTRSim` to `FilterList`/`AlgorithmList`. |
72 | | -- `LibMTRSim.cmake` — add `MTRSimDriver.{hpp,cpp}` to the standalone library. |
| 76 | +- `src/LibMTRSim/CMakeLists.txt` — add `MTRSimDriver.{hpp,cpp}` to the standalone library source/header lists. |
73 | 77 | - `tests/CMakeLists.txt` — add `test_mtrsim_driver.cpp`. |
74 | 78 | - `test/CMakeLists.txt` — add `MTRSimTest.cpp`. |
75 | 79 |
|
@@ -194,13 +198,13 @@ TEST_CASE("buildUniformODF produces correct bin centres", "[mtrsim_driver]") { |
194 | 198 | REQUIRE(uni.phi1Bins.size() == 72 * 36 * 72); |
195 | 199 |
|
196 | 200 | // Uniform mass: every bin equal, sums to 1. |
197 | | - REQUIRE(uni.odfVal.sum() == Catch::Approx(1.0)); |
198 | | - REQUIRE(uni.odfVal[0] == Catch::Approx(1.0 / (72.0 * 36.0 * 72.0))); |
| 201 | + REQUIRE(uni.odfVal.sum() == Approx(1.0)); |
| 202 | + REQUIRE(uni.odfVal[0] == Approx(1.0 / (72.0 * 36.0 * 72.0))); |
199 | 203 |
|
200 | 204 | // First bin centre: i1=iPHI=i2=0 -> all 0.5 * step. |
201 | | - REQUIRE(uni.phi1Bins[0] == Catch::Approx(0.5 * 2.0 * std::numbers::pi / 72.0)); |
202 | | - REQUIRE(uni.phiBins[0] == Catch::Approx(0.5 * std::numbers::pi / 36.0)); |
203 | | - REQUIRE(uni.phi2Bins[0] == Catch::Approx(0.5 * 2.0 * std::numbers::pi / 72.0)); |
| 205 | + REQUIRE(uni.phi1Bins[0] == Approx(0.5 * 2.0 * std::numbers::pi / 72.0)); |
| 206 | + REQUIRE(uni.phiBins[0] == Approx(0.5 * std::numbers::pi / 36.0)); |
| 207 | + REQUIRE(uni.phi2Bins[0] == Approx(0.5 * 2.0 * std::numbers::pi / 72.0)); |
204 | 208 | } |
205 | 209 | ``` |
206 | 210 |
|
@@ -266,12 +270,12 @@ TEST_CASE("gridToODFComponent derives bin centres in radians and normalizes", "[ |
266 | 270 | mtrsim::gridToODFComponent(values, n1, nPHI, n2, 5.0, 5.0, 5.0); |
267 | 271 |
|
268 | 272 | REQUIRE(c.odfVal.size() == n1 * nPHI * n2); |
269 | | - REQUIRE(c.odfVal.sum() == Catch::Approx(1.0)); // normalized |
| 273 | + REQUIRE(c.odfVal.sum() == Approx(1.0)); // normalized |
270 | 274 | // 5 deg step -> first bin centre 2.5 deg in radians. |
271 | 275 | const double deg2rad = std::numbers::pi / 180.0; |
272 | | - REQUIRE(c.phi1Bins[0] == Catch::Approx(2.5 * deg2rad)); |
273 | | - REQUIRE(c.phiBins[0] == Catch::Approx(2.5 * deg2rad)); |
274 | | - REQUIRE(c.phi2Bins[0] == Catch::Approx(2.5 * deg2rad)); |
| 276 | + REQUIRE(c.phi1Bins[0] == Approx(2.5 * deg2rad)); |
| 277 | + REQUIRE(c.phiBins[0] == Approx(2.5 * deg2rad)); |
| 278 | + REQUIRE(c.phi2Bins[0] == Approx(2.5 * deg2rad)); |
275 | 279 | } |
276 | 280 | ``` |
277 | 281 |
|
@@ -569,9 +573,9 @@ TEST_CASE("simulateMTR reproduces target volume fractions (statistical)", "[mtrs |
569 | 573 | // Empirical volume fractions within tolerance of targets. |
570 | 574 | std::array<int, 3> counts{0, 0, 0}; |
571 | 575 | for (int v : r.mtrIndex) { counts[v - 1]++; } |
572 | | - REQUIRE(static_cast<double>(counts[0]) / N == Catch::Approx(0.30).margin(0.05)); |
573 | | - REQUIRE(static_cast<double>(counts[1]) / N == Catch::Approx(0.35).margin(0.05)); |
574 | | - REQUIRE(static_cast<double>(counts[2]) / N == Catch::Approx(0.35).margin(0.05)); |
| 576 | + REQUIRE(static_cast<double>(counts[0]) / N == Approx(0.30).margin(0.05)); |
| 577 | + REQUIRE(static_cast<double>(counts[1]) / N == Approx(0.35).margin(0.05)); |
| 578 | + REQUIRE(static_cast<double>(counts[2]) / N == Approx(0.35).margin(0.05)); |
575 | 579 |
|
576 | 580 | // Euler ranges valid. |
577 | 581 | for (double a : r.phi1) { REQUIRE(a >= 0.0); REQUIRE(a <= 2.0 * std::numbers::pi); } |
@@ -1166,8 +1170,8 @@ TEST_CASE("MTRSimFilter: execute produces valid MTR ids + Eulers", "[MTRSim]") |
1166 | 1170 | counts[v - 1]++; |
1167 | 1171 | } |
1168 | 1172 | const double n = static_cast<double>(ids.getNumberOfTuples()); |
1169 | | - REQUIRE(counts[0] / n == Catch::Approx(0.30).margin(0.06)); |
1170 | | - REQUIRE(counts[1] / n == Catch::Approx(0.35).margin(0.06)); |
| 1173 | + REQUIRE(counts[0] / n == Approx(0.30).margin(0.06)); |
| 1174 | + REQUIRE(counts[1] / n == Approx(0.35).margin(0.06)); |
1171 | 1175 |
|
1172 | 1176 | // Seed array recorded. |
1173 | 1177 | auto& seedArr = ds.getDataRefAs<UInt64Array>(DataPath({"MTRSim SeedValue"})); |
|
0 commit comments