diff --git a/docs/source/_static/images/animation_md.gif b/docs/source/_static/images/animation_md.gif new file mode 100644 index 0000000..99bad54 Binary files /dev/null and b/docs/source/_static/images/animation_md.gif differ diff --git a/docs/source/_static/images/example_color_by_force.png b/docs/source/_static/images/example_color_by_force.png new file mode 100644 index 0000000..f658e26 Binary files /dev/null and b/docs/source/_static/images/example_color_by_force.png differ diff --git a/docs/source/_static/images/mesh_primitive.png b/docs/source/_static/images/mesh_primitive.png new file mode 100644 index 0000000..d54af58 Binary files /dev/null and b/docs/source/_static/images/mesh_primitive.png differ diff --git a/docs/source/_static/images/mesh_primitive_example.png b/docs/source/_static/images/mesh_primitive_example.png new file mode 100644 index 0000000..df881e5 Binary files /dev/null and b/docs/source/_static/images/mesh_primitive_example.png differ diff --git a/docs/source/_static/images/operator_search.png b/docs/source/_static/images/operator_search.png new file mode 100644 index 0000000..ecb16de Binary files /dev/null and b/docs/source/_static/images/operator_search.png differ diff --git a/docs/source/color.rst b/docs/source/color.rst new file mode 100644 index 0000000..f159cd3 --- /dev/null +++ b/docs/source/color.rst @@ -0,0 +1,55 @@ +Color +=============== + +One can color the atoms using the following scheme: + +- Element +- Random +- Uniform +- Index +- Attribute + + +Color by element +---------------- + +Supported style are: + +#. **JMOL**: http://jmol.sourceforge.net/jscolors/#color_U +#. **VESTA**: https://jp-minerals.org/vesta/en/ +#. **CPK**: https://en.wikipedia.org/wiki/CPK_coloring + + +Color by attribute +---------------- +Coloring based on the attribute of the atoms. The attribute can be: charge, magmom, or any other attribute in the structure. + +Here we show how to color the atoms by their forces. + + +.. code-block:: python + + from ase.build import bulk + from ase.calculators.emt import EMT + import numpy as np + from weas_widget import WeasWidget + + atoms = bulk('Au', cubic = True) + atoms *= [3, 3, 3] + atoms.positions += np.random.random((len(atoms), 3)) + atoms.calc = EMT() + atoms.get_potential_energy() + # set the forces as an attribute + atoms.set_array("Force", atoms.calc.results["forces"]) + + viewer = WeasWidget() + viewer.from_ase(atoms) + viewer.colorBy = "Force" + viewer.colorRamp = ["red", "yellow", "blue"] + viewer.modelStyle = 1 + viewer + + + +.. image:: _static/images/example_color_by_force.png + :width: 10cm diff --git a/docs/source/edit.rst b/docs/source/edit.rst index 70b1780..c7a99a2 100644 --- a/docs/source/edit.rst +++ b/docs/source/edit.rst @@ -22,7 +22,7 @@ There are two methods for selecting atoms: Move, Rotate and Duplicate selected atoms -=========================== +========================================= Press the transform shortcut, and move your mouse. diff --git a/docs/source/gallery.rst b/docs/source/gallery.rst new file mode 100644 index 0000000..29a66f7 --- /dev/null +++ b/docs/source/gallery.rst @@ -0,0 +1,69 @@ +========= +Gallery +========= + + +Model type +========== + +.. list-table:: + :widths: 25 25 25 25 + + * - Ball + - Ball-and-stick + - Polyhedral + - Wireframe + * - |crystal1| + - |crystal2| + - |crystal3| + - |crystal4| + + + + +Volumetric data +====================== + +Isosurface +-------------- + +.. image:: _static/images/example-isosurface.png + :width: 8cm + + + +Phonon visualization +======================= + +.. image:: _static/images/example-phonon.gif + :width: 10cm + + + +Color by attribute +======================= +Color by attribute is a powerful tool to visualize the data. Here we show how to color the atoms by their forces. + +.. image:: _static/images/example_color_by_force.png + :width: 10cm + + + + +Animation +============ + +.. image:: _static/images/animation_md.gif + :width: 15cm + + + + +.. |crystal1| image:: _static/images/model_style_0.png + :width: 8cm +.. |crystal2| image:: _static/images/model_style_1.png + :width: 8cm +.. |crystal3| image:: _static/images/model_style_2.png + :width: 8cm +.. |crystal4| image:: _static/images/model_style_3.png + :width: 8cm diff --git a/docs/source/gui.rst b/docs/source/gui.rst index a10717c..f128e1d 100644 --- a/docs/source/gui.rst +++ b/docs/source/gui.rst @@ -123,3 +123,13 @@ Select specific components } viewer = WeasWidget(guiConfig=guiConfig) viewer + + +Set viewer width and height +---------------------------- + +.. code-block:: python + + from weas_widget import WeasWidget + viewer = WeasWidget(viewerStyle = {"width": "800px", "height": "600px"}) + viewer diff --git a/docs/source/index.rst b/docs/source/index.rst index 33414e8..b46e035 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -23,12 +23,16 @@ A widget to visualize and interact with atomistic structures in Jupyter Notebook installation edit gui + color operation boundary measurement isosurface vector_field + mesh_primitive + search_operator selection + gallery Indices and tables diff --git a/docs/source/mesh_primitive.rst b/docs/source/mesh_primitive.rst new file mode 100644 index 0000000..c3d8270 --- /dev/null +++ b/docs/source/mesh_primitive.rst @@ -0,0 +1,198 @@ +Mesh Primitive +================= +This module allow user to draw custom geometry. The supported geometry are: + +- plane +- box +- sphere +- cylinder +- icosahedron +- cone +- torus +- arrow + +.. figure:: _static/images/mesh_primitive.png + :align: center + + +Example +----------------------------- +The following example shows how to use the mesh primitive to draw two cubes and a sphere. + + +.. figure:: _static/images/mesh_primitive_example.png + :align: center + :width: 50% + +.. code-block:: python + + from weas_widget import WeasWidget + viewer = WeasWidget() + data = [ + { + "type": "cube", + "data": [ + { + "position": [-5, 0, 0], + "size": 2, + "scale": [1, 0.5, 1], + "rotation": [0, 0, 0] + }, + { + "position": [5, 0, 1], + "size": 1, + "scale": [1, 0.5, 1], + "rotation": [1, 1, 0], + "color": "#bd0d87" + } + ] + }, + { + "type": "cylinder", + "data": [ + { + "position": [0, 0, 0], + "segments": 12, + "radius": 1, + "depth": 5, + "scale": [1, 1, 1], + "rotation": [0, 0, 0], + "color": "#0d87bd" + } + ] + }, + ] + + viewer.meshPrimitives = data + viewer + + +Primitive Parameters +----------------------------- + +Cube +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The cube is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "size": 2, + "scale": [1, 1, 1], + "rotation":[0, 0, 0], + "color": "#bd0d87", + "materialType": "Standard", + } + + +Cylinder +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The cylinder is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "segments": 12, + "radius": 1, + "depth": 2, + "scale": [1, 1, 1], + "rotation":[0, 0, 0], + "color": "#bd0d87", + } + +Sphere +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The sphere is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "widthSegments": 8, + "heightSegments": 6, + "radius": 1, + "scale": [1, 1, 1], + "rotation":[0, 0, 0], + "color": "#bd0d87", + } + +Plane +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The plane is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "size": 2, + "scale": [1, 1, 1], + "rotation":[0, 0, 0], + "color": "#bd0d87", + } + +Icosahedron +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The icosahedron is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "radius": 1, + "detail": 2, + "scale": [1, 1, 1], + "rotation":[0, 0, 0], + "color": "#bd0d87", + } + +Cone +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The cone is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "segments": 8, + "radius": 1, + "height": 2, + "scale": [1, 1, 1], + "rotation":[0, 0, 0], + "color": "#bd0d87", + } + +Arrow +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The arrow is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "direction": [0, 0, 1], + "length": 1, + "color": "#bd0d87", + "materialType": "Standard", + } + +Torus +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The torus is defined by the following parameters: + +.. code-block:: python + + { + "position": [0, 0, 0], + "radius": 1, + "tube": 0.4, + "radialSegments": 8, + "tubularSegments": 6, + "scale": [1, 1, 1], + "rotation":[0, 0, 0], + "color": "#bd0d87", + } + +.. tip:: + Please check the `three.js documentation `_ for more information about the parameters. diff --git a/docs/source/quick_start.ipynb b/docs/source/quick_start.ipynb index 529efad..f118a5b 100644 --- a/docs/source/quick_start.ipynb +++ b/docs/source/quick_start.ipynb @@ -59,6 +59,7 @@ "|----------|---------|\n", "| Move | `g` |\n", "| Rotate | `r` |\n", + "| Duplicate| `d` |\n", "\n", "\n", "### Delete selected atoms\n", @@ -398,6 +399,17 @@ "viewer" ] }, + { + "cell_type": "markdown", + "id": "98817cd6", + "metadata": {}, + "source": [ + "#### Color by attribute\n", + "Color by attribute is a powerful tool to visualize the data. Here we show how to color the atoms by their forces.\n", + "\n", + "\n" + ] + }, { "cell_type": "markdown", "id": "ede9f9c6", diff --git a/docs/source/search_operator.rst b/docs/source/search_operator.rst new file mode 100644 index 0000000..b0e6d71 --- /dev/null +++ b/docs/source/search_operator.rst @@ -0,0 +1,11 @@ +====================== +Operator Search +====================== + +The Operator Search pop-up lets you search for a certain operator and execute it. This is particularly beneficial for users looking to execute advanced operations not readily exposed in the GUI. + +Shortcut: `Ctrl + F` + +.. image:: _static/images/operator_search.png + :align: center + :width: 400px diff --git a/js/widget.css b/js/widget.css index f163fdb..9646a5b 100644 --- a/js/widget.css +++ b/js/widget.css @@ -79,5 +79,5 @@ #search-results { overflow-y: auto; /* Allow vertical scrolling */ - max-height: 200px; /* Adjust based on the overlay height and search box */ + max-height: 150px; /* Adjust based on the overlay height and search box */ } diff --git a/js/widget.js b/js/widget.js index 30abd0c..28dc36f 100644 --- a/js/widget.js +++ b/js/widget.js @@ -2,7 +2,7 @@ // clone the weas repo and import the weas module // import * as weas from "../../weas/src/index.js"; // if not, then use the release version from unpkg -import * as weas from "https://unpkg.com/weas@0.0.8/dist/weas.mjs"; +import * as weas from "https://unpkg.com/weas@0.0.8-a/dist/weas.mjs"; import "./widget.css"; @@ -37,7 +37,9 @@ function render({ model, el }) { const viewerConfig = { debug: model.get("debug"), _modelStyle: model.get("modelStyle"), + _colorBy: model.get("colorBy"), _colorType: model.get("colorType"), + _colorRamp: model.get("colorRamp"), _materialType: model.get("materialType"), _atomLabelType: model.get("atomLabelType"), _showCell: model.get("showCell"), @@ -56,6 +58,8 @@ function render({ model, el }) { // vector field avr.VFManager.fromSettings(model.get("vectorField")); avr.showVectorField = model.get("showVectorField") + // mesh primitives + avr.meshPrimitive.fromSettings(model.get("meshPrimitives")); avr.drawModels(); avr.render(); @@ -155,7 +159,13 @@ function render({ model, el }) { avr.VFManager.fromSettings(data); avr.VFManager.drawVectorFields(); }); - + // mesh primitives + model.on("change:meshPrimitives", () => { + const data = model.get("meshPrimitives"); + console.log("meshPrimitives: ", data); + avr.meshPrimitive.fromSettings(data); + avr.meshPrimitive.drawMesh(); + }); } function createVolumeData(data, cell=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) { // get the dimensions diff --git a/pyproject.toml b/pyproject.toml index 3b2c6bf..dc68170 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "weas_widget" -version = "0.0.12" +version = "0.0.13" description = "A widget to visualize and interact with atomistic structures in Jupyter Notebook." authors = [{name = "Xing Wang", email = "xingwang1991@gmail.com"}] readme = "README.md" diff --git a/src/weas_widget/__init__.py b/src/weas_widget/__init__.py index f0f976a..efe9542 100644 --- a/src/weas_widget/__init__.py +++ b/src/weas_widget/__init__.py @@ -23,7 +23,11 @@ class WeasWidget(anywidget.AnyWidget): selectedAtomsIndices = tl.List([]).tag(sync=True) boundary = tl.List([[0, 1], [0, 1], [0, 1]]).tag(sync=True) modelStyle = tl.Int(0).tag(sync=True) + # color + colorBy = tl.Unicode("Element").tag(sync=True) colorType = tl.Unicode("CPK").tag(sync=True) + colorRamp = tl.List(["red", "blue"]).tag(sync=True) + # material materialType = tl.Unicode("Standard").tag(sync=True) atomLabelType = tl.Unicode("None").tag(sync=True) showCell = tl.Bool(True).tag(sync=True) @@ -37,6 +41,8 @@ class WeasWidget(anywidget.AnyWidget): vectorField = tl.List().tag(sync=True) showVectorField = tl.Bool(True).tag(sync=True) guiConfig = tl.Dict({}).tag(sync=True) + # mesh primitives + meshPrimitives = tl.List(tl.Dict({})).tag(sync=True) # viewer viewerStyle = tl.Dict({}).tag(sync=True) # task