diff --git a/.gitignore b/.gitignore index 643427c0..c4531a41 100644 --- a/.gitignore +++ b/.gitignore @@ -69,7 +69,9 @@ instance/ # Sphinx documentation doc/build/ +doc/examples/ doc/reference/generated/ +doc/sg_execution_times.rst # PyBuilder target/ diff --git a/MANIFEST.in b/MANIFEST.in index 2153cf7e..ffbdbf7b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -12,4 +12,5 @@ include setup.cfg include setup.py include diffsims/tests/**/*.npy -recursive-include doc Makefile make.bat *.rst *.py *.png \ No newline at end of file +recursive-include doc Makefile make.bat *.rst *.py *.png +recursive-include examples *.py *.rst \ No newline at end of file diff --git a/diffsims/libraries/diffraction_library.py b/diffsims/libraries/diffraction_library.py index b0c084e1..ba222156 100644 --- a/diffsims/libraries/diffraction_library.py +++ b/diffsims/libraries/diffraction_library.py @@ -172,7 +172,7 @@ def pickle_library(self, filename): See Also -------- - load_DiffractionLibrary() + load_DiffractionLibrary """ with open(filename, "wb") as handle: diff --git a/diffsims/libraries/vector_library.py b/diffsims/libraries/vector_library.py index f56860cd..35e5a096 100644 --- a/diffsims/libraries/vector_library.py +++ b/diffsims/libraries/vector_library.py @@ -42,7 +42,7 @@ def load_VectorLibrary(filename, safety=False): See Also -------- - VectorLibrary.pickle_library() + VectorLibrary.pickle_library """ if safety: with open(filename, "rb") as handle: @@ -92,7 +92,7 @@ def pickle_library(self, filename): See Also -------- - load_VectorLibrary() + load_VectorLibrary """ with open(filename, "wb") as handle: diff --git a/doc/Makefile b/doc/Makefile index ed880990..b687a144 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -14,6 +14,12 @@ help: .PHONY: help Makefile +clean: + rm -rf $(BUILDDIR) + rm -rf $(SOURCEDIR)/examples + rm -rf $(SOURCEDIR)/reference/generated + rm sg_execution_times.rst + # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile diff --git a/doc/_templates/custom-attribute-template.rst b/doc/_templates/custom-attribute-template.rst index c31bebe0..ea206ece 100644 --- a/doc/_templates/custom-attribute-template.rst +++ b/doc/_templates/custom-attribute-template.rst @@ -3,3 +3,6 @@ .. currentmodule:: {{ module }} .. autoproperty:: {{ objname }} + +.. minigallery:: {{ module }}.{{ objname }} + :add-heading: Examples using ``{{ objname }}`` diff --git a/doc/_templates/custom-class-template.rst b/doc/_templates/custom-class-template.rst index 8ada3fb0..8ea2b40f 100644 --- a/doc/_templates/custom-class-template.rst +++ b/doc/_templates/custom-class-template.rst @@ -7,12 +7,11 @@ {% block attributes %} {% if attributes %} .. rubric:: {{ _('Attributes') }} - .. autosummary:: :toctree: :template: custom-attribute-template.rst {% for item in attributes %} - {% if item.0 != item.upper().0 and item not in inherited_members %} + {% if item.0 != item.upper().0 %} {{ name }}.{{ item }} {% endif %} {%- endfor %} @@ -22,14 +21,16 @@ {% block methods %} {% if methods %} .. rubric:: {{ _('Methods') }} - .. autosummary:: :toctree: :template: custom-method-template.rst {% for item in methods %} - {% if item != "__init__" and item not in inherited_members %} + {% if item.0 != item.upper().0 %} {{ name }}.{{ item }} {% endif %} {%- endfor %} {% endif %} {% endblock %} + +.. minigallery:: {{ module }}.{{ objname }} + :add-heading: Examples using ``{{ objname }}`` diff --git a/doc/_templates/custom-function-template.rst b/doc/_templates/custom-function-template.rst index 5ffed09e..b109cab9 100644 --- a/doc/_templates/custom-function-template.rst +++ b/doc/_templates/custom-function-template.rst @@ -3,3 +3,6 @@ .. currentmodule:: {{ module }} .. autofunction:: {{ objname }} + +.. minigallery:: {{ module }}.{{ objname }} + :add-heading: Examples using ``{{ objname }}`` \ No newline at end of file diff --git a/doc/_templates/custom-method-template.rst b/doc/_templates/custom-method-template.rst index 306d2aab..3ebddf87 100644 --- a/doc/_templates/custom-method-template.rst +++ b/doc/_templates/custom-method-template.rst @@ -3,3 +3,6 @@ .. currentmodule:: {{ module }} .. automethod:: {{ objname }} + +.. minigallery:: {{ module }}.{{ objname }} + :add-heading: Examples using ``{{ objname }}`` \ No newline at end of file diff --git a/doc/_templates/custom-module-template.rst b/doc/_templates/custom-module-template.rst index 05d36cd7..f45d4f56 100644 --- a/doc/_templates/custom-module-template.rst +++ b/doc/_templates/custom-module-template.rst @@ -60,8 +60,8 @@ :toctree: :template: custom-module-template.rst :recursive: -{% for item in modules %} + {% for item in modules %} {{ item }} -{%- endfor %} + {%- endfor %} {% endif %} {% endblock %} diff --git a/doc/conf.py b/doc/conf.py index 0179cf6d..76a3cd7e 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -39,13 +39,14 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + "numpydoc", "sphinx.ext.autodoc", "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.linkcode", "sphinx.ext.mathjax", - "sphinx.ext.napoleon", "sphinx_design", + "sphinx_gallery.gen_gallery", ] # Create links to references within diffsims' documentation to these packages @@ -73,7 +74,7 @@ "github_url": "https://github.com/pyxem/diffsims", "header_links_before_dropdown": 6, "logo": {"alt_text": project, "text": project}, - "navigation_with_keys": False, + "navigation_with_keys": True, "show_toc_level": 2, "use_edit_page_button": True, } @@ -162,3 +163,42 @@ def linkcode_resolve(domain, info): autodoc_default_options = { "show-inheritance": True, } + +# -- Sphinx-Gallery--------------- +# https://sphinx-gallery.github.io +sphinx_gallery_conf = { + "backreferences_dir": "reference/generated", + "doc_module": ("diffsims",), + "examples_dirs": "../examples", # path to your example scripts + "gallery_dirs": "examples", # path to where to save gallery generated output + "filename_pattern": "^((?!sgskip).)*$", # pattern to define which will be executed + "reference_url": {"diffsims": None}, + "run_stale_examples": False, +} +autosummary_generate = True + + +# -- numpydoc +# https://numpydoc.readthedocs.io +numpydoc_show_class_members = False +numpydoc_use_plots = True +numpydoc_xref_param_type = True +# fmt: off +numpydoc_validation_checks = { + "all", # All but the following: + "ES01", # Not all docstrings need an extend summary + "EX01", # Examples: Will eventually enforce + "GL01", # Contradicts numpydoc examples + "GL02", # Appears to be broken? + "GL07", # Appears to be broken? + "GL08", # Methods can be documented in super class + "PR01", # Parameters can be documented in super class + "PR02", # Properties with setters might have docstrings w/"Returns" + "PR04", # Doesn't seem to work with type hints? + "RT01", # Abstract classes might not have return sections + "SA01", # Not all docstrings need a "See Also" + "SA04", # "See Also" section does not need descriptions + "SS06", # Not possible to make all summaries one line + "YD01", # Yields: No plan to enforce +} +# fmt: on diff --git a/doc/index.rst b/doc/index.rst index 26de4faa..a77c1dcb 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -13,6 +13,7 @@ diffsims is an open-source Python library for simulating diffraction. dev/index.rst changelog.rst + Installation ============ @@ -35,6 +36,7 @@ diffsims can be installed with `pip `__ or Further details are available in the :doc:`installation guide `. + Learning resources ================== @@ -48,7 +50,16 @@ Learning resources :octicon:`book;2em;sd-text-info` Tutorials ^^^ - In-depth guides for using diffsims. + In-depth guides for using diffsims (notebooks hosted on GitHub). + + .. grid-item-card:: + :link: examples/index + :link-type: doc + + :octicon:`zap;2em;sd-text-info` Examples + ^^^ + + Short examples illustrating simple tasks that can be performed with diffsims. .. grid-item-card:: :link: reference/index @@ -69,6 +80,7 @@ Learning resources diffsims is a community project maintained for and by its users. There are many ways you can help! + Citing diffsims =============== diff --git a/doc/user/index.rst b/doc/user/index.rst index 3a85f3b2..f976ea83 100644 --- a/doc/user/index.rst +++ b/doc/user/index.rst @@ -2,15 +2,19 @@ User guide ========== -See the `demos `_ for how to -use diffsims. - .. toctree:: :caption: Getting started :maxdepth: 1 installation.rst +.. toctree:: + :caption: Usage + :maxdepth: 3 + + Tutorials + ../examples/index.rst + .. toctree:: :caption: Resources diff --git a/examples/README.rst b/examples/README.rst new file mode 100644 index 00000000..0e9e731a --- /dev/null +++ b/examples/README.rst @@ -0,0 +1,7 @@ +.. _examples-index: + +======== +Examples +======== + +Below is a gallery of examples for different operations in diffsims. diff --git a/examples/creating_a_simulation_library/README.rst b/examples/creating_a_simulation_library/README.rst new file mode 100644 index 00000000..7b204c8d --- /dev/null +++ b/examples/creating_a_simulation_library/README.rst @@ -0,0 +1,4 @@ +Creating a Simulation Library +============================= + +These examples show specific workflows for creating a library of simulations. diff --git a/examples/creating_a_simulation_library/migration_guide.py b/examples/creating_a_simulation_library/migration_guide.py new file mode 100644 index 00000000..613572dd --- /dev/null +++ b/examples/creating_a_simulation_library/migration_guide.py @@ -0,0 +1,84 @@ +""" +0.5.x --> 0.6.x Migration Guide +=============================== +This is a migration guide for version 0.5.x to 0.6.x. This guide helps to show the changes +that were made to the API and how to update your code to use the new API. + +Here you can see how to make an equivalent to a diffraction library + +Old +--- +""" + +import numpy as np +import matplotlib.pyplot as plt +from diffpy.structure import Atom, Lattice, Structure + +from diffsims.libraries.structure_library import StructureLibrary +from diffsims.generators.diffraction_generator import DiffractionGenerator +from diffsims.generators.library_generator import DiffractionLibraryGenerator + + +latt = Lattice(4, 4, 4, 90, 90, 90) +atoms = [ + Atom(atype="Al", xyz=[0.0, 0.0, 0.0], lattice=latt), + Atom(atype="Al", xyz=[0.5, 0.5, 0.0], lattice=latt), + Atom(atype="Al", xyz=[0.5, 0.0, 0.5], lattice=latt), + Atom(atype="Al", xyz=[0.0, 0.5, 0.5], lattice=latt), +] +structure_matrix = Structure(atoms=atoms, lattice=latt) +euler_angles = np.array([[0, 0, 0], [10.0, 0.0, 0.0]]) +struct_library = StructureLibrary(["Al"], [structure_matrix], [euler_angles]) +diff_gen = DiffractionGenerator(accelerating_voltage=200) +lib_gen = DiffractionLibraryGenerator(diff_gen) +diff_lib = lib_gen.get_diffraction_library( + struct_library, + calibration=0.0262, + reciprocal_radius=1.6768, + half_shape=64, + with_direct_beam=True, + max_excitation_error=0.02, +) + +# %% +# New +# --- + +from orix.crystal_map import Phase +from orix.quaternion import Rotation +from diffsims.generators.simulation_generator import SimulationGenerator + +latt = Lattice(4, 4, 4, 90, 90, 90) +atoms = [ + Atom(atype="Al", xyz=[0.0, 0.0, 0.0], lattice=latt), + Atom(atype="Al", xyz=[0.5, 0.5, 0.0], lattice=latt), + Atom(atype="Al", xyz=[0.5, 0.0, 0.5], lattice=latt), + Atom(atype="Al", xyz=[0.0, 0.5, 0.5], lattice=latt), +] +structure_matrix = Structure(atoms=atoms, lattice=latt) +p = Phase("Al", point_group="m-3m", structure=structure_matrix) +gen = SimulationGenerator(accelerating_voltage=200) +rot = Rotation.from_euler([[0, 0, 0], [10.0, 0.0, 0.0]], degrees=True) +sim = gen.calculate_diffraction2d( + phase=p, + rotation=rot, + reciprocal_radius=1.6768, + max_excitation_error=0.02, + with_direct_beam=True, +) + +fig, axs = plt.subplots(2, 2, figsize=(10, 10)) +for i in range(2): + diff_lib["Al"]["simulations"][i].plot( + size_factor=15, show_labels=True, ax=axs[i, 0] + ) + sim.irot[i].plot(ax=axs[i, 1], size_factor=15, show_labels=True) + axs[i, 0].set_xlim(-1.5, 1.5) + axs[i, 0].set_ylim(-1.5, 1.5) + axs[i, 1].set_xlim(-1.5, 1.5) + axs[i, 1].set_ylim(-1.5, 1.5) + +_ = axs[0, 0].set_title("Old") +_ = axs[0, 1].set_title("New") + +# %% diff --git a/examples/creating_a_simulation_library/simulating_diffraction_patterns.py b/examples/creating_a_simulation_library/simulating_diffraction_patterns.py new file mode 100644 index 00000000..fafec75f --- /dev/null +++ b/examples/creating_a_simulation_library/simulating_diffraction_patterns.py @@ -0,0 +1,101 @@ +""" +============================================== +Simple Diffraction Pattern Simulation Examples +============================================== + +This example demonstrates how to simulate diffraction patterns using the +:class:`diffsims.generators.simulation_generator.SimulationGenerator` class. A +single diffraction pattern can be simulated for a single phase or multiple +diffraction patterns can be simulated for a single/multiple phases given +a rotation. + +One Pattern for One Phase +-------------------------- +""" + +from orix.crystal_map import Phase +from orix.quaternion import Rotation +from diffpy.structure import Atom, Lattice, Structure +import matplotlib.pyplot as plt + +from diffsims.generators.simulation_generator import SimulationGenerator + +a = 5.431 +latt = Lattice(a, a, a, 90, 90, 90) +atom_list = [] +for coords in [[0, 0, 0], [0.5, 0, 0.5], [0, 0.5, 0.5], [0.5, 0.5, 0]]: + x, y, z = coords[0], coords[1], coords[2] + atom_list.append(Atom(atype="Si", xyz=[x, y, z], lattice=latt)) # Motif part A + atom_list.append( + Atom(atype="Si", xyz=[x + 0.25, y + 0.25, z + 0.25], lattice=latt) + ) # Motif part B +struct = Structure(atoms=atom_list, lattice=latt) +p = Phase(structure=struct, space_group=227) + +gen = SimulationGenerator( + accelerating_voltage=200, +) +rot = Rotation.from_axes_angles( + [1, 0, 0], 45, degrees=True +) # 45 degree rotation around x-axis +sim = gen.calculate_diffraction2d(phase=p, rotation=rot) + +_ = sim.plot(show_labels=True) # plot the first (and only) diffraction pattern + +# %% + +sim.coordinates # coordinates of the first (and only) diffraction pattern + +# %% +# Simulating Multiple Patterns for a Single Phase +# ----------------------------------------------- + +rot = Rotation.from_axes_angles( + [1, 0, 0], (0, 15, 30, 45, 60, 75, 90), degrees=True +) # 45 degree rotation around x-axis +sim = gen.calculate_diffraction2d(phase=p, rotation=rot) + +_ = sim.plot(show_labels=True) # plot the first diffraction pattern + +# %% + +_ = sim.irot[3].plot( + show_labels=True +) # plot the fourth(45 degrees) diffraction pattern +# %% + +sim.coordinates # coordinates of all the diffraction patterns + +# %% +# Simulating Multiple Patterns for Multiple Phases +# ------------------------------------------------ + +p2 = p.deepcopy() # copy the phase + +p2.name = "al_2" + +rot = Rotation.from_axes_angles( + [1, 0, 0], (0, 15, 30, 45, 60, 75, 90), degrees=True +) # 45 degree rotation around x-axis +sim = gen.calculate_diffraction2d(phase=[p, p2], rotation=[rot, rot]) + +_ = sim.plot( + include_direct_beam=True, show_labels=True, min_label_intensity=0.1 +) # plot the first diffraction pattern + +# %% + +_ = ( + sim.iphase["al_2"].irot[3].plot(show_labels=True, min_label_intensity=0.1) +) # plot the fourth(45 degrees) diffraction pattern + +# %% +# Plotting a Pixelated Diffraction Pattern +# ---------------------------------------- +dp = sim.get_diffraction_pattern( + shape=(512, 512), + calibration=0.01, +) +plt.figure() +_ = plt.imshow(dp) +# %% diff --git a/setup.py b/setup.py index 1ba7c559..6d835883 100644 --- a/setup.py +++ b/setup.py @@ -27,9 +27,11 @@ # fmt: off extra_feature_requirements = { "doc": [ + "numpydoc", "pydata-sphinx-theme", "sphinx >= 3.0.2", "sphinx-design", + "sphinx_gallery", ], "tests": [ "coverage >= 5.0",