Skip to content

Refactor Internal Modules Plan #40

Description

@jpfairbanks

Refactor CellularSheaves.jl into internal modules and add a Plots‑based package extension

Motivation

CellularSheaves.jl currently bundles a wide range of responsibilities in a single top‑level module:

  • Graph‑based sheaf representations & matrix constructions
  • A tiny DSL / parser for sheaf specifications
  • Specialized linear‑algebra utilities (factorisations, null‑space extraction, benchmarks)
  • Categorical abstractions (morphisms, push‑forward/pull‑back, push‑outs)
  • Trajectory and optimal‑control tools (controlled sheaves, LQR pipelines, visualisations)

While this monolithic layout works for a prototype, it makes the code harder to navigate, obscures the public API, and forces heavy optional dependencies (e.g. Plots.jl) on users that only need the core algebraic machinery.

The goal is not to publish separate packages, but to reorganise the source into well‑named internal sub‑modules while keeping a single meta‑package for backward compatibility. Plotting utilities will be provided via a Julia‑native package extension that activates only when Plots.jl is loaded.

Proposed Module Layout

CellularSheaves/
├─ Project.toml                # meta‑package (depends on core deps only)
├─ src/
│   ├─ CellularSheaves.jl      # top‑level module, re‑exports everything
│   ├─ NetworkSheaves/
│   │   └─ NetworkSheaves.jl   # vertex/edge stalks, coboundary, Laplacian, nullspace
│   ├─ SheafDSL/
│   │   └─ SheafDSL.jl        # parser / tiny DSL / ADT helpers
│   ├─ SheafLinAlg/
│   │   └─ SheafLinAlg.jl     # factorisations, sparse solvers, benchmarks
│   ├─ SheafCategories/
│   │   └─ SheafCategories.jl # morphism types, push‑forward/pull‑back, push‑out
│   ├─ SheafControl/
│   │   └─ SheafControl.jl    # ControlledTrajectorySheaf, LQR utilities, trajectory families
│   └─ ext/
│       └─ PlotsExt/
│           └─ PlotsExt.jl    # package‑extension stub (empty for now)
└─ test/

Each sub‑folder contains a single file that defines a sub‑module with the same name as the folder (module NetworkSheaves … end, etc.).
The top‑level CellularSheaves.jl includes these files and re‑exports their public symbols, preserving the current public API.

Naming

  • The graph‑sheaf core will be called NetworkSheaves (instead of “SheafGraph”).

Optional Plotting via Package Extensions

We will use Julia’s first‑class package‑extension mechanism (available since Julia 1.9) rather than the older Requires.jl approach.

  • Add an [extensions] entry in Project.toml:
[extensions]
PlotsExt = ["Plots"]
  • Create the stub extension in src/ext/PlotsExt/PlotsExt.jl:
module PlotsExt
using ..CellularSheaves   # gives us access to internal modules

function __init__()
    @info "CellularSheaves: Plots extension activated – plotting utilities will become available."
    # Future visualisation helpers (e.g. plot_laplacian, plot_trajectory) will be
    # placed in `src/ext/PlotsExt/plot_helpers.jl` and `include`‑d here.
end
end

No Plotting code is added yet; the extension will stay empty until we need it.


Documentation – one API page per sub‑module

The docs will be restructured so that each sub‑module gets its own markdown file under docs/src/api/:

  • api/network_sheaves.md
  • api/sheaf_dsl.md
  • api/sheaf_linalg.md
  • api/sheaf_categories.md
  • api/sheaf_control.md

Each page will start with a short narrative and then use an @docs block to pull in the docstrings from the corresponding sub‑module, e.g.:

# NetworkSheaves

This page documents the `NetworkSheaves` sub‑module, which implements the
graph‑theoretic representation of cellular sheaves, coboundary maps,
Laplacians, and null‑space extraction.

```@docs
NetworkSheaves.vertex_stalks
NetworkSheaves.edge_stalks
NetworkSheaves.coboundary_map
NetworkSheaves.sheaf_laplacian
NetworkSheaves.nullspace_ldlt
# …other exported symbols…

The `docs/make.jl` `makedocs` call will be updated to include these pages in the “API Reference” section:

```julia
makedocs(
    modules = [CellularSheaves],
    format = Documenter.HTML(),
    sitename = "CellularSheaves.jl",
    doctest = false,
    checkdocs = :none,
    warnonly = [:cross_references],
    pages = Any[
        "CellularSheaves.jl" => "index.md",
        "Examples" => [
            # generated examples unchanged
        ],
        "Feature Guides" => [
            # core feature pages
        ],
        "API Reference" => [
            "api/network_sheaves.md",
            "api/sheaf_dsl.md",
            "api/sheaf_linalg.md",
            "api/sheaf_categories.md",
            "api/sheaf_control.md",
        ],
    ]
)

The existing literate notebooks (docs/literate/*.jl) can continue to use using CellularSheaves. If we wish to be more explicit we may write using CellularSheaves.NetworkSheaves etc., but that is optional – the current blanket import will still resolve the symbols.


Implementation Steps

Step Action Command / file edit
Create module directories mkdir -p src/NetworkSheaves src/SheafDSL src/SheafLinAlg src/SheafCategories src/SheafControl src/ext/PlotsExt
Move source files e.g. mv src/network_sheaves/* src/NetworkSheaves/ (adjust imports)
Wrap each file in module … end Add module NetworkSheaves … end etc.
Update internal using statements Replace using CellularSheaves inside sub‑modules with relative imports (using ..NetworkSheaves, using ..SheafLinAlg, …).
Top‑level re‑exports Edit src/CellularSheaves.jl as shown above.
Add extension stub Create src/ext/PlotsExt/PlotsExt.jl with the tiny module PlotsExt … end.
Declare extension in Project.toml Add [extensions] PlotsExt = ["Plots"].
Create API docs Add docs/src/api/*.md files (copy the template shown).
Update docs/make.jl Replace the pages= block with the version above.
Run the full test suite julia --project=. -e 'using Pkg; Pkg.test()'.
Build the docs julia --project=docs -e 'ENV["JULIA_DOC_EXAMPLES"]=false; include("docs/make.jl")'. Verify no “EditURL” errors appear.
Commit & push Open a PR titled “Refactor into internal modules + package‑extension stub”.

Open Questions / Discussion

  • Export policy: Should we re‑export all symbols from each sub‑module at the top‑level (preserving the current API) or only a curated subset?
  • Naming of the DSL module: Do we keep the short name SheafDSL or prefer something like SheafParser?
  • Future plotting API: When visualisation functions are added, should they be exported from the extension (CellularSheaves.plot_laplacian) or live under CellularSheaves.PlotsExt? (My preference is to re‑export them from the top‑level once the extension is loaded, so users can just call CellularSheaves.plot_laplacian).
  • Testing strategy: Do we want separate test suites for each sub‑module (e.g. test/NetworkSheaves, test/SheafControl), or a single runtests.jl that exercises everything?

Benefits

  • Clearer code organization – each logical concern lives in its own module.
  • Optional heavy dependenciesPlots.jl is only pulled in via the extension.
  • Improved documentation – users can navigate directly to the API of the sub‑module they care about.
  • Future‑proof – adding more optional extensions (e.g. Makie.jl, GraphPlot.jl) will follow the same pattern.

Please review the plan and let me know if any adjustments are required. Once we have consensus, I will create the branch, add the skeleton files, and open the PR.

Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions