Skip to content

Commit

Permalink
Starting the 2nd tutorial.
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Jackson <mike.jackson@bluequartz.net>
  • Loading branch information
imikejackson committed Apr 28, 2024
1 parent a574060 commit 0f1ef1f
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 23 deletions.
4 changes: 2 additions & 2 deletions wrapping/python/docs/generate_sphinx_docs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,8 @@ void GeneratePythonRstFiles()
rstStream << ")\n\n";

rstStream << memberStream.str();
rstStream << " :return: Returns a :ref:`Result <result>` object that holds any warnings and/or errors that were encountered during execution.\n";
rstStream << " :rtype: :ref:`simplnx.Result <result>`\n\n";
rstStream << " :return: Returns a :ref:`nx.IFilter.ExecuteResult <result>` object that holds any warnings and/or errors that were encountered during execution.\n";
rstStream << " :rtype: :ref:`nx.IFilter.ExecuteResult <result>`\n\n";
rstStream << '\n';
}
}
Expand Down
85 changes: 71 additions & 14 deletions wrapping/python/docs/source/Tutorial_1.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
.. Tutorial 1:
.. _Tutorial_1:

=====================================
Tutorial 1: Basic Python Integration
=====================================

This tutorial is meant to be a very basic introduction to interacting with the DREAM3D-NX underlying library called 'simplnx'. This
tutorial will cover environment setup, minimal import statements and executing a few basic filters. Once you understand how to
execute a filter, all filters are generally setup the same way. Use the search feature on the web site to find the filter
that you are interested in running.

.. _Tutorial_1_Setup:

###################################
Anaconda Virtual Environment Setup
###################################
Expand All @@ -12,9 +19,9 @@ Anaconda Virtual Environment Setup
conda config --add channels conda-forge
conda config --set channel_priority strict
conda create -n nxpython python=3.12
conda create -c bluequartzsoftware -n nxpython python=3.12 dream3dnx
conda activate nxpython
conda install -c bluequartzsoftware dream3dnx
###################################
Introduction
Expand Down Expand Up @@ -63,7 +70,7 @@ A few caveats to take note of:
First Steps: Create a Group in the DataStructure
################################################

As in the user interface of DREAM3D-NX, you as the developer can execute any of filter from DREAM3D-NX using only Python codes. This is performed
As in the user interface of DREAM3D-NX, you as the developer can execute any of the filters from DREAM3D-NX using only Python codes. This is performed
by instantiating the filter and then calling the `execute()` method with the appropriate parameters used in the call. With the current API, we are tending to
inline instantiate the filter and execute it all in the same line. Some things to note with this small piece of code:

Expand Down Expand Up @@ -112,7 +119,7 @@ And the output would look like the following:
Result Objects
################################################

Each time a filter is executed, it will return an `nx.ExecuteResult` object. This
Each time a filter is executed, it will return a :ref:`nx.IFilter.ExecuteResult <result>` object. This
object can be interrogated for both warnings and errors that occured while the
filter was executing. A typical function that can be written to properly error
check the 'result' value is the following:
Expand All @@ -127,15 +134,15 @@ check the 'result' value is the following:
"""
if len(result.warnings) != 0:
for w in result.warnings:
print(f'Warning: ({w.code}) {w.message}')
print(f'Warning: ({w.code}) {w.message}')
has_errors = len(result.errors) != 0
if has_errors:
for err in result.errors:
print(f'Error: ({err.code}) {err.message}')
raise RuntimeError(result)
print(f"{filter.name()} :: No errors running the filter")
print(f'Error: ({err.code}) {err.message}')
raise RuntimeError(result)
else:
print(f"{filter.name()} :: No errors running the filter")
If you were to integrate this into your own code, then we would get the following when we wanted to execute a filter:

Expand All @@ -153,7 +160,7 @@ Creating a DataArray Object
Raw data is stored in a :ref:`DataArray` object within the :ref:`DataStructure`. The DREAM3D-NX python bindings only expose a subset of functionality
from the :ref:`DataArray`, enough to get the name, tuple shape and component shape. **ALL** interactions to modify a :ref:`DataArray` are done via a
`numpy view <https://numpy.org/doc/stable/user/basics.copies.html>`_. Let us first create a :ref:`DataArray` object within the :ref:`DataStructure` by using the
:ref:`CreateDataArray` filter. Adding into the current python source file...
:ref:`CreateDataArray <CreateDataArray>` filter. Adding into the current python source file...

.. code:: python
Expand Down Expand Up @@ -244,6 +251,23 @@ And if you wanted to use `matplotlib <https://matplotlib.org/>`_ to view the dat
:alt: MatPlotLib output


################################################
Saving your Data to a .dream3d file
################################################

Most pipelines would want to save any modified data to a .dream3d file (if you are wanting the easiest compatibility with DREAM3D-NX). In order
to do this one would run the :ref:`WriteDREAM3DFilter <WriteDREAM3DFilter>`. Appending the following code will write the entire
:ref:`DataStructure` to a .dream3d file (which is a plain HDF5 file).

.. code:: python
# Use the WriteDREAM3DFilter to write out the modified DataStructure to disk
result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure,
export_file_path="Output/lesson_4.dream3d",
write_xdmf_file=False)
check_filter_result( nx.WriteDREAM3DFilter(), result)
################################################
Complete Source Code
################################################
Expand All @@ -255,26 +279,52 @@ Complete Source Code
import matplotlib.pyplot as plt
import nxutility
def check_filter_result(filter: nx.IFilter, result: nx.IFilter.ExecuteResult) -> None:
"""
This function will check the `result` for any errors. If errors do exist then a
`RuntimeError` will be thrown. Your own code to modify this to return something
else that doesn't just stop your script in its tracks.
"""
if len(result.warnings) != 0:
for w in result.warnings:
print(f'Warning: ({w.code}) {w.message}')
has_errors = len(result.errors) != 0
if has_errors:
for err in result.errors:
print(f'Error: ({err.code}) {err.message}')
raise RuntimeError(result)
else:
print(f"{filter.name()} :: No errors running the filter")
# #############################################################################
# Script Starts Here
# #############################################################################
# Create the DataStructure instance
data_structure = nx.DataStructure()
result = nx.CreateDataGroup.execute(data_structure=data_structure,
data_object_path=nx.DataPath("Top Level Group"))
check_filter_result(nx.CreateDataGroup(), result)
# Loop to create a bunch of DataGroups.
for i in range(1, 6):
current_data_group_path = nx.DataPath(f"Top Level Group {i}")
result = nx.CreateDataGroup.execute(data_structure=data_structure,
data_object_path=current_data_group_path)
check_filter_result(nx.CreateDataGroup(), result)
# Execute the filter
# Execute the CreateDataArray filter
result = nx.CreateDataArray().execute(data_structure=data_structure,
component_count=1,
initialization_value_str="0",
numeric_type_index=nx.NumericType.float32,
output_array_path=nx.DataPath("Top Level Group/2D Array"),
tuple_dimensions=[[4,5]])
nxutility.check_filter_result( nx.CreateDataArray(), result)
check_filter_result(nx.CreateDataArray(), result)
print(f'{data_structure.hierarchy_to_str()}')
# Try to get the array from the DataStructure
Expand All @@ -283,7 +333,7 @@ Complete Source Code
except AttributeError as attrerr:
print(f'{attrerr}')
quit(1) # This is pretty harsh! Maybe something more elegant to unwind from this error
# Fill the numpy data view with random numbers
rng = np.random.default_rng()
rng.standard_normal(out=array_view, dtype=np.float32)
Expand All @@ -296,3 +346,10 @@ Complete Source Code
plt.axis('off') # to turn off axes
plt.show()
# Use the WriteDREAM3DFilter to write out the modified DataStructure to disk
result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure,
export_file_path="Output/tutorial_1.dream3d",
write_xdmf_file=False)
check_filter_result( nx.WriteDREAM3DFilter(), result)
13 changes: 13 additions & 0 deletions wrapping/python/docs/source/Tutorial_2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.. _Tutorial_2:

=====================================
Tutorial 2: Manipulating Pipelines
=====================================

###################################
Introduction
###################################

Setup your environment in the same way as from :ref:`Tutorial 1<Tutorial_1_Setup>`. In this tutorial we will
be manipulating a basic pipeline

20 changes: 13 additions & 7 deletions wrapping/python/docs/source/User_API.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.. _UserAPIDocs:

SIMPLNX Python API
===================

.. _UserAPIDocs:

Error & Warning Reporting
--------------------------

Expand All @@ -11,7 +11,7 @@ Error & Warning Reporting
.. _Result:
.. py:class:: Result
.. py:class:: IFilter.ExecuteResult
The object that encapsulates any warnings or errors from either preflighting or executing a simplnx.Filter object.
It can be queried for the list of errors or warnings and thus printed if needed.
Expand All @@ -23,11 +23,17 @@ Error & Warning Reporting
input_type=0,
output_orientation_array_name='Quaternions',
output_type=2)
if len(result.errors) != 0:
print('Errors: {}', result.errors)
print('Warnings: {}', result.warnings)
if len(result.warnings) != 0:
for w in result.warnings:
print(f'Warning: ({w.code}) {w.message}')
has_errors = len(result.errors) != 0
if has_errors:
for err in result.errors:
print(f'Error: ({err.code}) {err.message}')
raise RuntimeError(result)
else:
print("No errors running the ConvertOrientations")
print(f"{filter.name()} :: No errors running the filter")
General Parameters
------------------
Expand Down

0 comments on commit 0f1ef1f

Please sign in to comment.