Skip to content

Comments

Fixes #1863 remove check for monotonically increasing time values?#2764

Merged
rwmcintosh merged 7 commits intodevelopfrom
1863-remove-check-for-monotonically-increasing-time-values
Feb 5, 2026
Merged

Fixes #1863 remove check for monotonically increasing time values?#2764
rwmcintosh merged 7 commits intodevelopfrom
1863-remove-check-for-monotonically-increasing-time-values

Conversation

@rwmcintosh
Copy link
Member

@rwmcintosh rwmcintosh commented Feb 4, 2026

Fixes #1863 remove check for monotonically increasing time values?

Description

Relatively few fires created from what I can see.

Type of change

Please mark relevant options with an x in the brackets.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires documentation changes (link at least one user or developer documentation issue):
  • Algorithm update - updates algorithm documentation/questions/answers etc.
  • Other (please describe):

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Integration tests
  • Unit tests
  • Manual tests
  • No tests required

Reviewer checklist

Mark everything that needs to be checked before merging the PR.

  • Check if the code is well documented
  • Check if the behavior is what is expected
  • Check if the code is well tested
  • Check if the code is readable and well formatted
  • Additional checks (document below if any)
  • Check if documentation update issue(s) are created if the option This change requires a documentation update above is selected

Screenshots (if appropriate):

Questions (if appropriate):

Summary by CodeRabbit

  • User Experience

    • Improved chart tooltip detection and resolution for more accurate tooltips.
  • Bug Fixes

    • Interpolation now averages values across matching grid points for more consistent results.
  • Breaking Changes

    • Removed bulk data-manipulation and public mutation APIs (insert/swap).
    • Grids no longer enforce strict increasing order; duplicates/non-monotonic values accepted.
    • A specialized "time not strictly monotone" exception and sheet-name enrichment on import errors were removed.

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

Removed strict monotonicity checks and related APIs in BaseGrid, changed index-lookup semantics and averaging in DataColumn, deleted TimeNotStrictlyMonotoneException and its wrapping, refactored chart tooltip logic to ChartHitInfo, removed repository insert/swap APIs, and updated/removed tests accordingly.

Changes

Cohort / File(s) Summary
Core Grid & Column
src/OSPSuite.Core/Domain/Data/BaseGrid.cs, src/OSPSuite.Core/Domain/Data/DataColumn.cs
BaseGrid: added parameterless ctor, removed monotonicity enforcement and public mutation methods; renamed LeftIndexOfIndexOfNextLowest, RightIndexOfIndexOfNextHighest, replaced IndexOf with IndexesOf (returns all matches). DataColumn: GetValue now averages Values for matching base points and uses new scan-based index APIs for interpolation; added averageFor helper and OSPSuite.Utility.Extensions import.
Data Repository API
src/OSPSuite.Core/Domain/Data/DataRepository.cs
Removed public methods InsertValues(float, Cache<string,float>) and SwapValues(float, float).
Exception Removal
src/OSPSuite.Core/Domain/TimeNotStrictlyMonotoneException.cs
Deleted TimeNotStrictlyMonotoneException type and its message construction.
Import & Presenter
src/OSPSuite.Infrastructure.Import/.../DataSetToDataRepositoryMapper.cs, src/OSPSuite.Presentation/Presenters/Importer/ImporterPresenter.cs
Removed try/catch blocks that previously caught/rethrew TimeNotStrictlyMonotoneException; sheet-name enrichment and presenter-level handling removed.
Jacobian / Parameter ID usage
src/OSPSuite.Core/Domain/Services/ParameterIdentifications/JacobianMatrixCalculator.cs
Replaced LeftIndexOf with IndexOfNextLowest when mapping time to indices for Jacobian rows (verify semantics with new scan behavior).
UI Chart Tooltip Refactor
src/OSPSuite.UI/Views/Charts/ChartDisplayView.cs
Switched tooltip resolution from Point-based to ChartHitInfo; updated tooltip helpers and added findNextClosestSeriesPoint; several helpers converted to expression-bodied form.
Tests: Grid/Column/Repo & Integration
tests/OSPSuite.Core.Tests/Domain/BaseGridSpecs.cs, tests/OSPSuite.Core.Tests/Domain/DataColumnSpecs.cs, tests/OSPSuite.Core.Tests/Domain/DataRepositorySpecs.cs, tests/OSPSuite.Core.Tests/Domain/DataRowDataSpecs.cs, tests/OSPSuite.Presentation.Tests/Services/ParameterIdentificationTaskSpecs.cs, tests/OSPSuite.Core.IntegrationTests/PKValuesCalculatorSpecs.cs
Removed multiple tests around Insert/Swap and monotonicity; updated tests to use renamed index APIs and direct Values initializers; extended DataColumn test arrays (added extra grid point). Review for lost coverage.
Small imports/formatting
*
Minor whitespace/formatting adjustments and added OSPSuite.Utility.Extensions import usages.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nudged the grid and let it roam,
No rigid order, it finds a home.
I average hops where points align,
Tooltips now whisper via hitInfo's sign,
Hooray — the data hops and shines! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Multiple out-of-scope changes detected: removal of public Insert/InsertOrReplace/InsertInterval APIs, renaming of LeftIndexOf/RightIndexOf methods, and changes to chart display logic are not justified by the linked issue's narrow scope of removing monotonicity enforcement. Limit changes to removing strict monotonicity validation; preserve the public Insert APIs and method names, or justify these removals with additional linked requirements. Refactor ChartDisplayView changes into a separate PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective: removing the monotonic increasing time values check from DataRepository, which is the primary purpose of this changeset.
Linked Issues check ✅ Passed The PR successfully removes the monotonic increasing time values check from BaseGrid and DataRepository, eliminating the TimeNotStrictlyMonotoneException and related validation logic, directly addressing issue #1863's requirement.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 1863-remove-check-for-monotonically-increasing-time-values

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/OSPSuite.Core/Domain/Data/DataColumn.cs`:
- Around line 243-258: The averageFor method compares floats with exact equality
(baseGridAtIndex vs x) which can fail due to floating-point precision; modify
averageFor (and iterations over BaseGrid.Values) to use a tolerance-based
comparison (e.g., Math.Abs(BaseGrid[i] - baseGridAtIndex) <= epsilon) or iterate
by index using BaseGrid.IndexOf/Count to find matching positions, accumulate
Values[i] for matches, and choose a small sensible epsilon (e.g., 1e-6f) defined
centrally; update any usages of BaseGrid.Values.Each in averageFor to use this
tolerant comparison to avoid missed matches.

In `@tests/OSPSuite.Core.Tests/Domain/DataColumnSpecs.cs`:
- Line 147: In the test assignment to relatedColumn.Values in DataColumnSpecs
(the array with values 0.1F, 0.2F, 0.1F, 02F), fix the typo by changing the last
element from 02F to 0.2F so the array reads new[] { 0.1F, 0.2F, 0.1F, 0.2F };
locate the assignment via the relatedColumn.Values reference and update that
literal.
🧹 Nitpick comments (2)
src/OSPSuite.Core/Domain/Data/DataColumn.cs (1)

224-224: Clarify or remove the uncertain comment.

The comment "We can throw an exception here if the values are not monotonic?" reads as a question rather than documentation. If non-monotonic values should be handled silently (which is the PR's intent), consider removing this comment or converting it to a clear statement of the design decision.

✏️ Suggested clarification
-         // We can throw an exception here if the values are not monotonic?
+         // Non-monotonic values are supported - find neighbors by value comparison
          int leftIndex = BaseGrid.IndexOfNextLowest(baseValue);
tests/OSPSuite.Core.Tests/Domain/BaseGridSpecs.cs (1)

81-101: Test method names no longer match the API methods they test.

The test methods TestRightIndexOf and TestLeftIndexOf now call IndexOfNextHighest and IndexOfNextLowest respectively, but their names still reference the old method names. Consider renaming for clarity:

  • TestRightIndexOfTestIndexOfNextHighest
  • TestLeftIndexOfTestIndexOfNextLowest

Additionally, since this PR removes the monotonicity requirement, consider adding test cases with non-monotonic grid values to verify the new lookup behavior works correctly when values are not sorted.

🔧 Suggested rename
      [Observation]
-     public void TestRightIndexOf()
+     public void TestIndexOfNextHighest()
      {
         sut.Values = new[] { -2.0F, 0.5F, 1.0F, 1.5F };

         Assert.AreEqual(1, sut.IndexOfNextHighest(0.5F));
         Assert.AreEqual(2, sut.IndexOfNextHighest(0.6F));
         Assert.AreEqual(4, sut.IndexOfNextHighest(1.6F));
         Assert.AreEqual(0, sut.IndexOfNextHighest(-3F));
      }

      [Observation]
-     public void TestLeftIndexOf()
+     public void TestIndexOfNextLowest()
      {
         sut.Values = new[] { -2.0F, 0.5F, 1.0F, 1.5F };

         Assert.AreEqual(1, sut.IndexOfNextLowest(0.5F));
         Assert.AreEqual(1, sut.IndexOfNextLowest(0.6F));
         Assert.AreEqual(3, sut.IndexOfNextLowest(1.6F));
         Assert.AreEqual(-1, sut.IndexOfNextLowest(-3F));
      }

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/OSPSuite.Core/Domain/Data/DataColumn.cs`:
- Around line 224-226: Remove the unresolved question comment and replace it
with a short descriptive comment stating the expected behavior: that we no
longer enforce monotonicity and instead rely on
BaseGrid.IndexOfNextLowest(baseValue) and BaseGrid.IndexOfNextHighest(baseValue)
to return the nearest indices (or -1/null if none); update the comment near the
DataColumn method where leftIndex/rightIndex are computed to reflect this
decision (reference BaseGrid.IndexOfNextLowest and BaseGrid.IndexOfNextHighest
and the DataColumn class) so there is no ambiguity about error handling or
expectations.

Comment on lines -38 to -49
//check strong monotony of values first (values are sorted and unique)
for (int i = 1; i < value.Count; i++)
{
if (value[i] <= value[i - 1])
{

var beforeValue =this.ConvertToDisplayUnit(value[i - 1]);
var afterValue = this.ConvertToDisplayUnit(value[i]);
throw new TimeNotStrictlyMonotoneException(beforeValue, afterValue, DisplayUnit.Name, Repository?.Name);
}
}

Copy link
Member

@Yuri05 Yuri05 Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we at least check that the base grid values are sorted?
I think even in case of non-unique base grid we should sort the values before.

Otherwise, if when e.g. plotting observed data not only by dots but by dots+line - it could become ugly if the time values are not sorted. Also the IndexOfNextXXX routines below would be simpler.

Btw: use cases where not unique values (and not sorted values for sure) could make trouble are linear interpolations of data points, and those use cases must be checked once we allow non unique values:

  • import of ph dependent solubility table
Image
  • import of formulation table
Image
  • Import data points of arbitrary table formula in MoBi
Image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, sorted is a MUST.
Non unique values in table formula with activated "Use derivated values" will produce NaNs whatsoever pretty sure

Copy link
Member

@Yuri05 Yuri05 Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I think about it: non-unique values in all cases above must be forbidden.
It's only observed data (and maybe few other cases) where it could be allowed.
Any use case where table represents a function y=f(BaseGrid) should support only unique (and sorted) values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PavelBal Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't that then be controlled outside the base grid object? By the presenters or dtos of these particular usages? Or by another base grid type that does enforce.

Copy link
Member

@Yuri05 Yuri05 Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When plotting observed data we could make this ordering when creating the series points for the chart, only for observation repositories

It's better to sort once during the data import - then no need to sort every time later when the data is plotted, exported, whatsoever.

So in principle I would keep the code in BaseGrid.cs almost AS IS with the only exception that it does not check anymore that the values are unique (but still checks that they are sorted).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how much we gain by enforcing it. We can have the importer sort the points to make the charts less cluttered if lines are enabled, but interpolating values that are not at basegrid points will still require averaging.

All the removed insert/insert range stuff is not used anywhere in Suite anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can have the importer sort the points

yep, this should be done imo

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, what I mean is, I'll leave out the Exception throwing for non-increasing. Both uniqueness and increasing base grid are handled by the construction of the base grid and is not enforced by the base grid.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, let's try it like this and see what happens :)

@PavelBal
Copy link
Member

PavelBal commented Feb 5, 2026

There are two tasks here:

  • Allowing duplicates of x values. This should only be allowed for observed data, I agree with @Yuri05
  • Allowing import of non-monotonically ascending data. This should be easily fixed by simply sorting the grid during import.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@tests/OSPSuite.Core.IntegrationTests/PKValuesCalculatorSpecs.cs`:
- Around line 99-101: The test currently uses .Single() on
_multipleDosingColumn.BaseGrid.IndexesOf(...) which will fail or be inconsistent
if duplicates exist; instead retrieve the indexes via
_multipleDosingColumn.BaseGrid.IndexesOf(_pkOptions.LastMinusOneInterval.EndValue.Value)
and compute the averaged value across those indexes like DataColumn.GetValue
does (i.e., if indexes.Any() calculate the mean of _multipleDosingColumn.Values
at those indexes) and assign that mean to lastValueBeforeLastDose rather than
using indexOfEndTimePointOfLastButOneInterval from .Single(); update references
to indexOfEndTimePointOfLastButOneInterval accordingly.

In `@tests/OSPSuite.Core.Tests/Domain/BaseGridSpecs.cs`:
- Around line 74-102: Replace NUnit assertions in TestIndexOf,
TestIndexOfNextHighest, and TestIndexOfNextLowest with BDDHelper assertion
methods: use .ShouldBeEqualTo(expected) for numeric comparisons returned from
sut.IndexesOf(...).Single(), sut.IndexOfNextHighest(...), and
sut.IndexOfNextLowest(...), and use .ShouldBeFalse() for boolean checks (e.g.,
sut.IndexesOf(0.6F).Any().ShouldBeFalse()). Update each Assert.AreEqual(...)
instance in those three methods to the corresponding .ShouldBeEqualTo(...) or
.ShouldBeFalse() call on the actual value.

@rwmcintosh rwmcintosh merged commit cf6e02f into develop Feb 5, 2026
6 checks passed
@rwmcintosh rwmcintosh deleted the 1863-remove-check-for-monotonically-increasing-time-values branch February 5, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DataRepository - remove check for monotonically increasing time values?

3 participants