Add spatstat-equivalent edge corrections to G, F, J, K, and L#211
Draft
sjsrey wants to merge 10 commits into
Draft
Add spatstat-equivalent edge corrections to G, F, J, K, and L#211sjsrey wants to merge 10 commits into
sjsrey wants to merge 10 commits into
Conversation
Implements the erosion estimator for g(): points whose distance to the study window boundary is less than r are excluded from the guard set at each radius, and the support is automatically clipped to the erosion threshold radius from max_radius(..., method='erosion_threshold'). Adds hull parameter to g() and 18 new tests covering both the standard and erosion paths.
Implements the guard-area erosion estimator for k(): only points whose distance to the study window boundary exceeds r act as focal points at each radius, with the support auto-clipped to the erosion threshold from max_radius. Adds hull parameter to k() and l(), threads hull through _ripley_test for K/L calltypes, and extracts a shared _hull_to_poly helper used by both g() and k(). Adds 21 new tests covering standard K behaviour, all three hull types, the CSR K≈πr² sanity check, and L consistency with K.
Replace squareform() with two memory-efficient paths: when distances are not pre-supplied, use a radius-query tree so no pairwise distance matrix is built at all; when the user provides a condensed vector, work from triu_indices + int8 weight arrays instead of expanding to a full n×n float64 matrix. The non-erosion path is unchanged.
Implements edge_correction='ripley' for k() and l(): for each point within r of the window boundary, n_circle equally-spaced test points are placed on a circle of radius r and w_i = n_circle / n_inside. Adds TestKRipley (10 tests) and TestLRipley (3 tests); updates the existing invalid-correction test now that 'ripley' is a valid value. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements edge_correction='analytic' for k() and l(): for each point within r of the window boundary, w_i = πr² / area(circle(i,r) ∩ window), computed exactly via shapely intersection. Refactors the 'ripley' and 'analytic' paths to share a single weighted-K loop, selecting only the weight function at the branch point. Adds TestKAnalytic (11 tests) and TestLAnalytic (2 tests), including a test pinning that K_analytic ≤ K_ripley due to area fraction ≥ arc fraction for convex windows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
k() and l() now return KEstResult / LEstResult named tuples (support, theo, border, isotropic, translate) when called without edge_correction, mirroring spatstat::Kest() behaviour. Passing edge_correction=None retains the old uncorrected 2-tuple return for backward compatibility. A _NOTSET sentinel distinguishes "no argument" from "explicit None". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Deleted _ripley_circle_weights, _ripley_analytic_weights, and the 'ripley'/'analytic' edge_correction options from k() and l(). Also removed the n_circle parameter (it was only used by the ripley correction). The three supported corrections are now border/erosion, isotropic, and translate. Tests for the removed corrections dropped. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements rs, km, Hanisch (G), Chiu-Stoyan (F), and han/un (J) corrections following the spatstat pattern: omitting edge_correction returns a named-tuple (GEstResult/FEstResult/JEstResult) with all corrections; edge_correction=None returns the raw estimate for backward compatibility. Fixes Chiu-Stoyan weight formula: use π d²/area(disk∩W) rather than |W|/area(disk∩W), which diverged for small empty-space distances. Fixes J support-alignment when G-rs clips its grid to the erosion threshold. Refactors test suite to cover all new correction modes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #211 +/- ##
=======================================
+ Coverage 72.9% 80.2% +7.4%
=======================================
Files 12 12
Lines 2118 2489 +371
=======================================
+ Hits 1543 1997 +454
+ Misses 575 492 -83
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_NOTSETsentinel pattern: omittingedge_correctionreturns a named tuple with all corrections simultaneously (GEstResult,FEstResult,JEstResult); passingedge_correction=Nonereturns the uncorrected(support, values)tuple for backward compatibilitymax_radiushelper ingeometry.pyfor erosion-threshold computationCorrections added
raw,rs(border/erosion),km(Kaplan-Meier),hanischraw,rs,km,cs(Chiu-Stoyan)un,rs,km,han(Hanisch/CS hybrid)None(raw),border/erosion,isotropic,translateKey implementation notes
π d² / area(disk(u,d) ∩ W)— the fraction of the disk visible from inside W. An earlier approach using|W| / area(disk ∩ W)diverges as 1/d² for small empty-space distances and was discarded._kaplan_meier_cdfand_km_at_supportcompute the product-limit estimator and interpolate it onto an arbitrary support grid.Test plan
pytest pointpats/tests/test_distance_statistics.py— 171 tests covering all correction modes for G, F, J (raw/rs/km/Hanisch/CS/han/un), plus all existing K and L tests1 - exp(-λπr²)andπr²theoretical curvesdocs/user-guide/edge_corrections.ipynbexecutes end-to-end without errors (34 cells, 16 code cells)