Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
251b538
chore: enforce C++17, document CMake options
johnaoga Jun 16, 2026
4bc4ee1
feat(ncorr): audit CLI; stub missing post-DIC output flags
johnaoga Jun 16, 2026
6aafea2
fix(input/images): harden image-folder reader edge cases
johnaoga Jun 16, 2026
f241076
feat(input/memory): add in-memory NcorrSession API (stub)
johnaoga Jun 16, 2026
9c31435
feat(params): implement CLI > config-file > compiled-defaults overrid…
johnaoga Jun 16, 2026
b2bf99c
docs(tests): add TESTS_PLAN.md — awaiting confirmation before impleme…
johnaoga Jun 16, 2026
ea1d73e
refactor(input/images): extract frame-reader helpers into reusable he…
johnaoga Jun 16, 2026
6634af9
test(unit): add Catch2 v3 suite for ini/config/frame_reader/session
johnaoga Jun 16, 2026
7e5f89b
test(integration): add DIC pipeline-stage tests on ohtcfrp fixture
johnaoga Jun 16, 2026
417b89c
test(e2e): add ohtcfrp end-to-end regression guard with golden baseline
johnaoga Jun 16, 2026
fb7eb2a
docs: add quickstart guide
johnaoga Jun 16, 2026
4af29db
docs: add developer guide
johnaoga Jun 16, 2026
87585d4
docs: add user guide
johnaoga Jun 16, 2026
cfc0640
chore(deploy): organise parallel/cluster/Docker scripts under deploy/
johnaoga Jun 16, 2026
8273d66
ci: add GitHub Actions workflow for build, test, lint
johnaoga Jun 16, 2026
e2d3de5
docs: add PR description for newversion (local, not yet opened)
johnaoga Jun 16, 2026
43f035b
feat(input/memory): implement in-memory NcorrSession DIC
johnaoga Jun 16, 2026
b5799aa
test(session): real in-memory DIC parity test; move session tests to …
johnaoga Jun 16, 2026
e9f117b
feat(proxyncorr): lagrangian perspective + strain CSV export; clean u…
johnaoga Jun 16, 2026
01b6e81
feat(matlab-dic): fixed-step reference updates (fixed_step_ref option)
johnaoga Jul 7, 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
18 changes: 18 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# clang-format configuration for CppNCorr.
# Applies to new code on the newversion branch; CI lints only changed files so
# the large legacy headers are not reformatted wholesale.
---
Language: Cpp
BasedOnStyle: Google
ColumnLimit: 100
IndentWidth: 4
TabWidth: 4
UseTab: Never
AccessModifierOffset: -2
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: WithoutElse
DerivePointerAlignment: false
PointerAlignment: Left
SortIncludes: false
SpacesBeforeTrailingComments: 2
...
15 changes: 15 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Keep the Docker build context small and reproducible: never ship local build
# trees, fetched dependency caches, or editor/OS cruft into the image.
build
build_tests
test/build
test/bin
lib/libncorr.a
lib/libCatch2.a
lib/libCatch2Main.a
**/.DS_Store
.git
.cache
compile_commands.json
test/examples/ohtcfrp/save/
test/examples/ohtcfrp/video/
110 changes: 110 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: CI

# Build, test and lint CppNCorr. Triggered on pushes and pull requests targeting
# main and newversion. Kept deliberately fast: GCC on ubuntu-latest, system
# dependencies from apt (no GPU, no large dataset downloads, no source builds of
# OpenCV etc.).
on:
push:
branches: [main, newversion]
pull_request:
branches: [main, newversion]

# Cancel superseded runs on the same ref to save CI minutes.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

env:
DEBIAN_FRONTEND: noninteractive
# CMake >= 3.21 on the runner sets PROJECT_IS_TOP_LEVEL automatically.
CMAKE_ARGS: -DCMAKE_POLICY_VERSION_MINIMUM=3.5

jobs:
build:
name: build (gcc, ubuntu-latest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake \
libopencv-dev libfftw3-dev libsuitesparse-dev \
libopenblas-dev liblapack-dev nlohmann-json3-dev libomp-dev

- name: Configure (top-level, tests enabled)
run: cmake -S . -B build $CMAKE_ARGS

- name: Build library + tests
run: cmake --build build -j "$(nproc)"

test:
name: test (unit + integration via ctest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake \
libopencv-dev libfftw3-dev libsuitesparse-dev \
libopenblas-dev liblapack-dev nlohmann-json3-dev libomp-dev

- name: Configure
run: cmake -S . -B build $CMAKE_ARGS

- name: Build test targets
run: cmake --build build --target ncorr_unit_tests ncorr_engine_tests -j "$(nproc)"

- name: Run unit tests (fast)
working-directory: build
run: ctest --output-on-failure -L unit

- name: Run integration tests (ohtcfrp)
working-directory: build
env:
OMP_NUM_THREADS: "2"
# Integration DIC is compute-heavy; give it a generous timeout. The very
# slow end-to-end cases (label "e2e") are excluded here to keep CI fast —
# they run locally / on demand (see docs/developer_guide.md).
run: ctest --output-on-failure --timeout 1200 -L integration

lint:
name: lint (clang-format on changed files)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends clang-format

- name: clang-format --dry-run on changed C/C++ files
run: |
# Determine the base ref to diff against.
if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE="origin/${{ github.base_ref }}"
git fetch origin "${{ github.base_ref }}" || true
else
BASE="${{ github.event.before }}"
fi
# Lint files ADDED on this branch (diff-filter=A). Pre-existing legacy
# files that only received small edits are intentionally not reformatted
# wholesale; the .clang-format style applies to new code on this branch.
CHANGED=$(git diff --name-only --diff-filter=A "$BASE" HEAD 2>/dev/null \
| grep -E '\.(c|cc|cpp|cxx|h|hpp)$' || true)
if [ -z "$CHANGED" ]; then
echo "No newly added C/C++ files to lint."
exit 0
fi
echo "Linting:"; echo "$CHANGED"
# --dry-run --Werror fails if any file is not formatted.
clang-format --dry-run --Werror $CHANGED
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
lib/libncorr.a
lib/libCatch2.a
lib/libCatch2Main.a
build
build_tests
test/bin
test/examples/ohtcfrp/save/
test/examples/ohtcfrp/video/
Expand Down
43 changes: 41 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.14)
PROJECT(ncorr_library)

# Enforce C++17 project-wide (required for std::optional and modern features).
# Setting these before any target guarantees every target inherits the standard,
# in addition to the per-target properties set further down.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Include FetchContent fallbacks for systems without root access
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(FetchDependencies)
Expand All @@ -13,8 +20,8 @@ option(FORCE_FETCH_DEPENDENCIES "Force using FetchContent for all dependencies"
# included, since the install directories are searched automatically by g++.

# Set files
SET(ncorr_src src/ncorr.cpp src/Strain2D.cpp src/Disp2D.cpp src/Data2D.cpp src/ROI2D.cpp src/Image2D.cpp src/Array2D.cpp)
SET(ncorr_h include/ncorr.h include/Strain2D.h include/Disp2D.h include/Data2D.h include/ROI2D.h include/Image2D.h include/Array2D.h)
SET(ncorr_src src/ncorr.cpp src/Strain2D.cpp src/Disp2D.cpp src/Data2D.cpp src/ROI2D.cpp src/Image2D.cpp src/Array2D.cpp src/session.cpp src/config.cpp)
SET(ncorr_h include/ncorr.h include/Strain2D.h include/Disp2D.h include/Data2D.h include/ROI2D.h include/Image2D.h include/Array2D.h include/ncorr/session.h include/ncorr/config.h include/ncorr/ini.h)

# Set include directory
INCLUDE_DIRECTORIES(include)
Expand Down Expand Up @@ -97,3 +104,35 @@ ADD_DEFINITIONS(-DNDEBUG)
# Install library
INSTALL(TARGETS ncorr DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/lib)
INSTALL(FILES ${ncorr_h} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/include)

# ============================================================================
# Tests (section 5b) — Catch2 v3 via FetchContent.
# ----------------------------------------------------------------------------
# CRITICAL: all test infrastructure (Catch2 FetchContent, enable_testing(),
# test targets, add_test/CTest) is gated so it ONLY activates when CppNCorr is
# the TOP-LEVEL project. The parent CPPxDIC project does
# add_subdirectory(Tools/CppNCorr); without this guard the test/Catch2 logic
# would leak into and break the parent build.
#
# PROJECT_IS_TOP_LEVEL is set automatically by project() on CMake >= 3.21; for
# older CMake we derive it by comparing the source/binary dirs.
# ============================================================================
if(NOT DEFINED PROJECT_IS_TOP_LEVEL)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(PROJECT_IS_TOP_LEVEL ON)
else()
set(PROJECT_IS_TOP_LEVEL OFF)
endif()
endif()

# BUILD_TESTING defaults ON only when CppNCorr is top-level. When pulled in as a
# subdirectory it defaults OFF so the parent is never affected.
option(BUILD_TESTING "Build the CppNCorr test suite (Catch2)" ${PROJECT_IS_TOP_LEVEL})

if(PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
message(STATUS "CppNCorr: top-level build with testing enabled — configuring Catch2 test suite")
enable_testing()
include(${CMAKE_CURRENT_SOURCE_DIR}/test/tests.cmake)
else()
message(STATUS "CppNCorr: tests skipped (PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}, BUILD_TESTING=${BUILD_TESTING})")
endif()
100 changes: 100 additions & 0 deletions CMakeOptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# CppNCorr CMake Options & Build Reference

This document describes every CMake option, language requirement, and dependency
handling rule used by the CppNCorr build. It complements `CMakeLists.txt` (the
library) and `test/CMakeLists.txt` (the example/tool executables).

## Language standard

CppNCorr requires **C++17** (it relies on `std::optional` and other modern
features). The standard is enforced project-wide in the top of `CMakeLists.txt`:

```cmake
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
```

and is additionally pinned on the `ncorr` target via `set_property(... CXX_STANDARD 17)`.
`test/CMakeLists.txt` sets the same global variables before defining its targets.

- **Minimum CMake**: 3.14 (declared via `CMAKE_MINIMUM_REQUIRED`).
- **Compilers**: GCC 10+ / Clang 12+ / MSVC 2019+ (mirrors CPPxDIC).

## User-configurable options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `FORCE_FETCH_DEPENDENCIES` | BOOL | `OFF` | When `ON`, ignore system-installed packages and build **all** third-party dependencies from source via CMake `FetchContent`. Useful for reproducible builds and on machines without root / package-manager access. When `OFF` (default), each dependency is first searched with `find_package` / `find_library` and only fetched if missing. |

Pass options on the command line, e.g.:

```bash
cmake -S . -B build -DFORCE_FETCH_DEPENDENCIES=ON
```

## Compile flags applied by the build

| Flag / definition | Where | Purpose |
|-------------------|-------|---------|
| `-O3` | both | Added when the compiler supports it (probed with `CheckCXXCompilerFlag`). |
| `-Wall -Wextra` | library (`target_compile_options(ncorr ...)`) | Warning hygiene for the core library. |
| `-DNDEBUG` | both (`ADD_DEFINITIONS`) | Disables `assert()` in release builds. |
| `-isystem /opt/homebrew/include` | APPLE only | Silences warnings from Homebrew system headers. |

## Targets

| Target | Defined in | Type | Notes |
|--------|------------|------|-------|
| `ncorr` | `CMakeLists.txt` | STATIC library | Core DIC engine → `lib/libncorr.a`. |
| `proxyncorr` | `test/CMakeLists.txt` | executable | The de-facto **main DIC tool**: folder discovery, full CLI (getopt), config file, JSON/binary/video output. Used by the parent CPPxDIC project. |
| `ncorr_test` | `test/CMakeLists.txt` | executable | Minimal end-to-end example on the `ohtcfrp` dataset. |
| `ncorr_test_*`, `*_test` | `test/CMakeLists.txt` | executables | Assorted regression/unit-style harnesses (interpolator, cubic, parity, RGDIC, sequential, parallel, chain seam, ROI reduce, etc.). |

## Dependencies (resolved by `cmake/FetchDependencies.cmake`)

Each dependency is found on the system first; if missing (or when
`FORCE_FETCH_DEPENDENCIES=ON`) it is fetched and built from source. The pinned
fetch versions are:

| Dependency | Role | System lookup | Fetch tag/version |
|------------|------|---------------|-------------------|
| **OpenCV** | image / video I/O, image processing | `find_package(OpenCV)` (+ `opencv4` include hints on Debian/Ubuntu) | 4.9.0 (minimal `core,imgproc,imgcodecs,highgui,videoio` build) |
| **FFTW3** | FFT routines | `find_library(fftw3)` + `fftw3.h` | 3.3.10 |
| **SuiteSparse** | sparse solvers (SPQR, CHOLMOD, AMD, COLAMD, config) | `find_library(spqr/cholmod/...)` | v7.6.0 |
| **BLAS / LAPACK** | dense linear algebra (SuiteSparse backend) | `find_package(BLAS/LAPACK)` | OpenBLAS v0.3.26 (fallback) |
| **nlohmann/json** | JSON output (header-only) | `find_package(nlohmann_json CONFIG)` | v3.11.3 |
| **OpenMP** | parallelism | `find_package(OpenMP)` (Homebrew `libomp` paths on macOS) | system only (not fetched) |

> The `FORCE`-flagged `set(... CACHE ...)` lines inside `FetchDependencies.cmake`
> (e.g. `WITH_CUDA OFF`, `BUILD_TESTS OFF`) are **internal** build-tuning for the
> fetched dependency sub-builds. They are not meant to be set by users.

## Quick build

```bash
# Library only
cmake -S . -B build -DCMAKE_POLICY_VERSION_MINIMUM=3.5
cmake --build build --target ncorr -j

# Executables (proxyncorr, ncorr_test, ...) — configure the test/ tree
cmake -S test -B test/build -DCMAKE_POLICY_VERSION_MINIMUM=3.5
cmake --build test/build -j
```

The convenience script `build.sh` performs the library build (clean + configure +
make) and refreshes `lib/libncorr.a`.

## Known pre-existing warnings

The header `include/Array2D.h` emits a handful of `-Wall -Wextra` warnings that
predate this work and are intrinsic to its template iterator design:

- `-Winjected-class-name` on qualified iterator definitions.
- `-Wunused-parameter` for the `type` tag parameter of `eye(...)`.
- `-Wdeprecated-declarations` for `allocator::rebind<bool>`.

These are non-fatal and are left untouched to avoid risky edits to the large
template header; they are tracked with `// FIXME(newversion):` markers where it
is safe to annotate. New code added on this branch compiles cleanly under
`-Wall -Wextra`.
Loading