diff --git a/.gitignore b/.gitignore index 40da2fd36..9dc86c573 100644 --- a/.gitignore +++ b/.gitignore @@ -65,13 +65,6 @@ instance/ # Scrapy stuff: .scrapy -# Sphinx documentation -docs/source/api/ -docs/source/release/ -docs/source/releases.rst -docs/build/ -docs/_tags/ - # PyBuilder target/ @@ -139,24 +132,25 @@ windows/ napari/_version.py -docs/api/napari* -docs/_build +napari/settings/napari.schema.json # built in setup.py napari/view_layers.pyi napari/components/viewer_model.pyi -# Autogenerated documentation -docs/images/_autogenerated/ +# Sphinx documentation +docs/_build +docs/_tags/ +docs/api/napari* +docs/gallery/ docs/guides/preferences.md docs/guides/_layer_events.md -docs/guides/_viewer_events.md docs/guides/_layerlist_events.md +docs/guides/_viewer_events.md +docs/images/_autogenerated/ +docs/jupyter_execute/ +docs/sg_execution_times.rst + # come from npe2 docs docs/plugins/_npe2_*.md - -napari/settings/napari.schema.json - -docs/jupyter_execute/ -docs/.jupyter_cache/ -docs/gallery/ +npe2/ diff --git a/Makefile b/Makefile index 5635adf4c..af9d6c513 100644 --- a/Makefile +++ b/Makefile @@ -27,10 +27,10 @@ prep-docs: python $(docs_dir)/_scripts/prep_docs.py docs-build: prep-docs - NAPARI_APPLICATION_IPY_INTERACTIVE=0 sphinx-build -b html docs/ docs/_build -D sphinx_gallery_conf.examples_dirs=$(GALLERY_PATH) $(SPHINXOPTS) + NAPARI_CONFIG="" NAPARI_APPLICATION_IPY_INTERACTIVE=0 sphinx-build -b html docs/ docs/_build -D sphinx_gallery_conf.examples_dirs=$(GALLERY_PATH) $(SPHINXOPTS) docs-xvfb: prep-docs - NAPARI_APPLICATION_IPY_INTERACTIVE=0 xvfb-run --auto-servernum sphinx-build -b html docs/ docs/_build -D sphinx_gallery_conf.examples_dirs=$(GALLERY_PATH) $(SPHINXOPTS) + NAPARI_CONFIG="" NAPARI_APPLICATION_IPY_INTERACTIVE=0 xvfb-run --auto-servernum sphinx-build -b html docs/ docs/_build -D sphinx_gallery_conf.examples_dirs=$(GALLERY_PATH) $(SPHINXOPTS) docs: clean docs-install docs-build diff --git a/docs/_toc.yml b/docs/_toc.yml index 627dff03a..65937565e 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -133,6 +133,12 @@ subtrees: subtrees: - entries: - file: developers/contributing + - file: developers/architecture/index + subtrees: + - entries: + - file: developers/architecture/dir_organization + - file: developers/architecture/napari_models + - file: developers/architecture/app_model - file: naps/index subtrees: - maxdepth: 1 diff --git a/docs/guides/app_model.md b/docs/developers/architecture/app_model.md similarity index 99% rename from docs/guides/app_model.md rename to docs/developers/architecture/app_model.md index 2df2d7326..55e7ee407 100644 --- a/docs/guides/app_model.md +++ b/docs/developers/architecture/app_model.md @@ -1,3 +1,5 @@ +(app-model)= + # napari's application model ```{important} @@ -260,7 +262,7 @@ Some Points The fact that `injected_func` may now be called without parameters allows it to be used easily as a command in a menu, or bound to a keybinding. It is up to -`napari` to determine what providers it will make available, and what type hints +napari to determine what providers it will make available, and what type hints plugins/users may use to request dependencies. ## Motivation & Future Vision diff --git a/docs/developers/architecture/dir_organization.md b/docs/developers/architecture/dir_organization.md new file mode 100644 index 000000000..4bc48bd64 --- /dev/null +++ b/docs/developers/architecture/dir_organization.md @@ -0,0 +1,96 @@ +(napari-directory-organization)= + +# napari directory organization + +The majority of the napari code lives in +[`napari/`](https://github.com/napari/napari/tree/main/napari). The main +folders are: + +``` +napari/ +├── _app_model/ +├── _qt/ +├── _tests/ +├── _vendor/ +├── _vispy/ +├── benchmarks/ +├── components/ +├── errors/ +├── layers/ +├── plugins/ +├── qt/ +├── resources/ +├── settings/ +└── utils/ +``` + +* Folders beginning with `_` represent private code, that is not part of the public + API. + * Similarly, files beginning with `_` within folders are not considered part + of the public API. +* Information on organization of test files can be found in [](test-organization). + +Notable folders in the root directory: + +* [`examples/`](https://github.com/napari/napari/tree/main/examples) folder + contains the source [examples gallery](https://napari.org/gallery) files. + The code in these files are executed and outputs captured when building the gallery. + See [](docs_contributing_guide) for details on napari` documentation. +* [`.github/`](https://github.com/napari/napari/tree/main/.github) contains + our [GitHub Actions](https://docs.github.com/en/actions) + [continuous integration (CI)](https://en.wikipedia.org/wiki/Continuous_integration) + workflows. The majority of our CI workflows are run using GitHub Actions. + +## Qt separation + +[Qt](https://doc.qt.io/) is a C++ framework to build graphical user interfaces (GUIs) +that is available in Python from a number of libraries, such as +[PyQt5](https://www.riverbankcomputing.com/static/Docs/PyQt5/). +Napari uses Qt to build its GUI, but we want to remain flexible to offer other GUI +frameworks (such as a web-based GUI) in the future. Therefore, +we try to confine code that directly imports Qt (currently the only supported GUI +backend) to the folders `_qt/` and `_vispy/`. Sometimes this means that +code needs to be split in order to place the Qt part inside `_qt/`. For example, +some of the `Action` menu items in the **View** menu require Qt. These live in +`napari/_qt/_qapp_model/qactions/_view.py` while the `Action` menu items that +do not require Qt live in `napari/_app_model/actions/_view_actions.py`. +Notice how the folder structure inside `_qt/` tries to mirror the structure of +`napari/`, with 'q' being added to the start of folders and files (e.g., `_app_model` +is named `_qapp_model` inside `_qt/`). + +## Folder summary + +* `_app_model/` - the code here relates to [app-model](app-model) and defines + menu item `Actions`, providers and processors and context keys. Any Qt parts + live in `napari/_qt/_qapp_model`. +* `_qt/` - here we define all the visual elements of napari including layer controls, + menus, vispy canvas and dialogs. Any code that directly imports GUI also lives here. +* `_vendor/` - code vendored from other projects. This may have been because we only + wanted to use a small part of a library and did not want to add another dependency. + We may also have wanted to use changes in an upstream package before it has + been released. +* `_vispy/` - code here defines how layers and their metadata are displayed on the + canvas (the canvas is a vispy object onto which you can draw 'visuals'). +* `benchmarks/` - benchmarking code, mostly for checking the performance of layers. + It is is executed in CI and is run every Sunday. See + [`.github/workflows/benchmarks.yml`](https://github.com/napari/napari/tree/main/.github/workflows/benchmarks.yml) + for CI workflow details. The benchmarks can also be run locally. +* `components/` - code that defines all components of the napari viewer, including the + layerlist, dimensions and camera. +* `errors/` - custom napari errors (that inherit from built-in errors) are defined + here. Currently we only have reader related custom errors. +* `layers/` - defines the classes, utilities, keybinding and mouse binding for + each [layer type](using-layers). +* `plugins/` - the code here deals with registering, activating and deactivating + plugins. It also handles ingesting plugin contributions to achieve the desired + effect in viewer (e.g., widget contributions should add a widget to the napari + viewer). + Code that defines the specification for each plugin contribution, the plugin + manifest and defines plugin manager (a class that manages the currently installed + plugins and their contribitions) lives in its own repo: + [`npe2`](https://github.com/napari/npe2). +* `qt/` - public utilities that directly rely on Qt, such as the progress bar + and the [thread worker](multithreading-in-napari). +* `resources/` - stores icons for buttons in the viewer. +* `settings/` - code that defines and manages napari user settings. +* `utils/` - commonly used classes and functions imported in variety of places. diff --git a/docs/developers/architecture/index.md b/docs/developers/architecture/index.md new file mode 100644 index 000000000..402a8fac9 --- /dev/null +++ b/docs/developers/architecture/index.md @@ -0,0 +1,13 @@ +(architecture-index)= + +# napari architecture guide + +These pages provide a guide to the napari software architecture +and is aimed at contributors who would like a better understanding of the napari +code base. For advanced napari usage documentation, see [](explanations). + +- [](napari-directory-organization): Guide to the napari directory organization. +- [](napari-model-event): Explains napari python models and how they are + connected to Qt classes and Vispy classes. +- [](app-model): Explains the napari application model, a declarative schema for + keeping track of commands, menus and keybindings of the napari GUI. diff --git a/docs/guides/napari_models.md b/docs/developers/architecture/napari_models.md similarity index 94% rename from docs/guides/napari_models.md rename to docs/developers/architecture/napari_models.md index ac3dcf715..2511d45f5 100644 --- a/docs/guides/napari_models.md +++ b/docs/developers/architecture/napari_models.md @@ -1,14 +1,16 @@ -# Napari models and events +(napari-model-event)= + +# napari models and events This document explains the links between the three main components of napari: -python models, Qt classes and vispy classes, with code examples. This knowledge +Python models, Qt classes and vispy classes, with code examples. This knowledge is not necessary to use napari and is more aimed at developers interested in understanding the inner workings of napari. This document assumes you're familiar with basic usage of napari. The three main components: -* python models describing components in the napari application - these are able +* Python models describing components in the napari application - these are able to operate without the GUI interface and do not have any dependencies on user interface classes * this code lives in `napari/components` (utility objects) and @@ -19,19 +21,19 @@ The three main components: * vispy classes that handle rendering * the code for this is private and lives in `napari/_vispy` -The separation of the python models from viewer GUI code allows: +The separation of the Python models from viewer GUI code allows: * analysis plugins to be developed without worrying about the GUI aspect * napari to have the option to move away from the rendering backend currently used * tests to be easily run headlessly -* the python models to be run headlessly (see +* the Python models to be run headlessly (see [Running napari headlessly](../howtos/headless) for more) ## Python models and events -Commonly, python models in napari are classes that store information about their +Commonly, Python models in napari are classes that store information about their state as an attribute and are the "source of ground truth". When these attributes are changed an "event" needs to be emitted such that relevant observers of the model (such as other classes) can take the appropriate @@ -174,7 +176,7 @@ the Python model, which gets updated directly when a field is changed via the GUI. For example, below is a code snippet showing the `QtDims` class instantiating -with a reference to the python class `Dims` and registering the callback +with a reference to the Python class `Dims` and registering the callback `_update_display`: ```python diff --git a/docs/developers/testing.md b/docs/developers/testing.md index fdcd350cd..25f294cac 100644 --- a/docs/developers/testing.md +++ b/docs/developers/testing.md @@ -26,6 +26,8 @@ Unit tests are at the base of the pyramid because they are the easiest to write the quickest to run. The time and effort to implement and maintain tests increases from unit tests to integration and functional tests. +(test-organization)= + ## Test organization All of `napari` tests are located in folders named `_tests`. We keep our unit diff --git a/docs/tutorials/fundamentals/getting_started.md b/docs/tutorials/fundamentals/getting_started.md index 9d7151ec7..c8cb78c75 100644 --- a/docs/tutorials/fundamentals/getting_started.md +++ b/docs/tutorials/fundamentals/getting_started.md @@ -1,27 +1,29 @@ (getting_started)= -# How to launch napari +# How to launch `napari` -This tutorial assumes you have already installed napari. +This tutorial assumes you have already installed `napari`. For help with installation see our [installation tutorial](./installation). -This tutorial will teach you all the different ways to launch napari. -At the end of the tutorial you should be able to launch napari and see the viewer your favorite way. +This tutorial will teach you all the different ways to launch `napari`. +At the end of the tutorial you should be able to launch `napari` and see the viewer your favorite way. -## Launching napari +## Launching `napari` -There are four ways to launch the **napari** viewer: +There are four ways to launch the `napari` viewer: -- command line -- python script -- IPython console -- jupyter notebook +- [command line](launch-command) +- [python script](launch-script) +- [IPython console](launch-ipython) +- [jupyter notebook](launch-jupyter) -All four of these methods will launch the same napari viewer +All four of these methods will launch the same `napari` viewer but depending on your use-case different ones may be preferable. +(launch-command)= + ### Command line usage -To launch napari from the command line simply run +To launch `napari` from the command line simply run ```sh napari @@ -45,14 +47,20 @@ If the image is `RGB` or `RGBA` use the `-r` or `--rgb` flag. ![image: napari viewer displaying an image layer](../assets/tutorials/launch_cli_image.png) -Launching napari directly from the command line is the simplest and fastest way to open the viewer, +Launching `napari` directly from the command line is the simplest and fastest way to open the viewer, but it doesn't allow you to preprocess your images before opening them. It is also currently not possible to save images or other layer types directly from the viewer, but we'll be adding support for this functionality soon as discussed in [#379](https://github.com/napari/napari/issues/379). +If you wish to interact with your open viewer programmatically you can open an IPython +console via **Window** > **console** or clicking the 'Show/Hide IPython console' button +within the [viewer buttons](viewer-layout). + +(launch-script)= + ### Python script usage -To launch napari from a python script, inside your script you can import `napari`, +To launch `napari` from a python script, inside your script you can import `napari`, then create a {class}`Viewer` and {class}`Image` layer by adding some image data, using {func}`imshow`. The {class}`Viewer` is representative of the napari viewer GUI @@ -103,12 +111,18 @@ downloaded as `.py` (and `.ipynb` files) and run as above. ![image: napari launched from a python script](../assets/tutorials/launch_script.png) -An advantage of launching napari from a python script +An advantage of launching `napari` from a python script is that you can preprocess your images and add multiple layers before displaying the viewer. +As above, if you wish to interact with your open viewer programmatically you can open +an IPython console via **Window** > **console** or clicking the 'Show/Hide IPython +console' button within the [viewer buttons](viewer-layout). + +(launch-ipython)= + ### IPython console usage -To launch napari from an IPython console import `napari` and create a +To launch `napari` from an IPython console import `napari` and create a {class}`Viewer` and {class}`Image` object. ```python @@ -121,7 +135,7 @@ import napari viewer, image_layer = napari.imshow(cells3d()) ``` -Napari will automatically use the interactive [`%gui qt` event +`napari` will automatically use the interactive [`%gui qt` event loop](https://ipython.readthedocs.io/en/stable/config/eventloops.html#integrating-with-gui-event-loops) from IPython @@ -132,9 +146,11 @@ is that the you can continue to programmatically interact with the viewer from t including bidirectional communication, where code run in the console will update the current viewer and where data changed in the GUI will be accessible in the console. +(launch-jupyter)= + ### Jupyter notebook usage -You can also launch napari from a Jupyter notebook. The +You can also launch `napari` from a Jupyter notebook. The [examples gallery](../../gallery), as mentioned above, can also be downloaded as `.ipynb` which can be run from a Jupyter notebook. @@ -143,7 +159,7 @@ Below, we launch the [notebook example](https://github.com/napari/napari/tree/ma ![image: napari launched from a Jupyter notebook](../assets/tutorials/launch_jupyter.png) Similar to launching from the IPython console, -an advantage of launching napari from a Jupyter notebook +an advantage of launching `napari` from a Jupyter notebook is that you can continue to programmatically interact with the viewer from Jupyter notebook, including bidirectional communication, where code run in the notebook will update the current viewer and where data changed in the GUI will be accessible in the notebook. @@ -152,7 +168,7 @@ and where data changed in the GUI will be accessible in the notebook. To learn more about: -* how to use the napari viewer graphical user interface (GUI), +* how to use the `napari` viewer graphical user interface (GUI), checkout the [viewer tutorial](./viewer) -* how to use the napari viewer with different types of napari layers, see +* how to use the `napari` viewer with different types of `napari` layers, see [layers at a glance](../../guides/layers) diff --git a/docs/tutorials/fundamentals/viewer.md b/docs/tutorials/fundamentals/viewer.md index 17779cf32..c85339a06 100644 --- a/docs/tutorials/fundamentals/viewer.md +++ b/docs/tutorials/fundamentals/viewer.md @@ -82,6 +82,8 @@ Now we will continue exploring the rest of the viewer. +++ +(viewer-layout)= + ## Layout of the viewer The viewer is organized into a few key areas which are explained in the next sections: