diff --git a/src/examples/tutorial/ascent_intro/notebooks/01_ascent_first_light.ipynb b/src/examples/tutorial/ascent_intro/notebooks/01_ascent_first_light.ipynb index 7ba6a4b43..e4184d4e0 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/01_ascent_first_light.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/01_ascent_first_light.ipynb @@ -6,7 +6,7 @@ "source": [ "## First Light Example\n", "### Render a sample dataset using Ascent\n", - "To start, we run a basic “First Light” example to generate an image. This example renders the an example dataset using ray casting to create a pseudocolor plot. The dataset is one of the built-in Conduit Mesh Blueprint examples, in this case an unstructured mesh composed of hexagons." + "To start, we run a basic “First Light” example to generate an image. This example renders the example dataset using ray casting to create a pseudocolor plot. The dataset is one of the built-in Conduit Mesh Blueprint examples, in this case an unstructured mesh composed of hexagons." ] }, { @@ -118,11 +118,47 @@ "# close ascent\n", "a.close()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "**First**, change the \"field\" name for this dataset from \"braid\" to \"radial\" and re-plot the image.\n", + "\n", + "**Second**, observe how the image generated changes as you decrease the number of points on the mesh. For example, move from a 50x50x50 mesh to a 15x15x15 mesh.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise1.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -136,7 +172,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, diff --git a/src/examples/tutorial/ascent_intro/notebooks/02_conduit_basics.ipynb b/src/examples/tutorial/ascent_intro/notebooks/02_conduit_basics.ipynb index 8a122a494..5c3579459 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/02_conduit_basics.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/02_conduit_basics.ipynb @@ -118,11 +118,77 @@ "\n", "print(n.to_yaml())" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "**First**, create a tree with the following format:\n", + "\n", + "```\n", + "animals: \n", + " carnivores: \n", + " - \"cat\"\n", + " herbivores: \n", + " - \"koala\"\n", + " - \"sloth\"\n", + " omnivores: \n", + " - \"dog\"\n", + " - \"human\"\n", + "```\n", + "\n", + "Hint: You'll have to use lists.\n", + "\n", + "**Second**\n", + "\n", + "Add \"bear\" to the list of omnivores in `animals` so that the tree looks like\n", + "\n", + "```\n", + "animals: \n", + " carnivores: \n", + " - \"cat\"\n", + " herbivores: \n", + " - \"koala\"\n", + " - \"sloth\"\n", + " omnivores: \n", + " - \"dog\"\n", + " - \"human\"\n", + " - \"bear\"\n", + "```\n", + "\n", + "Here you'll use the `set` method introduced above! See [these docs](https://llnl-conduit.readthedocs.io/en/latest/tutorial_python_basics.html) for help." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise2.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -136,9 +202,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/examples/tutorial/ascent_intro/notebooks/03_conduit_blueprint_mesh_examples.ipynb b/src/examples/tutorial/ascent_intro/notebooks/03_conduit_blueprint_mesh_examples.ipynb index b2ea0097e..b60b6e7c6 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/03_conduit_blueprint_mesh_examples.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/03_conduit_blueprint_mesh_examples.ipynb @@ -450,11 +450,55 @@ "# view our results\n", "ascent.jupyter.AscentImageSequenceViewer(result_image_files).show()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "Use/alter the code from Mesh Blueprint Example 1 to create a scene with two plots: two versions of the alternating field on a uniform grid -- one with an origin at (-10,-10,-10) and one with an origin at (0,0,0).\n", + "\n", + "**First**, add a second coordinate set to `mesh` and call it `mycoords`. `mycoords` will have the same properties as `coords` except for the difference in origin.\n", + "\n", + "**Second**, add a second topology to `mesh` and call it `mytopo`. `mytopo` will have the same properties as `topo` except that its coordinate set will be `mycoords` instead of `coords`.\n", + "\n", + "**Third**, add a second field to `mesh` and call it `myalternating`. `myalternating` will have the same properties as `alternating` except that its topology will be `mytopo` instead of `topo`.\n", + "\n", + "**Fourth** add a second plot (`p2`) to the scene `s1`. `p1` will still plot the field `alternating` and `p2` should plot `myalternating`.\n", + "\n", + "Finally, use AscentViewer to plot the result.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise3.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -468,9 +512,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/examples/tutorial/ascent_intro/notebooks/04_ascent_scene_examples.ipynb b/src/examples/tutorial/ascent_intro/notebooks/04_ascent_scene_examples.ipynb index bc6b30b92..8eeff1484 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/04_ascent_scene_examples.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/04_ascent_scene_examples.ipynb @@ -318,11 +318,57 @@ "# close ascent\n", "a.close()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "Use and modify the code from Scene Example 3 (\"Adjusting camera parameters\").\n", + "Change the color scheme to Viridis and rotate the view of the tet example\n", + "360 degrees. \n", + "\n", + "**First**, update the name of the color table as in Example 4.\n", + "\n", + "**Second**, create 37 renders of `s1` with azimuth angles [0, 10, 20, 30, .... 360]\n", + "\n", + "Note: the following Python syntax for string interpolation may be helpful:\n", + "\n", + "```\n", + "a = \"world\"\n", + "print(f\"Hello {a}\")\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise4.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -336,9 +382,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/examples/tutorial/ascent_intro/notebooks/05_ascent_pipeline_examples.ipynb b/src/examples/tutorial/ascent_intro/notebooks/05_ascent_pipeline_examples.ipynb index 32283869b..479934b44 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/05_ascent_pipeline_examples.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/05_ascent_pipeline_examples.ipynb @@ -317,11 +317,50 @@ "# close ascent\n", "a.close()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "Use and refactor the code in Pipeline Example 3.\n", + "\n", + "**First** break the second pipeline `pl2` with two filters into two pipelines (`pl2` and `pl3`) -- one with a single filter each. \n", + "\n", + "**Second** create separate plots in `s1` for each of the three pipelines.\n", + "\n", + "You should end with a single scene and three plots that you can toggle between." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise5.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -335,9 +374,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/examples/tutorial/ascent_intro/notebooks/06_ascent_extract_examples.ipynb b/src/examples/tutorial/ascent_intro/notebooks/06_ascent_extract_examples.ipynb index 4020113b8..b664216da 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/06_ascent_extract_examples.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/06_ascent_extract_examples.ipynb @@ -600,11 +600,48 @@ "else:\n", " print(\"Extract results match.\")" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "Use and modify the code from Relay Extract Example 2 above.\n", + "\n", + "**First**, add a second field -- \"radial\" -- to be saved alongside \"braid\".\n", + "\n", + "**Second** change the protocol from hdf5 to yaml and change the path of the file created from `out_export_braid_one_field` to `out_export_braid_two_fields`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise6.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -618,9 +655,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/examples/tutorial/ascent_intro/notebooks/07_ascent_query_examples.ipynb b/src/examples/tutorial/ascent_intro/notebooks/07_ascent_query_examples.ipynb index cedd52531..4383bc054 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/07_ascent_query_examples.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/07_ascent_query_examples.ipynb @@ -175,11 +175,50 @@ "plt.xlabel('cycle')\n", "plt.show()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "Use and modify the code from Query Example 1:\n", + "\n", + "**First**, observe how changing the number of bins alters the entropy of the histogram in Query Example 1; change the number of bins from 128 to 64 and then to 32.\n", + "\n", + "**Second**, add two additional queries like `q2` -- `q3` with 64 bins and `q4` with 32 bins. \n", + "\n", + "**Third**, plot entropy vs. cycles for each of the three entropy queries. Create arrays to store the entropy as calculated for `q[1-3]` and overlay these entropies on the same plot. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise7.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -193,9 +232,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/examples/tutorial/ascent_intro/notebooks/08_ascent_trigger_examples.ipynb b/src/examples/tutorial/ascent_intro/notebooks/08_ascent_trigger_examples.ipynb index d03f4b5d4..5f09b6536 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/08_ascent_trigger_examples.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/08_ascent_trigger_examples.ipynb @@ -164,11 +164,52 @@ "source": [ "print(info[\"expressions\"].to_yaml())" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "Create your own trigger that sets up a scene with two renders (as in notebook 4) at cycle 1000.\n", + "\n", + "**First**, refactor the code from Trigger Example 1 to have a single trigger at cycle 1000.\n", + "\n", + "**Second**, create a new actions file or prepare to edit `cycle_trigger_actions.yaml`. Make sure your trigger is using the correct actions file.\n", + "\n", + "**Third**, edit your actions .yaml file to include two renders, as in notebook 4's \"Scene Example 3\". One render can use an azimuth angle of 10 degrees and the other a 3x zoom.\n", + "\n", + "**Fourth**, use `ascent.jupyter.AscentImageSequenceViewer` as above to plot the two .png files created by your trigger.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise8.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -182,9 +223,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.13" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/src/examples/tutorial/ascent_intro/notebooks/09_ascent_binning_examples.ipynb b/src/examples/tutorial/ascent_intro/notebooks/09_ascent_binning_examples.ipynb index 7db705216..ed7362807 100644 --- a/src/examples/tutorial/ascent_intro/notebooks/09_ascent_binning_examples.ipynb +++ b/src/examples/tutorial/ascent_intro/notebooks/09_ascent_binning_examples.ipynb @@ -254,11 +254,53 @@ "plt.xlabel('z position')\n", "plt.ylabel('max radial')" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise\n", + "\n", + "**First**, swap out “radial” for “braid” in each of the queries for Binning Example 1 such as\n", + "\n", + "```\n", + "queries[\"q1/params/expression\"] = \"binning('radial','max', [axis('x',num_bins=20)])\";\n", + "```\n", + "\n", + "Run the resulting code to see how this modifies the final plots.\n", + "\n", + "**Second**, copy and modify the existing code for 1D binning projected along the x axis. Your modified code should \n", + "create a fourth query that 1D bins along the y axis and plot the result. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exercise solution\n", + "Run the cell below once to see solutions and twice to run them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load solutions/exercise9.py" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -272,7 +314,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.3" + "version": "3.9.13" } }, "nbformat": 4, diff --git a/src/examples/tutorial/ascent_intro/notebooks/solution_notebook8.yaml b/src/examples/tutorial/ascent_intro/notebooks/solution_notebook8.yaml new file mode 100644 index 000000000..21b5b9c03 --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solution_notebook8.yaml @@ -0,0 +1,17 @@ +- + action: "add_scenes" + scenes: + s1: + plots: + p1: + type: "pseudocolor" + field: "gyre" + renders: + r1: + camera: + azimuth: 10.0 + image_name: "cycle_trigger_out_r1" + r2: + camera: + zoom: 3.0 + image_name: "cycle_trigger_out_r2" diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise1.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise1.py new file mode 100644 index 000000000..4d05eff5a --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise1.py @@ -0,0 +1,94 @@ + +""" +# Exercise 1 prompts: +First, change the "field" name for this dataset from "braid" to "radial" and re-plot the image. + +Second, observe how the image generated changes as you decrease the number of points on the mesh. For example, move from a 50x50x50 mesh to a 15x15x15 mesh. + + +# Changes to the code: +(1) `scenes["s1/plots/p1/field"] = "braid"` is updated to `scenes["s1/plots/p1/field"] = "radial" +` + +(2) +The line below is updated from a 50x50x50 mesh to a 15x15x15 mesh. + +``` +conduit.blueprint.mesh.examples.braid("hexs", + 15, + 15, + 15, + mesh) +``` + +""" + +# conduit + ascent imports +import conduit +import conduit.blueprint +import ascent + +# cleanup any old results +!./cleanup.sh + +mesh = conduit.Node() +conduit.blueprint.mesh.examples.braid("hexs", + 15, + 15, + 15, + mesh) + + +# create an Ascent instance +a = ascent.Ascent() + +# set options to allow errors propagate to python +ascent_opts = conduit.Node() +ascent_opts["exceptions"] = "forward" + +# +# open ascent +# +a.open(ascent_opts) + +# +# publish mesh data to ascent +# +a.publish(mesh) + +# +# Ascent's interface accepts "actions" +# that to tell Ascent what to execute +# +actions = conduit.Node() + +# Create an action that tells Ascent to: +# add a scene (s1) with one plot (p1) +# that will render a pseudocolor of +# the mesh field `braid` +add_act = actions.append() +add_act["action"] = "add_scenes" + +# declare a scene (s1) and pseudocolor plot (p1) +scenes = add_act["scenes"] + +# things to explore: +# changing plot type (mesh) +# changing field name (for this dataset: radial) +scenes["s1/plots/p1/type"] = "pseudocolor" +scenes["s1/plots/p1/field"] = "radial" + +# set the output file name (ascent will add ".png") +scenes["s1/image_name"] = "out_first_light_render_3d" + +# view our full actions tree +print(actions.to_yaml()) + +# execute the actions +a.execute(actions) + +# show the result from our scene using the AscentViewer widget +ascent.jupyter.AscentViewer(a).show() + +## close ascent +# a.close() \ No newline at end of file diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise2.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise2.py new file mode 100644 index 000000000..d1bfa0b59 --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise2.py @@ -0,0 +1,57 @@ + +""" +# Exercise 2 prompts: + +**First**, create a tree with the following format: + +``` +animals: + carnivores: + - "cat" + herbivores: + - "koala" + - "sloth" + omnivores: + - "dog" + - "human" +``` + +Hint: You'll have to use lists. + +**Second** + +Add "bear" to the list of omnivores in `animals` so that the tree looks like + +``` +animals: + carnivores: + - "cat" + herbivores: + - "koala" + - "sloth" + omnivores: + - "dog" + - "human" + - "bear" +``` + +Here you'll use the `set` method introduced above! See [these docs](https://llnl-conduit.readthedocs.io/en/latest/tutorial_python_basics.html) for help. + +""" + +# conduit + ascent imports +import conduit + +# cleanup any old results +!./cleanup.sh + +# Create the initial `animals` tree +animals = conduit.Node() +animals["animals/carnivores"] = ["cat"]; +animals["animals/herbivores"] = ["koala", "sloth"]; +animals["animals/omnivores"] = ["dog", "human"]; +print(animals.to_yaml()) + +# Add "bear" to the list of omnivores +animals["animals/omnivores"].append().set("bear") +print(animals.to_yaml()) diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise3.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise3.py new file mode 100644 index 000000000..f6b0e9a82 --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise3.py @@ -0,0 +1,148 @@ + +""" +# Exercise 3 prompts: + +Use/alter the code from Mesh Blueprint Example 1 to create a scene with two plots: two versions of the alternating field on a uniform grid -- one with an origin at (-10,-10,-10) and one with an origin at (0,0,0). + +**First**, add a second coordinate set to `mesh` and call it `mycoords`. `mycoords` will have the same properties as `coords` except for the difference in origin. + +**Second**, add a second topology to `mesh` and call it `mytopo`. `mytopo` will have the same properties as `topo` except that its coordinate set will be `mycoords` instead of `coords`. + +**Third**, add a second field to `mesh` and call it `myalternating`. `myalternating` will have the same properties as `alternating` except that its topology will be `mytopo` instead of `topo`. + +**Fourth** add a second plot (`p2`) to the scene `s1`. `p1` will still plot the field `alternating` and `p2` should plot `myalternating`. + +Finally, use AscentViewer to plot the result. +""" + +# conduit + ascent imports +import conduit +import conduit.blueprint +import ascent + +import math +import numpy as np + +# cleanup any old results +!./cleanup.sh + +# +# Create a 3D mesh defined on a uniform grid of points +# with two vertex associated fields named `alternating` and `myalternating` +# + +mesh = conduit.Node() + +# Create the coordinate sets + +# Create the first, original coordinate set +num_per_dim = 9 +mesh["coordsets/coords/type"] = "uniform"; +mesh["coordsets/coords/dims/i"] = num_per_dim +mesh["coordsets/coords/dims/j"] = num_per_dim +mesh["coordsets/coords/dims/k"] = num_per_dim + +# add origin and spacing to the coordset (optional) +mesh["coordsets/coords/origin/x"] = -10.0 +mesh["coordsets/coords/origin/y"] = -10.0 +mesh["coordsets/coords/origin/z"] = -10.0 + +distance_per_step = 20.0/(num_per_dim-1) + +mesh["coordsets/coords/spacing/dx"] = distance_per_step +mesh["coordsets/coords/spacing/dy"] = distance_per_step +mesh["coordsets/coords/spacing/dz"] = distance_per_step + +# Create the second coordinate set, `mycoords`, with the same dimensions and spacing +mesh["coordsets/mycoords/type"] = "uniform"; +mesh["coordsets/mycoords/dims/i"] = num_per_dim +mesh["coordsets/mycoords/dims/j"] = num_per_dim +mesh["coordsets/mycoords/dims/k"] = num_per_dim + +mesh["coordsets/mycoords/spacing/dx"] = distance_per_step +mesh["coordsets/mycoords/spacing/dy"] = distance_per_step +mesh["coordsets/mycoords/spacing/dz"] = distance_per_step + +# add an origin at (0,0,0) instead of (-10,-10,-10) +mesh["coordsets/mycoords/origin/x"] = 0.0 +mesh["coordsets/mycoords/origin/y"] = 0.0 +mesh["coordsets/mycoords/origin/z"] = 0.0 + +# Create topologies + +# add the topologies that will be used for each field +# Create the first topology, topo, which uses the coordinate set coords +mesh["topologies/topo/type"] = "uniform"; +# reference the coordinate set by name, coords +mesh["topologies/topo/coordset"] = "coords"; + +# Create the second topology, mytopo, which uses the coordinate set mycoords +mesh["topologies/mytopo/type"] = "uniform"; +# reference the secoond coordinate set by name, mycoords +mesh["topologies/mytopo/coordset"] = "mycoords"; + +# Create two fields named alternating and myalternating + +# Generate the data that will be plotted at the vertices on the mesh +num_vertices = num_per_dim * num_per_dim * num_per_dim +vals = np.zeros(num_vertices,dtype=np.float32) +for i in range(num_vertices): + if i%2: + vals[i] = 0.0 + else: + vals[i] = 1.0 + +# Create the first vertex-associated field, alternating, +# using the original topology, topo +mesh["fields/alternating/association"] = "vertex"; +mesh["fields/alternating/topology"] = "topo"; +mesh["fields/alternating/values"].set_external(vals) + +# Create the second vertex-associated field, alternating, +# using mytopo (and thereby mycoords) +mesh["fields/myalternating/association"] = "vertex"; +mesh["fields/myalternating/topology"] = "mytopo"; +mesh["fields/myalternating/values"].set_external(vals) + +# Print the mesh +print(mesh.to_yaml()) + +# Verify the mesh conforms to the blueprint +verify_info = conduit.Node() +if not conduit.blueprint.mesh.verify(mesh,verify_info): + print("Mesh Verify failed!") + print(verify_info.to_yaml()) +else: + print("Mesh verify success!") + +# Finally, let's plot both fields using Ascent +# We'll create one scene with two plots +a = ascent.Ascent() +a.open() + +# publish mesh to ascent +a.publish(mesh) + +# setup actions +actions = conduit.Node() +add_act = actions.append(); +add_act["action"] = "add_scenes"; + +# declare a scene (s1) with one plot (p1) +# to render the dataset +scenes = add_act["scenes"] +# First plot alternating +scenes["s1/plots/p1/type"] = "pseudocolor" +scenes["s1/plots/p1/field"] = "alternating" +# Add a second plot for myalternating +scenes["s1/plots/p2/type"] = "pseudocolor" +scenes["s1/plots/p2/field"] = "myalternating" + +# Set the output file name (ascent will add ".png") +scenes["s1/image_name"] = "out_ascent_render_uniform" + +# execute the actions +a.execute(actions) + +# show the result using the AscentViewer widget +ascent.jupyter.AscentViewer(a).show() \ No newline at end of file diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise4.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise4.py new file mode 100644 index 000000000..11b23def6 --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise4.py @@ -0,0 +1,85 @@ +""" +# Exercise 4 prompts: + +Use and modify the code from Scene Example 3 ("Adjusting camera parameters"). +Change the color scheme to Viridis and rotate the view of the tet example +360 degrees. + +**First**, update the name of the color table as in Example 4. + +**Second**, create 37 renders of `s1` with azimuth angles [0, 10, 20, 30, .... 360] + +Note: the following Python syntax for string interpolation may be helpful: + +``` +a = "world" +print(f"Hello {a}") +``` + +""" + +# ascent + conduit imports +import conduit +import conduit.blueprint +import ascent + +import numpy as np + +# helper for creating tutorial data +from ascent_tutorial_jupyter_utils import tutorial_tets_example + +# cleanup any old results +!./cleanup.sh + +# Prepare tet mesh +mesh = conduit.Node() +tutorial_tets_example(mesh) + +# Create Ascent instance and publish tet mesh +a = ascent.Ascent() +a.open() +a.publish(mesh) + +# Set up our actions +actions = conduit.Node() +add_act = actions.append() +add_act["action"] = "add_scenes" + +# Declare a scene to render the dataset +scenes = add_act["scenes"] + +# Set up our scene (s1) +scenes["s1/plots/p1/type"] = "pseudocolor" +scenes["s1/plots/p1/field"] = "var1" +scenes["s1/plots/p1/color_table/name"] = "Viridis" + +# Add renders of the field at different angles +# The view rotates 360 degrees in 10 degree increments, +# starting at and returning to 0 degrees +for i in range(37): + scenes[f"s1/renders/r{i}/image_name"] = f"out_scene_ex3_view{i}" + scenes[f"s1/renders/r{i}/camera/azimuth"] = 10.0*i + +# Without a loop, creating the first few renders would have looked +# like this: + +# scenes["s1/renders/r0/image_name"] = "out_scene_ex3_view0" +# scenes["s1/renders/r0/camera/azimuth"] = 0.0 + +# scenes["s1/renders/r1/image_name"] = "out_scene_ex3_view1" +# scenes["s1/renders/r1/camera/azimuth"] = 10.0 + +# scenes["s1/renders/r2/image_name"] = "out_scene_ex3_view2" +# scenes["s1/renders/r2/camera/azimuth"] = 20.0 + +# scenes["s1/renders/r3/image_name"] = "out_scene_ex3_view3" +# scenes["s1/renders/r3/camera/azimuth"] = 30.0 + +# scenes["s1/renders/r4/image_name"] = "out_scene_ex3_view4" +# scenes["s1/renders/r4/camera/azimuth"] = 40.0 + +# (...) + +a.execute(actions) + +ascent.jupyter.AscentViewer(a).show() \ No newline at end of file diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise5.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise5.py new file mode 100644 index 000000000..7941b6a5c --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise5.py @@ -0,0 +1,111 @@ +""" +# Exercise 5 prompts: + +Use and refactor the code in Pipeline Example 3. + +**First** break the second pipeline `pl2` with two filters into two pipelines (`pl2` and `pl3`) -- one with a single filter each. + +**Second** create separate plots in `s1` for each of the three pipelines. + +You should end with a single scene and three plots that you can toggle between. + +""" + +# ascent + conduit imports +import conduit +import conduit.blueprint +import ascent + +import numpy as np + +# cleanup any old results +!./cleanup.sh + +# Create example mesh + +# create example mesh using the conduit blueprint braid helper +mesh = conduit.Node() +conduit.blueprint.mesh.examples.braid("hexs", + 25, + 25, + 25, + mesh) + +a = ascent.Ascent() +a.open() + +# publish mesh to ascent +a.publish(mesh); + +# setup actions +actions = conduit.Node() +add_act = actions.append() +add_act["action"] = "add_pipelines" +pipelines = add_act["pipelines"] + +# create our first pipeline (pl1) +# with a contour filter (f1) +pipelines["pl1/f1/type"] = "contour" +# extract contours where braid variable +# equals 0.2 and 0.4 +contour_params = pipelines["pl1/f1/params"] +contour_params["field"] = "braid" +iso_vals = np.array([0.2, 0.4],dtype=np.float32) +contour_params["iso_values"].set(iso_vals) + +# create our second pipeline (pl2) with a threshold filter (f2) + +# add our threshold (pl2 f1) +pipelines["pl2/f2/type"] = "threshold" +thresh_params = pipelines["pl2/f2/params"] +# set threshold parameters +# keep elements with values between 0.0 and 0.5 +thresh_params["field"] = "braid" +thresh_params["min_value"] = 0.0 +thresh_params["max_value"] = 0.5 + + +# create our third pipeline (pl3) with a clip filter (f3) +pipelines["pl3/f3/type"] = "clip" +clip_params = pipelines["pl3/f3/params"] +# set clip parameters +# use spherical clip +clip_params["sphere/center/x"] = 0.0 +clip_params["sphere/center/y"] = 0.0 +clip_params["sphere/center/z"] = 0.0 +clip_params["sphere/radius"] = 12 + +# declare a scene to render our pipeline results +add_act2 = actions.append() +add_act2["action"] = "add_scenes" +scenes = add_act2["scenes"] + +# add a scene (s1) with two pseudocolor plots +# (p1 and p2) that will render the results +# of our pipelines (pl1 and pl2)## Pipeline Example 2: + +# scene (s1) to render our first pipeline (pl1) +scenes["s1/plots/p1/type"] = "pseudocolor" +scenes["s1/plots/p1/pipeline"] = "pl1" +scenes["s1/plots/p1/field"] = "braid" +# scene (s2) to render our second pipeline (pl2) +scenes["s2/plots/p1/type"] = "pseudocolor" +scenes["s2/plots/p1/pipeline"] = "pl2" +scenes["s2/plots/p1/field"] = "braid" +# scene (s3) to render our third pipeline (pl3) +scenes["s3/plots/p1/type"] = "pseudocolor" +scenes["s3/plots/p1/pipeline"] = "pl3" +scenes["s3/plots/p1/field"] = "braid" +# set the output file names (ascent will add ".png") +scenes["s1/image_name"] = "out_pipeline_ex3_1st_plot" +scenes["s2/image_name"] = "out_pipeline_ex3_2nd_plot" +scenes["s3/image_name"] = "out_pipeline_ex3_3rd_plot" + +# print our full actions tree +print(actions.to_yaml()) + +# execute +a.execute(actions) + +# show the resulting image +ascent.jupyter.AscentViewer(a).show() \ No newline at end of file diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise6.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise6.py new file mode 100644 index 000000000..88778ec77 --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise6.py @@ -0,0 +1,65 @@ +""" +# Exercise 6 prompts: + +Use and modify the code from Relay Extract Example 2 above. + +**First**, add a second field -- "radial" -- to be saved alongside "braid". + +**Second** change the protocol from hdf5 to yaml and change the path of the file created from `out_export_braid_one_field` to `out_export_braid_two_fields` + +""" + +import conduit +import conduit.blueprint +import ascent + +import numpy as np + +!./cleanup.sh + +# create example mesh using the conduit blueprint braid helper +mesh = conduit.Node() +conduit.blueprint.mesh.examples.braid("hexs", + 25, + 25, + 25, + mesh) + +# Use Ascent to export our mesh to blueprint flavored hdf5 files +a = ascent.Ascent() +a.open() + +# publish mesh to ascent +a.publish(mesh); + +# setup actions +actions = conduit.Node() +add_act = actions.append() +add_act["action"] = "add_extracts" + +# add a relay extract that will write mesh data to +# blueprint yaml file +extracts = add_act["extracts"] +extracts["e1/type"] = "relay" +# Change the path of the file created +extracts["e1/params/path"] = "out_export_braid_two_fields" +# Update the protocol from hdf5 to yaml +extracts["e1/params/protocol"] = "blueprint/mesh/yaml" + +# +# Original: add fields parameter to limit the export to +# just the `braid` field +# +extracts["e1/params/fields"].append().set("braid") +# For exercise, add the "radial" field +extracts["e1/params/fields"].append().set("radial") + + +# print our full actions tree +print(actions.to_yaml()) + +# execute the actions +a.execute(actions); + +# show details +ascent.jupyter.AscentViewer(a).show() \ No newline at end of file diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise7.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise7.py new file mode 100644 index 000000000..cad7a3972 --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise7.py @@ -0,0 +1,131 @@ +""" +# Exercise 7 prompts: + +Use and modify the code from Query Example 1: + +**First**, observe how changing the number of bins alters the entropy of the histogram in Query Example 1; change the number of bins from 128 to 64 and then to 32. + +**Second**, add two additional queries like `q2` -- `q3` with 64 bins and `q4` with 32 bins. + +**Third**, plot entropy vs. cycles for each of the three entropy queries. Create arrays to store the entropy as calculated for `q[1-3]` and overlay these entropies on the same plot. + +""" + +# ascent + conduit imports +import conduit +import conduit.blueprint +import ascent + +import numpy as np +import matplotlib.pyplot as plt + +# helpers we use to create tutorial data +from ascent_tutorial_jupyter_utils import tutorial_gyre_example + +# cleanup any old results +!./cleanup.sh + +# open ascent +a = ascent.Ascent() +a.open() + +# setup actions +actions = conduit.Node() +add_act = actions.append() +add_act["action"] = "add_queries" + +# declare a queries to ask some questions +queries = add_act["queries"] + +# add a simple query expression (q1) +queries["q1/params/expression"] = "cycle()" +queries["q1/params/name"] = "cycle" + +# For the exercise, you can start by changing the input `num_bins=128` to `num_bins=64` +# Then add queries q3 and q4 as below +queries["q2/params/expression"] = "entropy(histogram(field('gyre'), num_bins=128))" +queries["q2/params/name"] = "entropy_of_gyre" + +queries["q3/params/expression"] = "entropy(histogram(field('gyre'), num_bins=64))" +queries["q3/params/name"] = "entropy_of_gyre_64bins" + +queries["q4/params/expression"] = "entropy(histogram(field('gyre'), num_bins=32))" +queries["q4/params/name"] = "entropy_of_gyre_32bins" + +# declare a scene to render the dataset +add_scenes = actions.append() +add_scenes["action"] = "add_scenes" +scenes = add_scenes["scenes"] +scenes["s1/plots/p1/type"] = "pseudocolor" +scenes["s1/plots/p1/field"] = "gyre" +# Set the output file name (ascent will add ".png") +scenes["s1/image_name"] = "out_gyre" + +# view our full actions tree +print(actions.to_yaml()) + +# gyre time varying params +nsteps = 10 +time = 0.0 +delta_time = 0.5 + +info = conduit.Node() +for step in range(nsteps): + # call helper that generates a double gyre time varying example mesh. + # gyre ref :https://shaddenlab.berkeley.edu/uploads/LCS-tutorial/examples.html + mesh = tutorial_gyre_example(time) + + # update the example cycle + cycle = 100 + step * 100 + + mesh["state/cycle"] = cycle + print("time: {} cycle: {}".format(time,cycle)) + + # publish mesh to ascent + a.publish(mesh) + + # update image name + scenes["s1/image_name"] = "out_gyre_%04d" % step; + + # execute the actions + a.execute(actions) + + # retrieve the info node that contains the query results + ts_info = conduit.Node() + a.info(ts_info) + + # add to our running info + info["expressions"].update(ts_info["expressions"]) + + # update time + time = time + delta_time + +# close ascent +a.close() + +# create a 2D array with the entropy values from all +# cycles -- each row corresponds to the values from all +# cycles for a fixed number of bins. Each column has +# entropy values at a particular cycle for 128, 64, and 32 +# bins in the histogram +entropy = np.zeros([3, nsteps]) + +# For the exercise, we can make gyre a tuple that stores entropy information for all 3 calculations +gyre = info["expressions/entropy_of_gyre"], info["expressions/entropy_of_gyre_64bins"], info["expressions/entropy_of_gyre_32bins"] +# Grab `child_names()` associated with the first element of gyre (this was the original data used in Query Example 1) +cycle_names = gyre[0].child_names() + +# transfer conduit data to our summary numpy array +for i in range(3): + for j in range(gyre[0].number_of_children()): + entropy[i][j] = gyre[i][j]["value"] + +print("Entropy Result") +print(entropy) + +# plot the data for each of the 3 entropy arrays +for i in range(3): + plt.plot(cycle_names, entropy[i]) +plt.ylabel('entropy') +plt.xlabel('cycle') +plt.show() \ No newline at end of file diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise8.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise8.py new file mode 100644 index 000000000..86111180b --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise8.py @@ -0,0 +1,95 @@ +""" +# Exercise 8 prompts: + +Create your own trigger that sets up a scene with two renders (as in notebook 4) at cycle 1000. + +**First**, refactor the code from Trigger Example 1 to have a single trigger at cycle 1000. + +**Second**, create a new actions file or prepare to edit `cycle_trigger_actions.yaml`. Make sure your trigger is using the correct actions file. + +**Third**, edit your actions .yaml file to include two renders, as in notebook 4's "Scene Example 3". One render can use an azimuth angle of 10 degrees and the other a 3x zoom. + +**Fourth**, use `ascent.jupyter.AscentImageSequenceViewer` as above to plot the two .png files created by your trigger. + +""" + +# cleanup any old results +!./cleanup.sh + +# ascent + conduit imports +import conduit +import conduit.blueprint +import ascent + +import numpy as np + +# helpers we use to create tutorial data +from ascent_tutorial_jupyter_utils import img_display_width +from ascent_tutorial_jupyter_utils import tutorial_gyre_example + +import matplotlib.pyplot as plt + +# Use triggers to render when conditions occur +a = ascent.Ascent() +a.open() + +# setup actions +actions = conduit.Node() + +# declare a question to ask +add_queries = actions.append() +add_queries["action"] = "add_queries" + +# add our entropy query (q1) +queries = add_queries["queries"] +queries["q1/params/expression"] = "entropy(histogram(field('gyre'), num_bins=128))" +queries["q1/params/name"] = "entropy" + +# declare triggers +add_triggers = actions.append() +add_triggers["action"] = "add_triggers" +triggers = add_triggers["triggers"] + +# For the exercise, update `t1` to fire at cycle 1000. +# Create a new actions file or edit cycle_trigger_actions.yaml +# to specify two renders as in `solutions_notebook8.yaml` +triggers["myt1/params/condition"] = "cycle() == 1000" +triggers["myt1/params/actions_file"] = "solution_notebook8.yaml" + +# view our full actions tree +print(actions.to_yaml()) + +# gyre time varying params +nsteps = 10 +time = 0.0 +delta_time = 0.5 + +for step in range(nsteps): + # call helper that generates a double gyre time varying example mesh. + # gyre ref :https://shaddenlab.berkeley.edu/uploads/LCS-tutorial/examples.html + mesh = tutorial_gyre_example(time) + + # update the example cycle + cycle = 100 + step * 100 + mesh["state/cycle"] = cycle + print("time: {} cycle: {}".format(time,cycle)) + + # publish mesh to ascent + a.publish(mesh) + + # execute the actions + a.execute(actions) + + # update time + time = time + delta_time + +# retrieve the info node that contains the trigger and query results +info = conduit.Node() +a.info(info) + +# close ascent +a.close() + +# show the result image from the cycle trigger -- +# include whatever filenames you declared for your renders in your yaml file +ascent.jupyter.AscentImageSequenceViewer(["cycle_trigger_out_r1.png", "cycle_trigger_out_r2.png"]).show() \ No newline at end of file diff --git a/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise9.py b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise9.py new file mode 100644 index 000000000..c1ed1a054 --- /dev/null +++ b/src/examples/tutorial/ascent_intro/notebooks/solutions/exercise9.py @@ -0,0 +1,141 @@ +""" +# Exercise 9 prompts: + +**First**, swap out “radial” for “braid” in each of the queries for Binning Example 1 such as + +``` +queries["q1/params/expression"] = "binning('radial','max', [axis('x',num_bins=20)])"; +``` + +Run the resulting code to see how this modifies the final plots. + +**Second**, copy and modify the existing code for 1D binning projected along the x axis. Your modified code should +create a fourth query that 1D bins along the y axis and plot the result. + +**Note** that queries `q2` and `q3` are omitted from the solution for simplicity as they do not change. +""" + +# ascent + conduit imports +import conduit +import conduit.blueprint +import ascent + +import numpy as np + +# cleanup any old results +!./cleanup.sh + +# create example mesh using the conduit blueprint braid helper +mesh = conduit.Node() +conduit.blueprint.mesh.examples.braid("hexs", + 25, + 25, + 25, + mesh) + +## Data Binning Example + +# Use Ascent to bin an input mesh in a few ways +a = ascent.Ascent() + +# open ascent +a.open() + +# publish mesh to ascent +a.publish(mesh) + +# setup actions +actions = conduit.Node() +add_act = actions.append() +add_act["action"] = "add_queries" + +# declare a queries to ask some questions +queries = add_act["queries"] + +# Create a 1D binning projected onto the x-axis +queries["q1/params/expression"] = "binning('braid','max', [axis('x',num_bins=20)])"; +queries["q1/params/name"] = "1d_binning" + +# Create a 2D binning projected onto the x-y plane +queries["q2/params/expression"] = "binning('braid','max', [axis('x',num_bins=20), axis('y',num_bins=20)])"; +queries["q2/params/name"] = "2d_binning" + +# Create a binning that emulates a line-out, that is, bin all values +# between x = [-1,1], y = [-1,1] along the z-axis in 20 bins. +# The result is a 1x1x20 array +queries["q3/params/expression"] = "binning('braid','max', [axis('x',[-1,1]), axis('y', [-1,1]), axis('z', num_bins=20)])"; +queries["q3/params/name"] = "3d_binning" + +# Create a 1D binning projected onto the y-axis +queries["q4/params/expression"] = "binning('braid','max', [axis('y',num_bins=20)])"; +queries["q4/params/name"] = "1d_binning_y" + +# print our full actions tree +print(actions.to_yaml()) + +# execute the actions +a.execute(actions) + +## Plot results + +# extra imports for plotting +import yaml +import matplotlib.pyplot as plt + +# grab info from last execution which includes our binning results +info = conduit.Node() +a.info(info) + +## Plot the 1d binning result projected along x axis + +binning = info.fetch_existing('expressions/1d_binning') +cycles = binning.child_names() +bins = [] + +# loop through each cycle and grab the bins +for cycle in cycles: + bins.append(binning[cycle + '/attrs/value/value']) + +# create the coordinate axis using bin centers +x_axis = binning[cycles[0]]['attrs/bin_axes/value/x'] +x_min = x_axis['min_val'] +x_max = x_axis['max_val'] +x_bins = x_axis['num_bins'] + +x_delta = (x_max - x_min) / float(x_bins) +x_start = x_min + 0.5 * x_delta +x_vals = [] +for b in range(0,x_bins): + x_vals.append(b * x_delta + x_start) + +# plot the curve from the last cycle +plt.plot(x_vals, bins[-1]) +plt.xlabel('x position') +plt.ylabel('max braid') + +## Plot the 1d binning result projected along y axis + +binning = info.fetch_existing('expressions/1d_binning_y') +cycles = binning.child_names() +bins = [] + +# loop through each cycle and grab the bins +for cycle in cycles: + bins.append(binning[cycle + '/attrs/value/value']) + +# create the coordinate axis using bin centers +y_axis = binning[cycles[0]]['attrs/bin_axes/value/y'] +y_min = y_axis['min_val'] +y_max = y_axis['max_val'] +y_bins = y_axis['num_bins'] + +y_delta = (y_max - y_min) / float(y_bins) +y_start = y_min + 0.5 * y_delta +y_vals = [] +for b in range(0,x_bins): + y_vals.append(b * y_delta + y_start) + +# plot the curve from the last cycle +plt.plot(y_vals, bins[-1]) +plt.xlabel('y position') +plt.ylabel('max braid') \ No newline at end of file