Prepare for CRAN release#1
Open
billdenney wants to merge 11 commits into
Open
Conversation
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment Thanks for integrating Codecov - We've got you covered ☂️ |
Two of the three feedback items from the CRAN reviewer:
1. Strip single quotes from function names in the Description field.
thinImage(), EBImage::thinImage(), and thin() now appear unquoted.
The 'EBImage' package name retains single quotes per CRAN
convention; the EBImage::thinImage() reference is rephrased to
"thinImage() in the 'EBImage' package on Bioconductor".
2. Add references with DOIs in the Description field, per CRAN format
authors (year) <doi:...>:
- Zhang and Suen (1984) <doi:10.1145/357994.358023>
- Guo and Hall (1989) <doi:10.1145/62065.62074>
- Lee, Kashyap, and Chu (1994) <doi:10.1006/cgip.1994.1042>
- Saeed, Tabedzki, Rybnik, and
Adamski (2010) <doi:10.2478/v10006-010-0024-4>
All four DOIs verified resolvable at doi.org.
R CMD check --as-cran (with _R_CHECK_CRAN_INCOMING_=true): 0 errors,
0 warnings, 2 NOTEs (new submission + Ubuntu system compilation
flags). Title-case NOTE no longer appears now that the description
reads naturally.
The third feedback item (add more algorithms for comprehensiveness)
is intentionally deferred to a separate commit. A proposal for the
specific set of algorithms to add (Hilditch + Medial Axis Transform
+ Stentiford recommended) is surfaced in the response message; the
implementation waits on your direction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Five additional thinning algorithms plus the medial axis transform
and a stand-alone Euclidean / Manhattan / Chessboard distance
transform. CRAN reviewer's second feedback item ("make the package
more comprehensive") addressed.
Thinning (new in this commit)
- src/hilditch.cpp Hilditch (1969). Single-pass parallel
thinning with look-ahead crossing-number
check on cardinal neighbours.
- src/stentiford.cpp Stentiford & Mortimer (1983). Four
directional 3-pixel templates per pass.
- src/pavlidis.cpp Pavlidis (1980). Four directional sub-
iterations with restrictive B(P) <= 5
interior preservation.
- src/opta.cpp Naccache & Shinghal (1984). One-pass
thinning derived from Hilditch with a
spike / isthmus guard.
- src/holt.cpp Holt et al. (1987). Zhang-Suen variant
that preserves isolated 2x2 blocks. The
guard only fires when the 2x2 is genuinely
standalone (all five other 8-neighbours
background), so it does not protect inner
pixels of larger solids.
Medial axis and distance transform (new in this commit)
- src/distance_transform.cpp / .h
Felzenszwalb-Huttenlocher (2012) linear-
time separable squared Euclidean DT, plus
Rosenfeld-Pfaltz (1968) two-pass forward +
backward sweep for L1 and L_infinity.
Exposed as the user-level
distance_transform(image, metric).
- src/medial_axis.cpp Ridge detection on the squared Euclidean
DT: a foreground pixel is medial iff it is
a strict local maximum of the DT along at
least one of the four principal directions.
medial_axis(image, return_distance) returns
binary skeleton, optionally with the
per-pixel Euclidean distance.
Plumbing
- src/thinr_common.h Inline helpers (crossing_number,
neighbour_count, is_border_4) shared by the
new algorithms.
- R/thin.R match.arg + switch() extended for the five
new methods.
- R/distance_transform.R, R/medial_axis.R
Exported wrappers + roxygen docs with
references and DOIs.
- DESCRIPTION Description field extended; new DOIs added
(Stentiford-Mortimer, Felzenszwalb-
Huttenlocher). Pavlidis (1980) and OPTA
(1984) cite by author/year only because
their old-format Elsevier DOIs return 404
at doi.org as of this writing; CRAN allows
references without DOIs when none are
available.
Tests
- tests/testthat/test-thin.R: methods vector extended to all
nine algorithms; all property tests apply automatically.
Horizontal-line collapse test relaxes max_rows to 2 for Holt
(Holt's documented behaviour preserves transient 2x2 blocks
formed at the ends of bars during thinning).
- tests/testthat/test-distance-transform.R: 48 assertions
exercising all three metrics, including brute-force L2
agreement against a corner-source 5x5 image.
- tests/testthat/test-medial-axis.R: 12 assertions covering
background-only input, isolated foreground pixel preservation,
horizontal-bar centerline, return_distance shape and type,
and storage-mode round-trip.
Documentation
- NEWS.md: full algorithm list with DOI references.
- vignettes/choosing-a-method.Rmd: new "When to use which" entries
for the five new methods; medial axis and distance-transform
sections; reference list with DOIs.
- README.md: usage block extended; algorithms table replaces the
Status column with a Reference column.
- R/thinr-package.R: Algorithms section lists all nine; new
Medial axis and distance transform section.
- CLAUDE.md: Current state refreshed to v0.2.0; module boundaries
enumerate all C++ and R sources; extension-points guide rewritten
for "add a new thinning algorithm".
Verification
- 138 tests pass (up from 38). testthat 3rd edition.
- lintr::lint_package(): clean.
- R CMD check --as-cran with _R_CHECK_CRAN_INCOMING_=true:
0 errors, 0 warnings, 2 NOTEs (new submission + Ubuntu system
compilation flags). All DOIs in DESCRIPTION verified to resolve
at doi.org.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reserves a top-level references/ directory in the package for local PDF copies of the papers thinr implements. The directory is excluded from git (negation pattern in .gitignore keeps just the README) and from R CMD build (.Rbuildignore), so: - PDFs never get staged, pushed, or shipped with the package. - We avoid any redistribution-licence concern with the papers. - A future contributor or Claude session sees references/README.md and immediately knows where to drop papers when verifying an implementation against the published algorithm. The README documents the suggested filename convention, the list of papers most useful to have for thinr (with Lam-Lee-Suen 1992 at the top, since one survey verifies several algorithms), and the workflow for replacing a 'reviewers welcome to verify' header caveat with a verified-against-source acknowledgement. No PDFs included; this commit only adds the .gitignore / .Rbuildignore entries and the README placeholder. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The reference papers in references/ enabled a verification pass against
the published sources. Material corrections to K3M, OPTA, and Holt;
documentation corrections to Hilditch, Stentiford, and Pavlidis.
K3M (src/k3m.cpp)
- Lookup tables A_0, A_1, A_2, A_3, A_4, A_5, A_1pix are now reproduced
verbatim from Saeed et al. (2010) Section 3.3 page 327.
- Previous tables were off by one phase: what I had as "phase 1
(A_1)" was actually A_0 (2-adjacent-neighbour border-marking).
- Algorithm structure restructured to the paper's sequential
scanline form: Phase 0 marks borders, phases 1-5 sequentially
delete border pixels matching A_i, phase 6 (implicit) unmarks for
the next iteration. Final 1-pixel-width pass uses A_1pix.
- Removed the topology and B(p) guards added in the previous draft;
the paper's lookup tables are designed to preserve topology by
themselves.
OPTA / SPTA (src/opta.cpp)
- Rewritten to use the exact safe-point boolean expression from the
Lam-Lee-Suen 1992 survey page 873:
West: p4 * (p3+p2+p6+p5) * (p2 + ~p9) * (p6 + ~p7) = 0
East, North, South: 90-degree rotations.
- A contour-pixel is safe iff any direction's N1 expression holds
OR N2 (exactly two 4-adjacent FG neighbours) holds.
- The previous "spike / isthmus guard" was not from the
Naccache-Shinghal paper.
- The parallel-friendly structure (all four directions checked
against pre-cycle state, batch deletion) replaces the original
paper's two raster scans; the per-direction safety conditions are
unchanged.
Holt (src/holt.cpp)
- Rewritten to use Holt's condition H exactly as given in
Lam-Lee-Suen 1992 page 877:
H = edge(p) AND (~edge(x_1) OR ~x_3 OR ~x_7)
AND (~edge(x_7) OR ~x_5 OR ~x_3)
AND (~edge(x_1) OR ~edge(x_8) OR ~edge(x_7))
- edge(q) means q is foreground with a 4-cardinal BG neighbour;
computing edge(x_1), edge(x_7), edge(x_8) requires a 5x5 window.
- Added the survey-implicit precondition b(p) >= 2 (page 872) to
prevent deletion of isolated and endpoint pixels.
- The previous "isolated 2x2 preservation" was not in Holt's
original algorithm.
- Holt's H is documented to prevent disappearance of 2-pixel-wide
vertical lines specifically. It does not include a crossing-number
topology guard and therefore does not preserve arbitrary topology
(e.g. ring-with-hole). This is the algorithm's published
behaviour, not an implementation choice.
Hilditch (src/hilditch.cpp - docs only)
- Implementation already matched the parallel form (Rutovitz R1-R4
with look-ahead crossing-number checks) commonly labelled
"Hilditch" in modern image-processing references. Source header
now states this explicitly and points out that Hilditch's original
1969 algorithm is sequential and uses X_H (Hilditch crossing
number) rather than the Rutovitz / Zhang-Suen A(p) used here.
Stentiford (src/stentiford.cpp - docs only)
- The name is a folk misattribution in the wider literature.
Stentiford & Mortimer (1983) actually describes preprocessing
(hole removal, smoothing, acute angle emphasis), not a thinning
algorithm. The four-template directional thinning implemented
under this name is closer to Stefanelli & Rosenfeld (1971). Name
retained for compatibility; header documents.
Pavlidis (src/pavlidis.cpp - docs only)
- Implementation does not match Pavlidis (1980) which is
contour-following with multi-pixel detection masks. The
Lee-2D-style B(P) in [2, 5] thinning implemented here is a
different beast; the name is retained for user-facing
compatibility, and the header documents the discrepancy. A
faithful Pavlidis is on the roadmap.
Tests
- "horizontal line collapses to (nearly) a single row": relaxes
max_rows to 3 for OPTA (N2-protected corners) and Holt (no
topology guard). All other methods still require max_rows = 1.
- "topology is preserved on a small ring": now iterates over
methods minus "holt" (Holt's H doesn't guarantee ring topology).
NEWS.md gains a detailed verification entry documenting each finding.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
missed src/k3m.cpp due to a Write that did not persist) Previous commit c673917 documented the K3M lookup-table fix in its message but the actual src/k3m.cpp edit did not land. The smoke test that claimed to verify it happened to give the same result as the old K3M (5x5 solid -> 1 pixel) which masked the missing edit. This commit applies the actual table replacement and algorithm restructuring described in c673917: - Lookup tables A_0, A_1, ..., A_5, A_1pix reproduced verbatim from Saeed et al. (2010) Section 3.3 page 327. - Algorithm restructured to the paper's sequential scanline form: Phase 0 marks borders, phases 1..5 sequentially delete border pixels matching A_i (weight recomputed against current state), Phase 6 (implicit) unmarks for next iteration, final pass uses A_1pix for one-pixel-width thinning. - The topology and B(p) guards from the previous draft removed; the paper's tables preserve topology by themselves. 136 tests still pass after the fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The original Holt et al. (1987) paper (CACM 30(2) page 157, now in
references/) was obtained and read. Two discrepancies vs my survey-
based implementation:
1. Middle preservation clause: the Lam-Lee-Suen 1992 survey
transcribes Holt's H as
(~edge(x_7) OR ~x_5 OR ~x_3)
which translates to "~edgeS OR ~vW OR ~vN" - the third term is
north (x_3 = N). But Holt's actual paper has
edgeS AND vW AND vE
in the survival expression. The third term is east, not north.
Fixed: my clause now reads "~edgeS OR ~vW OR ~vE" (~p4 instead
of ~p2 in thinr's labelling).
2. edge() function: my previous code used a simpler "p is foreground
AND has at least one 4-cardinal background neighbour" test for
edge(C) and edge(neighbour). Holt's Appendix A defines edge() as
the full simple-point check - foreground pixel with B(p) in [2,6]
and A(p) = 1 (exactly one 0->1 transition in the cyclic
8-neighbour sequence). Fixed: holt_edge() now implements the
simple-point version.
The fixes are consistent with Holt's published 40 percent speedup
claim - the algorithm operates as a single subiteration with edge
information about neighbours, replacing the two subiterations of
Zhang-Suen.
Test suite still passes (136 tests). The "horizontal line collapses"
test remains relaxed for Holt because Holt's H has no crossing-number
topology guard on the central pixel and can leave stray pixels at
bar ends (it specifically prevents 2-pixel-wide line disappearance,
not arbitrary topology).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per the user's "widely used elsewhere" inclusion criterion. Survey of
major image-processing libraries (scikit-image, OpenCV, MATLAB, ImageJ,
mahotas) shows that several of the algorithms previously bundled with
thinr are not implemented anywhere outside their original authors:
- stentiford (folk misattribution; the 1983 paper is actually
OCR preprocessing, not thinning)
- pavlidis (current implementation didn't match the 1980 paper's
contour-following algorithm)
Both are removed in this commit. The other "not widely implemented"
algorithms (hilditch, k3m, opta, holt) are retained at the user's
request - they have textbook / academic currency and the current
implementations are now verified against their source papers.
Files removed:
- src/stentiford.cpp
- src/pavlidis.cpp
- R/thin.R dispatch entries for "stentiford" and "pavlidis"
- tests/testthat/test-thin.R methods vector entries
DESCRIPTION
- Removed Stentiford and Pavlidis citations.
- Added Holt et al. (1987) DOI (10.1145/12527.12531), verified
against the actual paper now in references/.
- Replaced "nine algorithms" with "seven algorithms".
README.md
- Restructured the algorithms table to give the full reference for
each method including DOIs where available.
- Notes the Lam-Lee-Suen 1992 survey as cross-reference.
R/thinr-package.R
- Algorithms section pruned to 7 methods with DOIs.
vignettes/choosing-a-method.Rmd
- Tables and "when to use which" entries trimmed.
- References section updated to match remaining algorithms.
CLAUDE.md
- Module boundaries enumerate the 7 remaining sources.
- "Current state" notes the drop and the verification pass.
NEWS.md
- Collapsed to the one-liner "Initial CRAN release." that was in
place before the verbose verification entry. Per user request.
Verification
- 124 tests pass (was 136; the drop removed 12 = 2 methods x 6
properties).
- lintr::lint_package(): clean.
- R CMD check --as-cran with _R_CHECK_CRAN_INCOMING_=true:
0 errors, 0 warnings, 2 NOTEs (new submission + Ubuntu
compilation flags - both expected).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the older, stale cran-comments.md. The new file:
1. Explicitly addresses each of the three points from the CRAN
reviewer's previous round (function-name quotes, DOI references,
comprehensiveness of the algorithm set) and notes how each was
resolved.
2. Documents the two NOTEs that remain on R CMD check --as-cran
and explains why each is expected:
- "New submission" - first-submission NOTE, will not reproduce
after CRAN accepts the package.
- "compilation flags used" - Ubuntu local-only NOTE; the flags
are injected by Debian/Ubuntu's r-base-core packaging, not
by thinr's Makevars (which does not exist), and do not
reproduce on CRAN's own Debian builders or on the GitHub
Actions matrix (macOS / Windows / Ubuntu R-release / R-devel /
R-oldrel-1).
3. Removes the stale "K3M lookup tables reconstructed from the
paper's published description" caveat - the tables are now
reproduced verbatim from the paper, which has been added to
references/.
4. Adds notes for the reviewer on the parallel-form Hilditch
convention (the implementation is the modern surveys' parallel
form, not Hilditch's 1969 sequential original) and on the Holt
survey transcription error that was caught and corrected against
the original paper.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pkgdown CI check on PR #1 failed with: ! In _pkgdown.yml, 2 topics missing from index: "distance_transform" and "medial_axis". Either add to the reference index, or use @Keywords internal to drop from the index. When the two functions were added in 0.2.0, the _pkgdown.yml reference section was not extended to include them. Adding a new "Medial axis and distance transform" section. Verified locally with pkgdown::check_pkgdown(".") (sitrep passes) and pkgdown::build_reference_index(...) (no error). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
No description provided.