Skip to content

Commit

Permalink
chore(ci/docs): nitpicky check (#142)
Browse files Browse the repository at this point in the history
* chore(ci/docs): nitpicky check

* chore(ci): ignore jaxtyping references

* chore(ci): actually ignore everything from jaxtyping

* fix(docs): some broken refs are fixed

* fix(ci): press F

* fixes

* fix(docs): all references are fixed!!

* chore(docs): fix redirect error
  • Loading branch information
jeertmans authored Oct 13, 2024
1 parent 879bb11 commit ded6edc
Show file tree
Hide file tree
Showing 14 changed files with 73 additions and 48 deletions.
4 changes: 2 additions & 2 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
condense_wildcard_suffixes = true
error_on_line_overflow = true
error_on_line_overflow = false
error_on_unformatted = true
force_multiline_blocks = true
format_code_in_doc_comments = true
Expand All @@ -12,4 +12,4 @@ normalize_doc_attributes = true
reorder_modules = true
style_edition = "2024"
unstable_features = true
wrap_comments = true
wrap_comments = false # This breaks Python docstring
20 changes: 7 additions & 13 deletions differt-core/src/geometry/triangle_mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,21 @@ impl TriangleMesh {

#[pymethods]
impl TriangleMesh {
/// jaxtyping.Float[np.ndarray, 'num_vertices 3']: The array of triangle
/// vertices.
/// ``Float[np.ndarray, 'num_vertices 3']``: The array of triangle vertices.
#[getter]
fn vertices<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray2<f32>> {
let array = arr2(&self.vertices);
PyArray2::from_owned_array_bound(py, array)
}

/// jaxtyping.Int[np.ndarray, 'num_triangles 3']: The array of triangle
/// indices.
/// ``Int[np.ndarray, 'num_triangles 3']``: The array of triangle indices.
#[getter]
fn triangles<'py>(&self, py: Python<'py>) -> Bound<'py, PyArray2<usize>> {
let array = arr2(&self.triangles);
PyArray2::from_owned_array_bound(py, array)
}

/// jaxtyping.Float[numpy.ndarray, 'num_vertices 3'] | None: The array of
/// face colors.
/// ``Float[np.ndarray, 'num_vertices 3']`` | :data:`None`: The array of face colors.
///
/// The array contains the face colors, as RGB triplets,
/// with a black color used as defaults (if some faces have a color).
Expand All @@ -150,11 +147,10 @@ impl TriangleMesh {
None
}

/// jaxtyping.Int[numpy.ndarray, 'num_vertices'] | None: The array of face
/// materials.
/// ``Int[np.ndarray, 'num_vertices']`` | :data:`None`: The array of face materials.
///
/// The array contains the material indices,
/// with a special placeholder value of :data:`-1`.
/// with a special placeholder value of ``-1``.
/// The obtain the name of the material, see :attr:`material_names`.
/// This attribute is :data:`None` if all face materials are unset.
#[getter]
Expand All @@ -165,8 +161,7 @@ impl TriangleMesh {
None
}

/// jaxtyping.Int[numpy.ndarray, 'num_objects 2'] | None: The array of
/// object indices.
/// ``Int[np.ndarray, 'num_objects 2']`` | :data:`None`: The array of object indices.
///
/// If the present mesh contains multiple objects, usually as a result of
/// appending multiple meshes together, this array contain start end end
Expand All @@ -180,8 +175,7 @@ impl TriangleMesh {
None
}

/// Move all the elements of ``other`` into ``self`` and update
/// :attr:`object_bounds`.
/// Move all the elements of ``other`` into ``self`` and update :attr:`object_bounds`.
///
/// After calling this method, ``other`` will be empty.
///
Expand Down
9 changes: 3 additions & 6 deletions differt-core/src/scene/sionna.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use indexmap::IndexMap;
use pyo3::{exceptions::PyValueError, prelude::*, types::PyType};
use serde::{Deserialize, de};

/// A scene as loaded from a Sionna-compatible
/// XML file.
/// A scene as loaded from a Sionna-compatible XML file.
///
/// Only a subset of the XML file is actually used.
///
Expand All @@ -19,14 +18,12 @@ use serde::{Deserialize, de};
#[pyclass(get_all)]
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct SionnaScene {
/// dict[str, Material]: A mapping between material IDs and actual
/// materials.
/// dict[str, Material]: A mapping between material IDs and actual materials.
///
/// Currently, only BSDF materials are used.
#[serde(rename = "bsdf", deserialize_with = "deserialize_materials")]
pub(crate) materials: IndexMap<String, Material>,
/// dict[str, Shape]: A mapping between shape IDs and actual
/// shapes.
/// dict[str, Shape]: A mapping between shape IDs and actual shapes.
///
/// Currently, only shapes from files are supported.
///
Expand Down
4 changes: 1 addition & 3 deletions differt-core/src/scene/triangle_scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ use pyo3::{exceptions::PyValueError, prelude::*, types::PyType};
use super::sionna::SionnaScene;
use crate::geometry::triangle_mesh::TriangleMesh;

/// A scene that contains one mesh, usually begin the results of multiple call
/// to :meth:`TriangleMesh.append<differt_core.geometry.triangle_mesh.
/// TriangleMesh.append>`.
/// A scene that contains one mesh, usually begin the results of multiple call to :meth:`TriangleMesh.append<differt_core.geometry.triangle_mesh.TriangleMesh.append>`.
///
/// This class is only useful to provide a fast constructor for scenes
/// created using the Sionna file format.
Expand Down
4 changes: 2 additions & 2 deletions differt/src/differt/geometry/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def path_length(self) -> int:
@property
@jax.jit
@jaxtyped(typechecker=typechecker)
def num_valid_paths(self) -> Int[ArrayLike, ""]:
def num_valid_paths(self) -> Int[ArrayLike, " "]:
"""The number of paths kept by :attr:`mask`.
If :attr:`mask` is not :data:`None`, then the output value can be traced by JAX.
Expand Down Expand Up @@ -210,7 +210,7 @@ def multipath_clusters(
By default, the last axis is used to match the
``num_path_candidates`` axis as returned by
:meth:`TriangleScene.compute_paths<differt.scene.triangle_scene.TriangleScene.compute_paths`.
:meth:`TriangleScene.compute_paths<differt.scene.triangle_scene.TriangleScene.compute_paths>`.
Returns:
The array of group indices.
Expand Down
2 changes: 1 addition & 1 deletion differt/src/differt/geometry/triangle_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class TriangleMesh(eqx.Module):
"""The array of face materials.
The array contains the material indices,
with a special placeholder value of :data:`-1`.
with a special placeholder value of ``-1``.
The obtain the name of the material, see :attr:`material_names`.
This attribute is :data:`None` if all face materials are unset.
"""
Expand Down
4 changes: 2 additions & 2 deletions differt/src/differt/plotting/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ def draw_image(
the image.
z0: The z-coordinate at which the image is placed.
kwargs: Keyword arguments passed to
:class:`Mesh<vispy.scene.visuals.Image>`,
:class:`Image<vispy.scene.visuals.Image>`,
:meth:`contourf<mpl_toolkits.mplot3d.axes3d.Axes3D.contourf>`,
or :class:`Mesh3d<plotly.graph_objects.Surface>`, depending on the
backend.
Expand Down Expand Up @@ -631,7 +631,7 @@ def draw_contour( # noqa: PLR0917
levels: The levels at which the contour is drawn.
fill: Whether to fill the contour.
kwargs: Keyword arguments passed to
:class:`Mesh<vispy.scene.visuals.Isorcurve>`,
:class:`Isocurve<vispy.scene.visuals.Isocurve>`,
:meth:`contour<mpl_toolkits.mplot3d.axes3d.Axes3D.contour>`,
(or :meth:`contourf<mpl_toolkits.mplot3d.axes3d.Axes3D.contourf>`
if ``fill`` is :data:`True`),
Expand Down
4 changes: 2 additions & 2 deletions differt/src/differt/plotting/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def get_backend(backend: str | None = None) -> BackendName:
If :data:`None` is provided, then the default
backend is returned. Otherwise, the backend corresponding to
value of :data:`backend`.
value of ``backend``.
Args:
backend: The name of the backend to use, or
Expand Down Expand Up @@ -259,7 +259,7 @@ def dispatch(fun: Callable[P, T]) -> _Dispatcher[P, T]:
Notes:
Only the functions registered with ``register`` will be called.
The :data:`fun` argument wrapped inside :func:`dispatch` is
The ``fun`` argument wrapped inside :func:`dispatch` is
only used for documentation, but never called.
Examples:
Expand Down
8 changes: 4 additions & 4 deletions differt/src/differt/rt/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@
else:
from typing_extensions import Self

T = TypeVar("T")
_T = TypeVar("_T")


@typechecker
class SizedIterator(Iterator, Sized, Generic[T]):
class SizedIterator(Iterator, Sized, Generic[_T]):
"""A custom generatic class that is both :class:`Iterator<collections.abc.Iterator>` and :class:`Sized<collections.abc.Sized>`.
The main purpose of this class is to be able to use
Expand All @@ -76,14 +76,14 @@ class SizedIterator(Iterator, Sized, Generic[T]):

__slots__ = ("_iter", "_size")

def __init__(self, iter: Iterator[T], size: int | Callable[[], int]) -> None: # noqa: A002,D107
def __init__(self, iter: Iterator[_T], size: int | Callable[[], int]) -> None: # noqa: A002,D107
self._iter = iter
self._size = size

def __iter__(self) -> Self: # noqa: D105
return self

def __next__(self) -> T: # noqa: D105
def __next__(self) -> _T: # noqa: D105
return next(self._iter)

def __len__(self) -> int: # noqa: D105
Expand Down
12 changes: 6 additions & 6 deletions differt/src/differt/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

# Redefined here, because chex uses deprecated type hints
# TODO: fixme when google/chex#361 is resolved.
OptState = chex.Array | Iterable["OptState"] | Mapping[Any, "OptState"]
Ts = TypeVarTuple("Ts")
_OptState = chex.Array | Iterable["_OptState"] | Mapping[Any, "_OptState"]
_Ts = TypeVarTuple("_Ts")


@jax.jit
Expand Down Expand Up @@ -93,9 +93,9 @@ def sorted_array2(array: Shaped[Array, "m n"]) -> Shaped[Array, "m n"]:
@eqx.filter_jit
@jaxtyped(typechecker=None)
def minimize(
fun: Callable[[Num[Array, "*batch n"], *Ts], Num[Array, " *batch"]],
fun: Callable[[Num[Array, "*batch n"], *_Ts], Num[Array, " *batch"]],
x0: Num[Array, "*batch n"],
args: tuple[Unpack[Ts]] = (),
args: tuple[Unpack[_Ts]] = (),
steps: int = 1000,
optimizer: optax.GradientTransformation | None = None,
) -> tuple[Num[Array, "*batch n"], Num[Array, " *batch"]]:
Expand Down Expand Up @@ -216,9 +216,9 @@ def minimize(

@jaxtyped(typechecker=typechecker)
def f(
carry: tuple[Num[Array, "*batch n"], OptState],
carry: tuple[Num[Array, "*batch n"], _OptState],
_: None,
) -> tuple[tuple[Num[Array, "*batch n"], OptState], Num[Array, " *batch"]]:
) -> tuple[tuple[Num[Array, "*batch n"], _OptState], Num[Array, " *batch"]]:
x, opt_state = carry
loss, grads = f_and_df(x, *args)
updates, opt_state = optimizer.update(grads, opt_state)
Expand Down
4 changes: 2 additions & 2 deletions docs/source/batch_axes.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ the size of some dimensions can rapidly become so large than they
cannot fit inside your memory.
This is also why we propose chunked iterators
(e.g.,
{class}`AllPathsFromCompleteGraphChunksIter<differt.rt.graph.AllPathsFromCompleteGraphChunksIter>`)
{class}`AllPathsFromCompleteGraphChunksIter<differt_core.rt.graph.AllPathsFromCompleteGraphChunksIter>`)
as an alternative.

Likewise, when a dimension is getting too big,
Expand All @@ -115,7 +115,7 @@ bottleneck in your pipeline. In some cases,
if you are only interested in a *reduced* result,
JAX may be able to optimize the computation such that some batch
dimensions are never allocated.
See [jax#1929](https://github.com/google/jax/issues/1923) for reference.
See [jax#1929](https://github.com/jax-ml/jax/issues/1923) for reference.

In general, finding the optimum is a trial-and-error process,
where the solution will highly depend on your problem parameters.
42 changes: 39 additions & 3 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
from datetime import date
from typing import Any

from docutils.nodes import Element, TextElement
from sphinx.addnodes import pending_xref
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
from sphinx.ext.intersphinx import missing_reference

from differt import __version__
from differt.scene.sionna import download_sionna_scenes
Expand Down Expand Up @@ -55,6 +59,23 @@
add_module_names = False
add_function_parentheses = False

nitpicky = True
nitpick_ignore = (
("py:class", "Array"),
("py:class", "differt.plotting._utils._Dispatcher"),
("py:class", "differt.utils.TypeVarTuple"),
("py:class", "jax._src.typing.SupportsDType"),
("py:class", "ndarray"), # From ArrayLike
("py:mod", "equinox"),
("py:mod", "jaxtyping"),
("py:obj", "differt.utils._T"),
("py:obj", "differt.rt.utils._T"),
)
nitpick_ignore_regex = (
(r"py:.*", r"equinox\..*"),
(r"py:.*", r"jaxtyping\..*"),
)

# -- Intersphinx mapping

intersphinx_mapping = {
Expand Down Expand Up @@ -179,9 +200,6 @@

# Patches

# TODO: fix Plotly's Figure not linking to docs with intersphinx,
# reported here https://github.com/sphinx-doc/sphinx/issues/12360.


def fix_sionna_folder(_app: Sphinx, obj: Any, _bound_method: bool) -> None:
"""
Expand All @@ -200,7 +218,25 @@ def fix_sionna_folder(_app: Sphinx, obj: Any, _bound_method: bool) -> None:
obj.__signature__ = sig.replace(parameters=parameters)


def fix_reference(
app: Sphinx, env: BuildEnvironment, node: pending_xref, contnode: TextElement
) -> Element | None:
"""
Fix some intersphinx references that are broken.
"""
if node["refdomain"] == "py":
if node["reftarget"] == "plotly.graph_objs._figure.Figure":
node["reftarget"] = "plotly.graph_objects.Figure"
else:
return None

return missing_reference(app, env, node, contnode)

return None


def setup(app: Sphinx) -> None:
download_sionna_scenes() # Put this here so that download does not occur during notebooks execution

app.connect("autodoc-before-process-signature", fix_sionna_folder)
app.connect("missing-reference", fix_reference)
2 changes: 1 addition & 1 deletion docs/source/notebooks/advanced_path_tracing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@
"Recalling the graph analogy we mentioned above, we can implement this behavior by disconnecting some primitives (i.e., triangles) in the graph.\n",
"There is no unique solution to this challenge, but we still provide a small utility to estimate the visibility matrix of a given scene: <TODO>.\n",
"\n",
"Then, from this visibility matrix, which is actually just an adjacency matrix, we can instantiate a {class}`DiGraph<differt.rt.graph.DiGraph>` from the {mod}`differt.rt.graph` module.\n",
"Then, from this visibility matrix, which is actually just an adjacency matrix, we can instantiate a {class}`DiGraph<differt_core.rt.graph.DiGraph>` from the {mod}`differt_core.rt.graph` module.\n",
"\n",
"[^1]: The first node to be visited can be any of the `num_triangles` nodes. For the next nodes, we will have to choose between `num_triangles - 1` nodes, because we do not allow for loops (i.e., cycles) in our graph."
]
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ search = "version: v{current_version}"
builtin = "clear,rare,informal,usage,names,en-GB_to_en-US"
check-hidden = true
ignore-words-list = "crate,ue"
skip = "docs/source/conf.py,pyproject.toml,uv.lock"
skip = "docs/source/conf.py,docs/source/notebooks/multipath.ipynb,pyproject.toml,uv.lock"

[tool.coverage.report]
exclude_lines = [
Expand Down

0 comments on commit ded6edc

Please sign in to comment.