Repository navigation
Fix gdal-warp -ovr ports - #3200
Conversation
There was a problem hiding this comment.
LGTM and in general it fixes the problem (in case travis is happy). Apart of a small code hygiene things and the lack of a CHANGELOG, my main question is about the def selectOverview function that probably should not be a part of AST, since can be used only in a single known usecase.
Would be happy to talk through it, mb my API concerns are not applicable here.
/cc @moradology @echeipesh // and anyone else if Eugene is busy // we need 3 persons for the consensus? :D
P.S. It looks like some specs are failing i.e. geotrellis.layer.LayoutTileSourceSpec => there is some bug in a new overview selection function. Let's try to be as conservative as it is possible to preserve the old behavior (or some compat) to make RF life easier.
/cc @notthatbreezy & @jisantuc you were using it in RasterFoundry mentioning it here because this can be a pretty sensitive change for RasterFoundry.
|
|
||
| import org.scalatest._ | ||
|
|
||
| class OverviewStrategySpec extends FunSpec with Matchers { |
bc6a3c2 to
4f7fe57
Compare
pomadchin
left a comment
There was a problem hiding this comment.
Once Travis is happy I think we can merge it 👍
| case Base => | ||
| overviewCS.indexOf(overviewCS.min) | ||
| case AutoHigherResolution => | ||
| selectIndexByProximity(overviewCS, desiredCS, 1.0) |
There was a problem hiding this comment.
Waiting for Travis to be happy with this change. This behavior should match to the tested old behavior (the old one had a long testing path).
There was a problem hiding this comment.
The tests turned out to require a bit more attention than I'd anticipated as some of them baked in the AutoHigher behavior rather than Auto
Implementation wasn't updated to properly use OverviewStrategy Also updates OverviewStrategy.selectOverview to clamp returned indices to valid range
47498f0 to
ce931ed
Compare
There was a problem hiding this comment.
LGTM, but have questions about why everywhere we use Base instead of the former default AutoHigher (as a sainity check that we preserved the old behavior).
And is it okay that getClosestResolution changed its signature? (im fine with that btw, I don't have a strong opinion about that function atm). If so, what kind of errors can it throw? Can we add a small test? Before this change it returned an Option type so nothing really was to test here.
| case Base => maxResultion | ||
| } | ||
| strategy: OverviewStrategy = OverviewStrategy.DEFAULT | ||
| )(implicit f: T => CellSize): T = { |
There was a problem hiding this comment.
And this change made this function throw, do we have tests for that? What kind of exceptions can it throw?
There was a problem hiding this comment.
Ah, should have mentioned this sooner.
It was Option[Int] because some operations could return an out of bounds index. It's not clear how GDAL handles this situation, so we decided that it would be simpler if OverviewStrategy.selectOverview always returned an in bounds index. Which it now does due to additional error handling there. Before this change, we were doing an option.get everywhere which just pushes the throw further down. In that case, I wasn't sure how we would even handle getting a bad overview.
I can add some additional docstrings to note that selectOverview should always return a clamped index, this was apparently the intent of the code based on a test that predates me picking this task up.
There was a problem hiding this comment.
When it can’t find an overview the idea was to use the Base layer, since it looks like what GDAL does. That is why function returned Option - it is a normal behavior not to find any overviews
There was a problem hiding this comment.
How does that reconcile with the idea that we've decided to include the base layer in the resolutions list in all RasterSource implementations?
There was a problem hiding this comment.
Perhaps this discussion should be moved offline as well?
There was a problem hiding this comment.
After a discussion we decided on the following:
- Revert OverviewStrategy.DEFAULT = AutoHigherResolution to make the default consistent with the old behavior for now. We'll address changing the default at a later date
- Update AutoHigherResolution implementation to match the docstring and old behavior, and verify it with tests
- OverviewStrategy.selectOverview still clamps to available indices. Each overview strategy can perform custom clamping behavior, like AutoHigher above, but in the absence of that, the index will be clamped to the nearest valid value, e.g. -1 -> 0 or list.size + 5 -> list.size - 1
- Revert tests where possible to use the AutoHigher default in order to appropriately test the old behavior.
Fixes methods in: - RasterSourceRDD.apply - RasterSource.reprojectToGrid where OverviewStrategy was not correctly passed to some resample operations. **NOTE:**: RasterSourceRDD still inconsistently uses both ResampleMethod and OverviewStrategy. For best results, its necessary to use RasterSourceRDD.apply directly.
Same issue as in previous commit for RasterSourceRDDSpec, need to provide strategy. See: locationtech#3216
Sets to WARN by default, to reduce verbosity in build logs which make it difficult to see the test results.
In RasterSourceRDD tests in order to better preserve original test intent (since the default strategy used to be AutoHigher)
To retain backwards compatibility with existing code that uses the default strategy. We expect to change this default to Auto(0) in the future.
Specifically it should now clamp to Base if the index is OOB in any direction
96ab3da to
d930be7
Compare
ebfa9cb to
f62214e
Compare
f62214e to
0bcb552
Compare
| // This method is unsafe. It's up to the selectOverview method to handle each index OOB error for | ||
| // each indivdual strategy | ||
| private def selectIndexByProximity(overviewCS: List[CellSize], desiredCS: CellSize, proximityThreshold: Double): Int = | ||
| overviewCS.search(desiredCS) match { |
There was a problem hiding this comment.
I guess this could be replaced with a foldM function. Amyway this list should be sorted ¯_(ツ)_/¯ so it could be more easy to read.
0bcb552 to
5d7b6fd
Compare
| /** | ||
| * Select appropriate overview given the strategy. | ||
| * | ||
| * WARN: this function assumes that CellSizes are sorted. It interprets idx 0 as the position with the highest CellSize. |
There was a problem hiding this comment.
Taking into the account that this is true, usage of the search function in the selectIndexByProximity function makes it really hard to interpret.
| val idx = selectIndexByProximity(overviewCS, desiredCS, 1.0) | ||
| // AutoHigherResolution defaults to the closest level | ||
| // idx > overviewCS.size means, that idx = overviewCS.size (last idx + 1) | ||
| if (idx > overviewCS.size) idx - 1 else idx |
There was a problem hiding this comment.
We need to know where is the highest resolution to interpret the index the selectIndexByProximity function returns. If the input list is sorted, idx > overviewCS.size means the lower resolution. In case it is reversed, it means the higher resolution. If the list is not sorted, this index makes no sense for its interpretation.
7ffbf11 to
ed78d83
Compare
4390220 to
7d894bd
Compare
| * @return index of the closest cellSize. Returns -1 in case nothing was found or the input list was not sorted. | ||
| */ | ||
| private def selectIndexByProximity(overviewCS: List[CellSize], desiredCS: CellSize, proximityThreshold: Double): Int = | ||
| overviewCS.zipWithIndex.foldLeftM(Option.empty[(CellSize, Int)]) { case (acc, r @ (rightCZ, _)) => |
There was a problem hiding this comment.
I am not sure that with folding it is much easier to read, however it is more explicit about sorting.
| // - negative if rightCZ < leftCZ | ||
| // - positive if rightCZ > leftCZ | ||
| // - zero otherwise (if rightCZ == leftCZ) | ||
| if (Ordering[CellSize].compare(rightCZ, leftCZ) < 0) { |
There was a problem hiding this comment.
short circuiting if the list is not sorted
Overview
This PR exposes the overview selection logic implicit in each of the
OverviewStrategyinstances by way of aselectOverviewmethod. Now, instead of matching and requiring users of the sum type to implement logic themselves, a call toselectOverviewwith the availableCellSizesand the desiredCellSizewill yield a selection of theCellSizecorresponding to the selectedOverviewChecklist
docsguides update, if necessaryNotes
Optional. Ancillary topics, caveats, alternative strategies that didn't work out, anything else.
Closes #3196