Skip to content

Fix more broken links and anchors in README files - #2085

Open
pratikgx wants to merge 2 commits into
Project-MONAI:mainfrom
pratikgx:fix-more-readme-links
Open

pratikgx wants to merge 2 commits into
Project-MONAI:mainfrom
pratikgx:fix-more-readme-links

Conversation

@pratikgx

@pratikgx pratikgx commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Fixes # .

Description

Fixes broken relative links and anchors in README files on main:

  • nnunet/README.md: the datalist tutorial link pointed to msd_datalist_generator.ipynb; the notebook in auto3dseg/notebooks/ is msd_crossval_datalist_generator.ipynb.
  • bundle/introducing_config/README.md: the plain-text replacement link pointed to ../get_started.md, which does not exist; macro text replacement is covered in ../further_features.md.
  • CONTRIBUTING.md: #ci-test-passing-guide did not match the "CI/CD test passing guide" heading, whose anchor is #cicd-test-passing-guide.
  • deployment/Triton/README.md: three links used #model-config-file; the heading is "Model Config", so the anchor is #model-config.
  • reconstruction/MRI_reconstruction/unet_demo/README.md and varnet_demo/README.md: the table of contents linked #Acknowledgement, but the heading is spelled "Acknowledgment".

Docs-only change, no notebooks touched.

Checks

  • Avoid including large-size files in the PR.
  • For security purposes, please check the contents and remove any sensitive info such as user names and private key.
  • Ensure (1) hyperlinks and markdown anchors are working (2) use relative paths for tutorial repo files (3) put figure and graphs in the ./figure folder

Summary by CodeRabbit

  • Documentation
    • Corrected links and section anchors across the contribution guide, configuration tutorial, deployment instructions, dataset-preparation guide, and MRI reconstruction demos.
    • Added a reference from the Triton directory-structure guidance to the Model Config section and fixed formatting in the Quick Start example.
    • Removed the link from the “Deepgrow Stats” heading while keeping its description and image unchanged.
    • Standardized heading spacing and corrected the pre/post-processing table-of-contents link.

- nnunet/README.md: msd_datalist_generator.ipynb -> msd_crossval_datalist_generator.ipynb
- bundle/introducing_config/README.md: ../get_started.md -> ../further_features.md
- CONTRIBUTING.md: #ci-test-passing-guide -> #cicd-test-passing-guide
- deployment/Triton/README.md: #model-config-file -> #model-config
- reconstruction/MRI_reconstruction/{unet,varnet}_demo/README.md: #Acknowledgement -> #acknowledgment

Signed-off-by: Pratik Gandhi <travpreneur@gmail.com>
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3c1b86b8-a13b-4c0a-873b-359640d971aa
Commits

Reviewing files that changed from the base of the PR and between 08634fb and c2db924.

Files selected for processing: 3
  • deepgrow/ignite/README.md
  • deployment/Triton/README.md
  • full_gpu_inference_pipeline/README.md
Files skipped from review as they are similar to previous changes: 1
  • deployment/Triton/README.md

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Walkthrough

This change corrects documentation links and heading anchors, adjusts heading spaces, removes a code fence, and adds a note in the Triton README.

Changes

Documentation corrections

Layer / File(s) Summary
Guide and tutorial destinations
CONTRIBUTING.md, bundle/introducing_config/README.md, nnunet/README.md
Updated links to the testing guide, plain-text replacement tutorial, and dataset-preparation tutorial.
Triton Quick Start and Model Config
deployment/Triton/README.md
Corrected Quick Start and Model Config links, removed a closing code fence, and added a note linking the expected directory structure to Model Config.
Demo README anchors and headings
reconstruction/MRI_reconstruction/unet_demo/README.md, reconstruction/MRI_reconstruction/varnet_demo/README.md, deepgrow/ignite/README.md, full_gpu_inference_pipeline/README.md
Updated acknowledgment and pre/post-processing anchors, normalized heading spaces, and changed the “Deepgrow Stats” heading to plain text.

Priority: Low

Estimated code review effort: 1 (Trivial) | ~4 minutes

Change: Other

Suggested reviewers: slbryson, zmsunnyday, sachidanandalle

Merge Risk: Minimal · up to c2db9

The documentation fixes are mergeable with no identified blocking risk.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly summarizes the main change: fixing broken links and anchors in README files.
Description check Passed The description explains the documentation changes, identifies the affected files, and reports applicable checks. The issue reference is not populated, and the notebook execution check is omitted beca…
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the documentation changes, identifies the affected files, and reports applicable checks. The issue reference is not populated, and the notebook execution check is omitted because no notebooks were changed; these are non-critical for this documentation-only pull request.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (3 skipped: 3 unsupported.)

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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.

@ericspod

Copy link
Copy Markdown
Member

@coderabbitai are these link fixes all correct? Are there other broken links elsewhere in the repo?

@coderabbitai

coderabbitai Bot commented Oct 26, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
gh pr diff 2085 --repo Project-MONAI/tutorials
printf '\n--- Documentation inventory ---\n'
git ls-files '*.md' '*.ipynb' | awk '/\.md$/ {md++} /\.ipynb$/ {nb++} END {print "Markdown files:",md,"Notebooks:",nb}'
printf '\n--- Changed documents ---\n'
for f in CONTRIBUTING.md bundle/introducing_config/README.md deployment/Triton/README.md nnunet/README.md reconstruction/MRI_reconstruction/unet_demo/README.md reconstruction/MRI_reconstruction/varnet_demo/README.md; do
  printf '\n--- %s ---\n' "$f"
  cat -n "$f"
done
printf '\n--- Target sections ---\n'
rg -n -C3 '^#{1,6} .*|plain text|macro|model-config' bundle/further_features.md
fd -i '.*(contribut|test|model.*config).*' --type f

Length of output: 72911


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python -m pip -q install markdown-it-py
python - <<'PY'
import subprocess,json,re,html,unicodedata,collections
from pathlib import Path
from urllib.parse import urlsplit,unquote
from markdown_it import MarkdownIt
md=MarkdownIt('commonmark',{'html':True})
files=subprocess.check_output(['git','ls-files','-z']).decode().split('\0')
docs=[Path(p) for p in files if p.endswith(('.md','.ipynb'))]
data={}
for p in docs:
    if p.suffix=='.md': cells=[(None,p.read_text())]
    else:
        nb=json.loads(p.read_text())
        cells=[(i+1,''.join(c.get('source',[]))) for i,c in enumerate(nb.get('cells',[])) if c.get('cell_type')=='markdown']
    anchors=set(); headings=[]; links=[]; counts=collections.Counter()
    for ci,text in cells:
        toks=md.parse(text)
        for i,t in enumerate(toks):
            line=(t.map[0]+1) if t.map else 1
            loc=f'Line {line}' if ci is None else f'cell {ci}, Markdown line {line}'
            if t.type=='heading_open':
                inline=toks[i+1]
                title=''.join(c.content for c in inline.children or [] if c.type in ('text','code_inline'))
                slug=''.join(c for c in html.unescape(title).lower() if c in (' ','-','_') or unicodedata.category(c)[0] in ('L','N','M')).replace(' ','-')
                base=slug
                while slug in anchors:
                    counts[base]+=1; slug=f'{base}-{counts[base]}'
                anchors.add(slug);headings.append((loc,title,slug))
            if t.type=='inline':
                for c in t.children or []:
                    if c.type in ('link_open','image'):
                        links.append((loc,c.attrGet('href') if c.type=='link_open' else c.attrGet('src')))
            if t.type in ('html_block','inline'):
                content=t.content if t.type=='html_block' else '\n'.join(c.content for c in t.children or [] if c.type=='html_inline')
                for a in re.finditer(r'\b(?:id|name)\s*=\s*["\']([^"\']+)["\']',content): anchors.add(a.group(1))
                for a in re.finditer(r'\b(?:href|src)\s*=\s*["\']([^"\']+)["\']',content):
                    links.append((loc,a.group(1)))
    data[p]=(anchors,headings,links)
missing=[];fragments=[];external=set();checked=0
for p,(_,_,links) in data.items():
    for loc,url in links:
        if not url: continue
        u=urlsplit(html.unescape(url))
        if u.scheme or u.netloc:
            if u.scheme in ('http','https'):external.add(url)
            continue
        if u.path.startswith('/'):continue
        target=Path(__import__('os').path.normpath(str(p.parent/unquote(u.path)))) if u.path else p
        checked+=1
        if not target.exists():
            missing.append((str(p),loc,url,str(target)));continue
        frag=unquote(u.fragment)
        if frag and target in data and frag not in data[target][0]:
            # Uppercase-only fragment differences are listed separately from missing fragments.
            if frag.lower() in {a.lower() for a in data[target][0]}:continue
            fragments.append((str(p),loc,url,str(target)))
print('SUMMARY',json.dumps({'documents':len(docs),'local_link_occurrences_checked':checked,'missing_path_occurrences':len(missing),'unmatched_fragment_candidates':len(fragments),'unique_external_urls_not_checked':len(external)}))
print('\nMISSING PATHS')
for x in missing:print(json.dumps(x))
print('\nUNMATCHED FRAGMENT CANDIDATES')
for x in fragments:print(json.dumps(x))
print('\nTRITON PARSED HEADINGS')
print(json.dumps(data[Path('deployment/Triton/README.md')][1],indent=2))
print('\nMSD TARGET MARKDOWN EXCERPTS')
p=Path('auto3dseg/notebooks/msd_crossval_datalist_generator.ipynb')
nb=json.loads(p.read_text())
for i,c in enumerate(nb['cells']):
    text=''.join(c.get('source',[]))
    if c.get('cell_type')=='markdown' and (i<5 or re.search('spleen|datalist|download',text,re.I)):
        print('cell',i+1,text[:1600])
PY

Length of output: 7560


🏁 Script executed:

#!/bin/bash
set -euo pipefail
printf '\n--- Candidate contexts ---\n'
sed -n '125,160p' deepgrow/ignite/README.md
sed -n '115,155p' federated_learning/breast_density_challenge/README.md
cat -n full_gpu_inference_pipeline/README.md
printf '\n--- Possible replacement files ---\n'
fd -i 'handler|predictions|maisi.*tutorial|rxrx1' --type f
printf '\n--- Notebook Markdown context ---\n'
python - <<'PY'
import json
from pathlib import Path
from markdown_it import MarkdownIt
md=MarkdownIt()
for filename,cellnums in [
 ('generation/maisi/maisi_train_controlnet_tutorial.ipynb',[10]),
 ('microscopy/multichannel_microscopy_classification.ipynb',[11]),
 ('3d_registration/learn2reg_oasis_unpaired_brain_mr.ipynb',[35])]:
    nb=json.loads(Path(filename).read_text())
    print('\nFILE',filename)
    for i,c in enumerate(nb['cells'],1):
        text=''.join(c.get('source',[]))
        if i in cellnums: print('CELL',i,'\n',text)
        if c.get('cell_type')=='markdown':
            toks=md.parse(text)
            for j,t in enumerate(toks):
                if t.type=='heading_open': print('HEADING cell',i,':',toks[j+1].content)
print('\nMSD DOWNLOAD AND DATALIST CODE (inspection only)')
nb=json.loads(Path('auto3dseg/notebooks/msd_crossval_datalist_generator.ipynb').read_text())
for i,c in enumerate(nb['cells'],1):
    text=''.join(c.get('source',[]))
    if c.get('cell_type')=='code' and any(s in text for s in ['download','datalist','json.dump']):
        print('CELL',i,'\n',text[:2600])
PY
printf '\n--- Replacement and generated-data references ---\n'
rg -n -C2 'handler[s]?\.py|predictions\.json|rxrx1_subset_monai|maisi_diff_unet_training_tutorial|maisi_train_diffusion_model' deepgrow microscopy generation/maisi federated_learning/breast_density_challenge -g '*.md' -g '*.py'

Length of output: 26007


@ericspod Yes. All eight link changes in this PR are correct. I checked the target files, target content, and Markdown headings.

Change Verification
nnunet/README.md The replacement notebook exists. It downloads the MSD Spleen dataset and writes a cross-validation datalist.
bundle/introducing_config/README.md bundle/further_features.md contains the macro text replacement example.
CONTRIBUTING.md #cicd-test-passing-guide matches CI/CD test passing guide.
deployment/Triton/README.md All three replacement links match Model Config.
Both MRI reconstruction READMEs #acknowledgment matches the heading in each file.

Other broken links

I scanned 98 Markdown files and the Markdown cells in 173 notebooks. The scan checked 762 local link and image references. I found these additional issues:

Location Issue Recommended correction
deepgrow/ignite/README.md, Line 146 ./handler.py does not exist. Replace the link with the current statistics-handler implementation, or remove the obsolete link.
generation/maisi/maisi_train_controlnet_tutorial.ipynb, cell 10 ./maisi_diff_unet_training_tutorial.ipynb does not exist. Use ./maisi_train_diff_unet_tutorial.ipynb.
deployment/Triton/README.md, Line 70 #examples has no rendered target. An extra code fence at Line 109 puts ## Examples: inside a code block. Remove the extra fence and check the surrounding code blocks. Also fix [Quick Start] (#quick-start) at Line 56 by removing the space before (.
full_gpu_inference_pipeline/README.md, Line 8 The target heading at Line 60 contains a non-breaking space between Setup and python. The generated anchor does not match the link. Replace the non-breaking space with a normal space.
full_gpu_inference_pipeline/README.md, Line 14 #pre-post-processing-on-gpu-vs-cpu does not match the heading at Line 143. The heading contains / and a trailing non-breaking space. Remove the trailing non-breaking space and use #prepost-processing-on-gpu-vs-cpu.

Two other missing paths need separate treatment:

  • federated_learning/breast_density_challenge/README.md, Line 143 links to downloaded predictions.json. The README explicitly says that the file becomes available after running the download script. This is not a missing committed file, but the link cannot work when browsing GitHub.
  • microscopy/multichannel_microscopy_classification.ipynb, cell 11 links to ./rxrx1_subset_monai/README.md#metadata. That path is absent from the checkout. It needs a check against the downloaded dataset before selecting a replacement.

Scope: This was a static local-link check, not a complete external-link audit. I did not request the 569 unique external URLs, execute notebooks, or fully validate renderer-specific notebook anchors. The results do not establish that every other link works.

You are interacting with an AI system.

@ericspod

Copy link
Copy Markdown
Member

Hi @pratikgx thanks for these fixes. I asked coderabbit and there's a few more things that could be addressed, would you be able to do those in this PR as well?

…_pipeline anchors, deepgrow stale link

Signed-off-by: Pratik Gandhi <travpreneur@gmail.com>
@pratikgx

Copy link
Copy Markdown
Contributor Author

@ericspod Thanks! Done in the latest commit: removed the stray code fence in deployment/Triton/README.md (so ## Examples renders and #examples works), fixed the [Quick Start] (#quick-start) link, replaced the non-breaking spaces in the two full_gpu_inference_pipeline/README.md headings and fixed the #prepost-processing-on-gpu-vs-cpu anchor, and removed the link to the deleted deepgrow/ignite/handler.py. I left the maisi_train_controlnet_tutorial.ipynb link out because editing the notebook would trigger the notebook runner in CI. Happy to add it if you prefer. The predictions.json and rxrx1_subset_monai links point to files that only exist after a download, so I left those as they are.

@ericspod

Copy link
Copy Markdown
Member

Hi @pratikgx go ahead and fix the notebook issue, the tests shouldn't take too long to run and it's best to get it done now before we forget. Thanks!

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.

2 participants