Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,9 @@ def setup(app):
ogp_site_name = "PyKale Tutorials"
ogp_description_length = 200

# sphinx-favicon: reuse the PyKale mark (served from _static).
# Use the compact PyKale mark for browser tabs; the wide logo remains in the navbar.
favicons = [
{"href": "pykale_logo.png"},
{"href": "pykale_favicon.png"},
]

# sphinx-notfound-page: absolute URLs on the 404 so links work from any depth.
Expand Down
60 changes: 24 additions & 36 deletions index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Learn with PyKale
<div class="pky-hero-cta">
<a class="pky-btn pky-btn-primary" href="pages/getting-started.html">Start learning</a>
<a class="pky-btn pky-btn-ghost" href="pages/all-tutorials.html">Browse tutorials</a>
<a class="pky-btn pky-btn-ghost" href="https://github.com/pykale/pykale"
<a class="pky-btn pky-btn-ghost" href="https://github.com/pykale/tutorials"
target="_blank" rel="noopener">View on GitHub ↗</a>
</div>
</div>
Expand All @@ -37,52 +37,37 @@ Learn with PyKale
</div>
</section>

What's new
----------
.. raw:: html

.. include:: _generated/news.rst
<div class="pky-home-overview">

Get started
-----------

.. grid:: 1 2 2 4
:gutter: 3
:class-container: pky-getstarted

.. grid-item-card:: 1 · Install PyKale
:link: https://github.com/pykale/pykale#installation

``pip install pykale`` — then you are ready to run any tutorial.

.. grid-item-card:: 2 · Run your first tutorial
:link: _pages/others
:link-type: doc
.. container:: pky-start-steps

Domain adaptation on digit images: the recommended starting point.
1. **Install PyKale.** Run ``pip install pykale``. :doc:`Setup guide <pages/getting-started>`
2. **Try the first tutorial.** :doc:`Domain adaptation on digit images
</_gallery/others/image_classification/digit_domain_adaptation/plot_digit_domain_adaptation>`
is the recommended starting point.
3. **Find your next topic.** :doc:`Browse all tutorials <pages/all-tutorials>` or
:doc:`follow a learning path <pages/learning-paths>`.

.. grid-item-card:: 3 · Explore a domain
:link: pages/all-tutorials
:link-type: doc
What's new
----------

Browse by Protein, Cancer, Cardiac, Materials or Others.
.. include:: _generated/news.rst

.. grid-item-card:: 4 · Adapt it to your data
:link: CONTRIBUTING
:link-type: doc
.. raw:: html

Every tutorial ships its full script — fork it and point it at your own dataset.
</div>

Featured learning paths
-----------------------

Curated routes through the tutorials, using the catalogue's own metadata.

.. include:: _generated/paths.rst

Browse by domain
----------------
Choose a route, then follow its tutorials in order.

.. include:: _generated/domains.rst
.. include:: _generated/featured_paths.rst

Browse all tutorials
--------------------
Expand All @@ -91,20 +76,23 @@ Filter the full catalogue by domain, task, modality, difficulty, runtime and sta

.. raw:: html

<div id="pky-catalog" class="pky-catalog" data-src="_static/tutorials.json">
<div id="pky-catalog" class="pky-catalog" data-home data-src="_static/tutorials.json">
<div class="pky-catalog-controls">
<div class="pky-search">
<label for="pky-q" class="pky-visually-hidden">Search tutorials</label>
<input id="pky-q" type="search" placeholder="Search tutorials…" autocomplete="off">
</div>
<div id="pky-facets" class="pky-facets" role="group" aria-label="Filters"></div>
<details class="pky-filter-details" open>
<summary id="pky-filter-summary">Filters</summary>
<div id="pky-facets" class="pky-facets" role="group" aria-label="Filters"></div>
</details>
<button id="pky-clear" class="pky-btn pky-btn-ghost pky-clear" type="button">Clear filters</button>
</div>
<p id="pky-count" class="pky-count" role="status" aria-live="polite"></p>
<div id="pky-grid" class="pky-grid"></div>
<p id="pky-empty" class="pky-empty" hidden>No tutorials match these filters.</p>
<noscript>
<p>Enable JavaScript to filter, or browse the domains above.</p>
<p>Enable JavaScript to filter, or use the Domains menu to browse tutorials.</p>
</noscript>
</div>

Expand All @@ -128,7 +116,7 @@ Contributing
See which narratives are still drafts and pick one to write.

.. grid-item-card:: Report an issue
:link: https://github.com/pykale/pykale/issues
:link: https://github.com/pykale/tutorials/issues

Something wrong or unclear? Open an issue.

Expand Down
2 changes: 1 addition & 1 deletion pages/about.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ What this is

Each tutorial is a self-contained folder: a narrated ``plot_<slug>.py`` that reads top to bottom and
builds into a notebook, plus the full ``main.py`` experiment it is drawn from. Tutorials are
organised by the domain that owns them — General, Protein, Cancer, Cardiac and Materials — and every
organised by the domain that owns them — Others, Protein, Cancer, Cardiac and Materials — and every
tutorial carries structured metadata (task, modality, difficulty, runtime, status) that drives the
filters, learning paths and status page.

Expand Down
5 changes: 4 additions & 1 deletion pages/all-tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ count and URL update as you go, so a filtered view can be shared.
<label for="pky-q" class="pky-visually-hidden">Search tutorials</label>
<input id="pky-q" type="search" placeholder="Search tutorials…" autocomplete="off">
</div>
<div id="pky-facets" class="pky-facets" role="group" aria-label="Filters"></div>
<details class="pky-filter-details" open>
<summary id="pky-filter-summary">Filters</summary>
<div id="pky-facets" class="pky-facets" role="group" aria-label="Filters"></div>
</details>
<button id="pky-clear" class="pky-btn pky-btn-ghost pky-clear" type="button">Clear filters</button>
</div>
<p id="pky-count" class="pky-count" role="status" aria-live="polite"></p>
Expand Down
4 changes: 1 addition & 3 deletions pages/learning-paths.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
Learning paths
==============

Curated routes through the tutorials. Each path is an ordered sequence — follow it top to bottom, or
jump to whichever step you need. Paths are defined in ``tutorial_catalog.yml`` and stay in sync with
the catalogue.
Choose a route that matches your goal. Follow its tutorials in order, or jump to the topic you need.

.. include:: /_generated/paths.rst
54 changes: 36 additions & 18 deletions scripts/generate_homepage.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,15 @@ def _gallery_doc(path: str) -> str:

def _news_rst() -> str:
items = yaml.safe_load(NEWS_FILE.read_text(encoding="utf-8")) or []
out = [".. grid:: 1 2 2 2", " :gutter: 3", " :class-container: pky-news", ""]
out = [".. container:: pky-news", ""]
for item in items:
badge = item.get("badge", "")
role = BADGE_ROLE.get(badge, "bdg-secondary")
badge_rst = f":{role}:`{badge}`" if badge else ""
out += [
" .. grid-item-card::",
" :class-card: pky-news-card",
"",
f" {badge_rst} **{item['title']}**",
"",
f" {' '.join(item['summary'].split())}",
]
content = f"{badge_rst} **{item['title']}** — {' '.join(item['summary'].split())}"
if item.get("link"):
out += ["", f" :doc:`{item.get('link_text', 'Learn more')} <{item['link']}>`"]
out.append("")
content += f" :doc:`{item.get('link_text', 'Learn more')} <{item['link']}>`"
out.append(f" - {content}")
return "\n".join(out) + "\n"


Expand Down Expand Up @@ -91,19 +84,42 @@ def _domains_rst() -> str:
def _paths_rst() -> str:
catalog = Catalog.load()
slug_to_path = catalog.slug_to_path()
out = [".. grid:: 1 2 2 2", " :gutter: 3", " :class-container: pky-paths", ""]
out: List[str] = []
for path_def in catalog.learning_paths:
steps: List[str] = []
out += [
f".. _learning-path-{path_def.id}:",
"",
path_def.title,
"-" * len(path_def.title),
"",
" ".join(path_def.summary.split()),
"",
]
for i, slug in enumerate(path_def.tutorials, 1):
meta = _meta(slug_to_path[slug])
steps.append(f" {i}. :doc:`{meta.title} <{_gallery_doc(slug_to_path[slug])}>`")
out.append(f"{i}. :doc:`{meta.title} <{_gallery_doc(slug_to_path[slug])}>`")
out.append("")
return "\n".join(out) + "\n"


def _featured_paths_rst() -> str:
catalog = Catalog.load()
slug_to_path = catalog.slug_to_path()
out = [".. grid:: 1 2 2 4", " :gutter: 2", " :class-container: pky-featured-paths", ""]
for path_def in catalog.learning_paths:
first = _meta(slug_to_path[path_def.tutorials[0]])
out += [
f" .. grid-item-card:: {path_def.title}",
" :class-card: pky-path-card",
f" :link: learning-path-{path_def.id}",
" :link-type: ref",
" :class-card: pky-featured-path",
"",
f" {' '.join(path_def.summary.split())}",
"",
*steps,
f" {len(path_def.tutorials)} tutorials · Starts with {first.title}",
"",
" +++",
" View path →",
"",
]
return "\n".join(out) + "\n"
Expand All @@ -128,6 +144,7 @@ def _ecosystem_rst() -> str:
def _status_table_rst() -> str:
"""A list-table of every tutorial's status, for the Tutorial Status page."""
catalog = Catalog.load()
domain_labels = {bucket.id.value: bucket.label for bucket in catalog.buckets}
rows = [
".. list-table::",
" :header-rows: 1",
Expand All @@ -145,9 +162,9 @@ def _status_table_rst() -> str:
status = "Draft" if meta.draft else "Written"
rows += [
f" * - :doc:`{meta.title} <{_gallery_doc(path)}>`",
f" - {meta.domain.value if meta.domain.value != 'others' else 'general'}",
f" - {domain_labels[meta.domain.value]}",
f" - {status}",
f" - {meta.difficulty.value}",
f" - {meta.difficulty.value.capitalize()}",
f" - {meta.estimated_runtime}",
]
return "\n".join(rows) + "\n"
Expand All @@ -159,6 +176,7 @@ def build() -> int:
"news.rst": _news_rst(),
"domains.rst": _domains_rst(),
"paths.rst": _paths_rst(),
"featured_paths.rst": _featured_paths_rst(),
"ecosystem.rst": _ecosystem_rst(),
"status_table.rst": _status_table_rst(),
}
Expand Down
21 changes: 5 additions & 16 deletions source/_data/news.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,18 @@
date: 2026-07-24
badge: New
summary: >-
Tutorials are now organised by the domain that owns them -- Protein, Cancer, Cardiac, Materials
and Others -- each with its own page and colour.
Browse tutorials by Protein, Cancer, Cardiac or general methods.

- title: Executable Sphinx-Gallery tutorials
date: 2026-07-24
badge: New
summary: >-
Every tutorial is a runnable script. The narrated version builds into a notebook and a
downloadable Python file. The executing CI build can be run manually; its nightly schedule is
currently disabled.
Each tutorial includes a runnable script. Narrated walkthroughs are being completed.

- title: Reference tutorial available
date: 2026-07-24
badge: Updated
summary: >-
Domain adaptation on digit images is fully written -- the recommended starting point for
transfer learning with PyKale.
link: _pages/others
link_text: Read it

- title: Materials domain
date: 2026-07-24
badge: Planned
summary: >-
A Materials domain is reserved for structure/property prediction and crystal descriptors.
Tutorials are in development.
The digit-image domain adaptation walkthrough is ready for first-time readers.
link: /_gallery/others/image_classification/digit_domain_adaptation/plot_digit_domain_adaptation
link_text: Read tutorial
Loading
Loading