Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model Vis inline with Callback ipynb #13

Open
wants to merge 90 commits into
base: examples
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 85 commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
c43179b
Merge pull request #4 from cropsinsilico/no_double_add_node
matthewturk Oct 18, 2021
e163455
Add in solo work
Xyzic Oct 18, 2021
e911ce3
Merge pull request #6 from cropsinsilico/examples
matthewturk Oct 19, 2021
a348b5c
Add tabs that display currently selected node
matthewturk Oct 19, 2021
d5ee9a3
Added in hard-coded cleanup function
Xyzic Oct 19, 2021
7eb2c00
Sync input/output slots and observe changes
matthewturk Oct 20, 2021
3eebc95
Cleaned up a bit, added in requested changes
Xyzic Oct 20, 2021
40dce43
Enumeration
Xyzic Oct 20, 2021
5af2c55
Files
Xyzic Nov 30, 2021
fe156a8
Tester TO-DO
Xyzic Nov 30, 2021
454998e
Skeleton
Xyzic Dec 1, 2021
0b63b59
Added pytest
Xyzic Dec 1, 2021
cd72dd1
Bugfix example, delete MAtt's code
Xyzic Dec 6, 2021
9c616df
removed useless imports
Xyzic Dec 6, 2021
ac09350
addeda test
Xyzic Dec 6, 2021
29a6f46
testing updates
Xyzic Dec 7, 2021
411b2f0
moving back to focus on manual testing/parsing
Xyzic Dec 7, 2021
b5bab10
start making sample models
Xyzic Dec 7, 2021
e2d2a43
Added first sample model
Xyzic Dec 10, 2021
c837477
Completed all 3 sample models
Xyzic Dec 10, 2021
fdb71da
Modify tests, begin update parser
Xyzic Dec 10, 2021
12f658b
Added skeleton for testing instance
Xyzic Dec 17, 2021
5e1c925
Begin testing
Xyzic Dec 17, 2021
0731c65
Classified single vs multi models
Xyzic Dec 17, 2021
a737e0a
Sample Model 2 passes parsing!
Xyzic Dec 17, 2021
3297bd0
Integrated example w singular function
Xyzic Dec 20, 2021
0a55b90
Can now input any kind of model for testing
Xyzic Dec 20, 2021
4e09e61
sample model 1 is working
Xyzic Dec 20, 2021
8cd10bd
Passes all sample parsing
Xyzic Dec 20, 2021
916e0eb
Finished looking through
Xyzic Dec 22, 2021
d6595f8
Removed useless file, added note
Xyzic Dec 30, 2021
c82ec1e
Adjustments, check slack
Xyzic Dec 30, 2021
b171a9c
fstrings
Xyzic Jan 3, 2022
9c9cc00
Delete yggdrasil_support.py
Xyzic Jan 3, 2022
815c617
Remove TODO
Xyzic Jan 6, 2022
ea213a7
Merge pull request #7 from cropsinsilico/viz_panel
matthewturk Jan 6, 2022
606862e
Merge pull request #5 from Xyzic/main
matthewturk Jan 6, 2022
1f5530f
Created MPL WIP
Xyzic Jan 6, 2022
a22d619
Updated
Xyzic Jan 7, 2022
b8d1f0f
Delete garbage files
Xyzic Jan 7, 2022
7e6a4e5
Updated on widgets, WIP
Xyzic Jan 10, 2022
8049284
Delete autogenerate_sidebar.ipynb
Xyzic Jan 10, 2022
1f0743e
Add in png temp workaround
Xyzic Jan 10, 2022
d3dc491
Added in an updating function and second test plot
Xyzic Jan 10, 2022
ac70340
Changed plots for testing
Xyzic Jan 10, 2022
36c45fd
Now updates on function call
Xyzic Jan 10, 2022
4732d95
Updated todo
Xyzic Jan 10, 2022
231028a
Progress, almost have sliders working
Xyzic Jan 11, 2022
c969472
Fixed issue w sync
Xyzic Jan 11, 2022
d8f61f4
Moved files, added as an example
Xyzic Jan 13, 2022
0007d98
Updated the wip notebook
Xyzic Jan 18, 2022
75c4001
Adding in photosynth model
Xyzic Jan 18, 2022
87e5df3
Added in float boxes instead of sliders
Xyzic Jan 20, 2022
123f8db
Sample Modeling Yggdrasil
Xyzic Feb 8, 2022
8aa5e69
Finished Reader
Xyzic Feb 8, 2022
42db001
Cleanup
Xyzic Feb 9, 2022
0f69e94
Merge branch 'main' of https://github.com/Xyzic/jupyterlab_nodeeditor
Xyzic Mar 8, 2022
22c19ec
03/08 changes
Xyzic Mar 9, 2022
322dea3
03/08 unignored
Xyzic Mar 9, 2022
138b68e
Continue rebuilding
Xyzic Mar 9, 2022
6f4ad1f
03/08 final push
Xyzic Mar 9, 2022
ae94949
03/11 Updates
Xyzic Mar 11, 2022
bc11f14
Desync'd models because of string issues
Xyzic Mar 11, 2022
ba8eca5
All in 1 cell
Xyzic Mar 11, 2022
afb8625
Adding in files for the parser
Xyzic Mar 30, 2022
6af1f87
Cleaning up for better tutorial
Xyzic Apr 5, 2022
552ad2e
Added note for rows and i/os
Xyzic Apr 5, 2022
dc50697
Moving stuff for PR
Xyzic Apr 5, 2022
3dcbc4a
Moved again
Xyzic Apr 5, 2022
0b9cda6
Update .gitignore
Xyzic Apr 5, 2022
39ffff3
Update .gitignore
Xyzic Apr 5, 2022
eae00d6
Delete examples/wip_notebooks directory
Xyzic Apr 5, 2022
42a9226
Add stuff to ignore list
Xyzic Apr 5, 2022
38fdf24
Merge branch 'main' of https://github.com/Xyzic/jupyterlab_nodeeditor
Xyzic Apr 5, 2022
a1ea143
Update .gitignore
Xyzic Apr 5, 2022
ef2f5eb
Revisions round 1
Xyzic Apr 6, 2022
bd578df
Remove requested file and add in more examples from video tutorial
Xyzic Apr 15, 2022
fb66995
Ignoring
Xyzic Jun 1, 2022
8ad4360
Automation of modelvis
Xyzic Jun 1, 2022
99fda1a
Update .gitignore
Xyzic Jun 1, 2022
1a09036
cleared
Xyzic Jun 1, 2022
33c01cf
Update .gitignore
Xyzic Jun 1, 2022
a71f81e
Merge branch 'examples' into main
Xyzic Jun 8, 2022
1489e6d
Streamline new notebook into one function
Xyzic Jul 11, 2022
7215b3c
Automation
Xyzic Jul 19, 2022
87fd4bd
Use os
Xyzic Aug 4, 2022
d011d4e
add todo
Xyzic Aug 5, 2022
65c467b
Batch update of returns
Xyzic Aug 9, 2022
d14d43f
Black formatting
Xyzic Aug 9, 2022
37145f3
ignore nodejs stuff
Xyzic Aug 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ dmypy.json

# WIP stuff
/examples/wip_notebooks
/examples/sample_test_models/trifecta_output

# Not my examples
/examples/example_jlne
/examples/example_matplotlib
/examples/example_node_editor
/examples/example_rete
/examples/make_an_editor

# VS Code Folder
/.vscode
examples/example_jlne.ipynb
examples/sample_test_models/trifecta_output.txt
92 changes: 92 additions & 0 deletions examples/automated_modelvis.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "989d4419-dcd1-465a-aa00-2deca223b7cd",
"metadata": {},
"outputs": [],
"source": [
"import jupyterlab_nodeeditor as jlne\n",
"import ipywidgets\n",
"import time\n",
"from yggdrasil.runner import YggRunner\n",
"ne = jlne.NodeEditor()\n",
"\n",
"# Change this to your model's filepath\n",
"model_filepath = \"sample_test_models\\model_trifecta.yml\"\n",
Xyzic marked this conversation as resolved.
Show resolved Hide resolved
"jlne.load_model(model_filepath, ne)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dd6b2195-1b2d-4241-a434-55676fee3e44",
"metadata": {},
"outputs": [],
"source": [
"# Create a runner for the model, adjust the filepath for wherever the model is located\n",
"runner = YggRunner(model_filepath)\n",
"\n",
"# Create the callback class and update the first tab with live information\n",
"\n",
"class VariableDisplay:\n",
" # We add in filler labels to overwrite with actual data later since it is automated\n",
" if len(ne.node_editor.nodes[0].display_element.children) <= 5:\n",
" for i in range(len(list(runner.connectiondrivers))):\n",
" ne.node_editor.nodes[0].display_element.children += (ipywidgets.Label(\"Initializing\"),)\n",
" \n",
" # The initialization will have the label from ipywidgets but also the name of the variable and it's order in the list\n",
" def __init__(self, elem_number, name):\n",
" self.label = ipywidgets.Label()\n",
" self.elem_number = elem_number\n",
" self.name = name\n",
" \n",
" # Display data will always show the relevant information taken from the dictionary itself and use the default dictionary key as it's name\n",
" # As of May 31st, 2022, the timesync bug still exists, so the time.sleep is necessary to see it run in realtime\n",
" # Otherwise, it still works as intended\n",
" # If you are only processing basic tings, you may opt to use the clean_bytes function with 'args[0].args' though it may be better to not use it as it may convolute the data being processed\n",
" def display_data(self, *args, **kwargs):\n",
" ne.node_editor.nodes[0].display_element.children[self.elem_number].value = f\"{self.name}: {args[0].args}\"\n",
" time.sleep(1)\n",
"\n",
"# We pull the exact drivers from the dictionary keys from the model itself here\n",
"for i, v in enumerate(list(runner.connectiondrivers)):\n",
" display = VariableDisplay(i + 3, v.split(\":\")[1])\n",
" runner.connectiondrivers[v]['callbacks'] = [display.display_data]\n",
"\n",
"# Run the runner to see the data update in realtime\n",
"runner.run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a582ed70-cbbd-47e3-9b40-125aa36b56c9",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "yggJLNE",
"language": "python",
"name": "yggjlne"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
25 changes: 25 additions & 0 deletions examples/example_jlne.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,31 @@
" 'name': 'My Model'}}}})"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "aded3656-07c8-4b47-8058-4d0c7ee7a3dd",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"NodeEditorModel(selected_node=None)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(editor)"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
128 changes: 60 additions & 68 deletions examples/example_modelvis.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
{
"cell_type": "markdown",
"id": "27b8d143-d596-4d62-ae11-39e4ac67f0eb",
"metadata": {},
"metadata": {
"tags": []
},
"source": [
"### Libraries Used\n",
"As a note, please be sure to have model_loader.py in the same folder as this"
"### Libraries Used"
]
},
{
Expand All @@ -28,6 +29,7 @@
"source": [
"import jupyterlab_nodeeditor as jlne\n",
"import ipywidgets\n",
"import time\n",
"from yggdrasil.runner import YggRunner"
]
},
Expand All @@ -36,12 +38,13 @@
"id": "be8f959e-d5ea-45a1-9071-1ab1e199d171",
"metadata": {},
"source": [
"### Helper Function: Clean Bytes\n",
"### Optional Helper Function: Clean Bytes\n",
"Input: A 'bytes' type of data\n",
"\n",
"Output: A cleaned 'string' conversion of the input\n",
"\n",
"The reason behind this is just to make the output legible by removing quotations and any useless characters."
"The reason behind this is just to make the output legible by removing quotations and any useless characters.\n",
"Note: Only works on some models"
]
},
{
Expand All @@ -51,14 +54,8 @@
"metadata": {},
"outputs": [],
"source": [
"# This will be a cleaner for the sidebar display\n",
"def clean_bytes(ibytes):\n",
" sbytes = str(ibytes)[1:].strip(\"'\")\n",
" if \"\\\\n\" in sbytes:\n",
" clean = sbytes[:-2]\n",
" else:\n",
" clean = sbytes\n",
" return clean"
" return str(ibytes)[1:-1].strip()"
]
},
{
Expand All @@ -78,6 +75,8 @@
"\n",
"**Make sure you manually right click and add all of your desired components once the editor appears.**\n",
"\n",
"While the rest of the notebook only needs 1 tab to run, it is important to notice how your model is loaded.\n",
"\n",
"As of March 30th, 2022, there is a bug that does not allow for the components to be linked. We are working on fixing that but for production it will still execute normally."
]
},
Expand All @@ -89,61 +88,32 @@
"outputs": [],
"source": [
"ne = jlne.NodeEditor()\n",
"jlne.load_model(ne)"
"\n",
"# Change this to your model's filepath\n",
"model_filepath = \"sample_test_models\\model_trifecta.yml\"\n",
"\n",
"jlne.load_model(model_filepath, ne)"
]
},
{
"cell_type": "markdown",
"id": "162e6c02-5215-45f0-8f8f-245877a87c21",
"id": "8c75c955-cd4a-40e5-a75b-21dda69332f6",
"metadata": {},
"source": [
"### Callback Classes and Display\n",
"This is where things get a bit messy and will need to be adjusted based on your specific model.\n",
"\n",
"The class name doesn't matter (*CBJLNE* - CallBack JLNE) so long as it is called properly. The comments in the code will explain each portion to better help the flow of this example.\n",
"\n",
"*args[0]* is where the data in the runner is stored (i.e. the data that is being moved around, in the sample model's case, the number, line of text, and the rotated output)\n",
"\n",
"*Note: You will see that we use the 3, 4, and 5 indices for the children but this modifies the sixth, seventh, and eighth rows in the tab. This is due to the Inputs/Outputs in JLNE spacing out their actual name to the next line. For example, under Inputs in Tab 3 it says \"Slot 1: input_rotxx (temp_in0)\" in the next row, but this is still all in the 2nd ipywidgets Label, just spread out for visual clarity in case of multiple Inputs/Outputs. If you need more to display, continue the index trend and do not worry about the rows. Be sure to add them to the initial length check as well so all rows are created properly.*"
"Right click the JLNE instance and open a new view in a seperate tab when you run the YggRunner below."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3efbcbef-887c-462d-af0b-a4257f3eba6c",
"cell_type": "markdown",
"id": "162e6c02-5215-45f0-8f8f-245877a87c21",
"metadata": {},
"outputs": [],
"source": [
"# Create the callback class and have the third component be updated with live information\n",
"# You can add/remove/adjust functions that best suit what data you want to output\n",
"# As of March 30th, 2022 there is an issue with connected components in JLNE but the third tab will display the correct information regardless\n",
"class CBJLNE:\n",
" # We check if there are 5 elements in the tab already. On initialization, this is not the case, so we add 3 more to the third tab,\n",
" # which is index number 2, and add in filler labels until they are overwritten with the actual data\n",
" if len(ne.node_editor.nodes[2].display_element.children) <= 5:\n",
" for i in range(3):\n",
" ne.node_editor.nodes[2].display_element.children += (ipywidgets.Label(\"Initializing\"),)\n",
" \n",
" # The initialization just puts a Label in for this class\n",
" def __init__(self):\n",
" self.label = ipywidgets.Label()\n",
" \n",
" # Display Number pulls the number from Model RNG to display in the sixth row in the third tab\n",
" def display_number(self, *args, **kwargs):\n",
" ne.node_editor.nodes[2].display_element.children[3].value = f\"Number: {args[0].args[0]}\"\n",
" \n",
" # Display String pulls the line text from Model Reader to display in the seventh row in the third tab and cleans it using the previously defined Clean Bytes\n",
" # For some reason, this one runs much faster than the other two, but the print() statement shows that it still does go through each line, just at light speed\n",
" def display_string(self, *args, **kwargs):\n",
" print(clean_bytes(args[0].args))\n",
" ne.node_editor.nodes[2].display_element.children[4].value = f\"String: {clean_bytes(args[0].args)}\"\n",
" \n",
" # Display Rotated pulls the output from the Trifecta Model (i.e. the Rotated data) to show in the eighth row in the third tab\n",
" def display_rotated(self, *args, **kwargs):\n",
" ne.node_editor.nodes[2].display_element.children[5].value = f\"Rotated: {args[0].args}\"\n",
"### Callback Classes and Display\n",
"This is where things get a bit messy **but** is still automated. The explanations may just seem difficult to understand, but I will do my best to simplify things and explain them in detail still.\n",
"\n",
"The class name doesn't matter (*VariableDisplay* - Display the variable) so long as it is called properly. The comments in the code will explain each portion to better help the flow of this example.\n",
"\n",
"# Make sure to call the class with a name that is easy to remember for use\n",
"display = CBJLNE()"
"*args[0]* is where the data in the runner is stored (i.e. the data that is being moved around, in the sample model's case, the number, line of text, and the rotated output)"
]
},
{
Expand All @@ -152,7 +122,7 @@
"metadata": {},
"source": [
"### Connection Drivers\n",
"By having a runner on the model path, we can execute the YAML file directly inside the notebook. Please make sure to change this path to the actual filepath of the YAML."
"By having a runner on the model path, we can execute the YAML file directly inside the notebook. Please make sure that the variable \"model_filepath\" was changed correctly above."
]
},
{
Expand All @@ -163,25 +133,47 @@
"outputs": [],
"source": [
"# Create a runner for the model, adjust the filepath for wherever the model is located\n",
"runner = YggRunner(\"sample_test_models/model_trifecta.yml\")"
"runner = YggRunner(model_filepath)"
]
},
{
"cell_type": "markdown",
"id": "cb23b6e2-6d99-4343-aa86-ea22dd7807b1",
"metadata": {},
"source": [
"You will need to uncomment the below line and run it to see what your YAML looks like as a runner in order to properly match the class functions to their connections"
"Below is the class that will update the JLNE instance in real time.\n",
"\n",
"Read the comments for more details but the basic gist is that it will take each parsed component's arguments and output them as they are run in the first tab in the visualization"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "227ea659-2c1a-4285-8798-3bcb44beec02",
"id": "c6927599-6113-45c2-a88f-76e9bb2d8291",
"metadata": {},
"outputs": [],
"source": [
"# runner.connectiondrivers"
"# Create the callback class and update the first tab with live information\n",
"\n",
"class VariableDisplay:\n",
" # We add in filler labels to overwrite with actual data later since it is automated\n",
" if len(ne.node_editor.nodes[0].display_element.children) <= 5:\n",
" for i in range(len(list(runner.connectiondrivers))):\n",
" ne.node_editor.nodes[0].display_element.children += (ipywidgets.Label(\"Initializing\"),)\n",
" \n",
" # The initialization will have the label from ipywidgets but also the name of the variable and it's order in the list\n",
" def __init__(self, elem_number, name):\n",
" self.label = ipywidgets.Label()\n",
" self.elem_number = elem_number\n",
" self.name = name\n",
" \n",
" # Display data will always show the relevant information taken from the dictionary itself and use the default dictionary key as it's name\n",
" # As of May 31st, 2022, the timesync bug still exists, so the time.sleep is necessary to see it run in realtime\n",
" # Otherwise, it still works as intended\n",
" # If you are only processing basic tings, you may opt to use the clean_bytes function with 'args[0].args' though it may be better to not use it as it may convolute the data being processed\n",
" def display_data(self, *args, **kwargs):\n",
" ne.node_editor.nodes[0].display_element.children[self.elem_number].value = f\"{self.name}: {args[0].args}\"\n",
" time.sleep(1)"
]
},
{
Expand All @@ -195,11 +187,11 @@
"2. The random number and line of text connected to the ROTXX model\n",
"3. The output of the ROTXX model (i.e. the rotated string)\n",
"\n",
"To utilize realtime updating with a Yggdrasil Runner, we need ot add in a 'callbacks' key to each connectiondriver. The value of this key will be the class function corresponding to the data you want to show casted to a list.\n",
"To utilize realtime updating with a Yggdrasil Runner, we need to add in a 'callbacks' key to each connectiondriver. The value of this key will be the class function corresponding to the data you want to show casted to a list.\n",
"\n",
"To break it down further, the value must be the class class with brackets around it so it is recognized by the Runner. This will allow the Runner to call back to that class function whenever the model is run. This is why you can create/remove/adjust any functions from the sample set to best fit your model. \n",
"To break it down further, the value must be the class class with brackets around it so it is recognized by the Runner. This will allow the Runner to call back to that class function whenever the model is run. \n",
"\n",
"**Be sure to call the correct function on the correct connection**"
"**This is all automated for you; there is no need to adjust any functions, just run the cells!**"
]
},
{
Expand All @@ -209,10 +201,10 @@
"metadata": {},
"outputs": [],
"source": [
"# Add in the callback functions to the connection drivers for execution\n",
"runner.connectiondrivers['model_reader:inputReader']['callbacks'] = [display.display_string]\n",
"runner.connectiondrivers['model_rng:outputRNG,model_reader:outputReader_to_model_rotxx:input_rotxx']['callbacks'] = [display.display_number]\n",
"runner.connectiondrivers['model_rotxx:output_rotxx']['callbacks'] = [display.display_rotated]"
"# We pull the exact drivers from the dictionary keys from the model itself here\n",
"for i, v in enumerate(list(runner.connectiondrivers)):\n",
" display = VariableDisplay(i + 3, v.split(\":\")[1])\n",
" runner.connectiondrivers[v]['callbacks'] = [display.display_data]"
]
},
{
Expand All @@ -239,7 +231,7 @@
"id": "9b7b4c72-f60b-4cdc-9049-f208465584e0",
"metadata": {},
"source": [
"If you need to make adjustments and rerun, you must reload the Runner as well and everything after it (All of the Connection Drivers tab minus seeing the actual drivers)"
"If you need to rerun, you must reload the YggRunner as well as everything after it (All of the Connection Drivers tab minus seeing the actual drivers)"
]
},
{
Expand Down
8 changes: 4 additions & 4 deletions examples/sample_test_models/trifecta_output.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# %s
fqefxuzq
docdvsxo
hsghzwbs
znoysujkrcorrcuxqcoznsainrutmkxzkdzlorkygyckrr
epdewtyp
paopheja
alzaspul
rfgqkmbcjugjjumpiugrfksafjmlecprcvrdgjcqyqucjj
Loading