Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "scikit_build_core.build"

[project]
name = "pyvale"
version = "2026.10.0"
version = "2026.10.1"
description = "Your virtual engineering lab: An all-in-one package for simulation-driven experimental design."
authors = [
{ name = "scepticalrabbit et al.", email = "[email protected]" },
Expand Down
2 changes: 1 addition & 1 deletion src/pyvale/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
virtually testing digital shadows/twins.
"""

__version__ = "2026.9.0"
__version__ = "2026.10.1"

from . import data, dataio, dic, mooseherder, render, sensorsim, strain

Expand Down
17 changes: 17 additions & 0 deletions src/pyvale/dic/cpp/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <cstring>
#include <stdexcept>
#include <type_traits>
#include <algorithm>

// commoncpp Header Files
#include "../../commoncpp/util.hpp"
Expand Down Expand Up @@ -174,6 +175,22 @@ PYBIND11_MODULE(diccpp, m) {
engine_images(images_from_sequence(image_arrays, conf), img_roi_arr, calib, conf, multiwindowconf, saveconf);
}, "Run DIC analysis on in-memory image arrays with config");

m.def("_should_update_ref", [](int image_number,
const std::vector<int>& iterations,
const std::vector<double>& costs,
util::EIncrementalCond condition,
double threshold) {
const int num_results = static_cast<int>(std::max(iterations.size(), costs.size()));
ResultArrays results(num_results, 0, false);
results.niter = iterations;
results.cost = costs;

util::Config config{};
config.incremental_update_cond = condition;
config.incremental_update_val = threshold;
return should_update_ref(image_number, results, config);
}, "Evaluate an incremental-reference update condition");

// interpolator bindings
py::class_<InterpVals>(m, "InterpVals")
.def_readonly("f", &InterpVals::f)
Expand Down
2 changes: 1 addition & 1 deletion src/pyvale/dic/cpp/dicmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ bool should_update_ref(const int img_num_def_l, const ResultArrays& results, con
if (results.cost.empty()) return false;

double avg = std::accumulate(results.cost.begin(), results.cost.end(), 0.0) / results.cost.size();
return avg > conf.incremental_update_val;
return avg < conf.incremental_update_val;
}

default:
Expand Down
40 changes: 40 additions & 0 deletions tests/dic/test_incremental.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Tests for incremental DIC reference-update conditions."""

import pytest

import pyvale.dic.diccpp as diccpp


@pytest.mark.parametrize(
("condition", "image_number", "iterations", "costs", "threshold", "expected"),
[
# The first deformed image never updates the reference.
("IMAGE", 1, [4], [0.5], 1, False),
("IMAGE", 2, [4], [0.5], 1, True),
("IMAGE", 3, [4], [0.5], 2, True),
# COST updates only when the mean ZNCC cost is strictly below the threshold.
("COST", 2, [4, 4], [0.4, 0.6], 0.6, True),
("COST", 2, [4, 4], [0.4, 0.6], 0.5, False),
("COST", 2, [4, 4], [0.4, 0.6], 0.4, False),
# ITER updates only when the mean iteration count exceeds the threshold.
("ITER", 2, [4, 6], [0.5, 0.5], 4.9, True),
("ITER", 2, [4, 6], [0.5, 0.5], 5, False),
],
)
def test_incremental_update_conditions(
condition: str,
image_number: int,
iterations: list[int],
costs: list[float],
threshold: float,
expected: bool,
) -> None:
result = diccpp._should_update_ref(
image_number,
iterations,
costs,
getattr(diccpp.IncrementalCond, condition),
threshold,
)

assert result is expected
Loading