Welcome to the final half of part 2! Here I'm going to show you how to script your keyframes for your race graph using the data that we already have. In this tutorial we assume your graph is set up with a dictionary like in Part 1.2. We'll be using a lot of for loops in our scripting and I'll break down the code so anyone reading this can understand what's going on. The full keyframing script can be found in the Appendix of the HTML Jupyter Notebook linked for download at the bottom of this page.
Section 1. Modules and data
First, we're going to import bpy and then declare our data. Here, I am declaring the data for my example graph in a dictionary. In Python, a dictionary is used to assign 'values' to 'keys'. Our keys are the months Jan to Jun, and the values assigned to them are the lists of numbers which represent a value of 'beans' in each 'pot' for that month.
Section 2. Setting up some Variables
Now we have a few things that we need to set up before the real computation.
Gridx: is the length of your grid which is the same as the Gridx value for the graph that you generated.
objList: is a list of objects that have the word 'Cube' in their name which we've filled with a list comprehension.
ind: is a list of the keys we have in dataDict
maxFr: calculates the maximum frame range that we want our keyframes to span. I've set it up such that we'll get 48 frames per month in dataDict.
Fr: calculates the frames that we want to assign keyframes to. The first 48 is our starting frame, maxFr+1 is our end frame and the last 48 is our increment. This means that we're going to assign a keyframe every 48 frames from frame 48 to our maximum frame.
Section 3. Scripting Growth Keyframes
Now all that's left to do is create keyframes for every bar for every month in dataDict at our desired frames calculated in Fr. Here we have a nested for loop which you generally want to avoid cause they're a little slow but speed isn't a huge issue here so I didn't bother worrying about it.
The first for loop goes through every key in dataDict which are our months. It gets the frame we want from list Fr and stores the key corresponding to our month into currentkey.
The second for loop then loops through all the values in currentkey which are just the values for the current month our first loop is up to. We then calculate the length of our bar according to what is store in dataDict and then store that calculation in Dist. We select the hook that corresponds to the bar that corresponds to that value. The next line then translates the bar length by the amount that was calculated in Dist. The second last line assigns a keyframe for the Location of the currently selected hook object. The last line deselects the hook. These steps are repeated for every hook and for each month of data in dataDict.
Now when you run the keyframer script you should get a result similar to the image below:
![broken image](http://custom-images.strikinglycdn.com/res/hrscywv4p/image/upload/c_limit,fl_lossy,h_9000,w_1200,f_auto,q_60/735811/404552_493639.gif)
Section 4. Scripting Sorting Keyframes
Now we're ready to script our basic sorting algorithm. We'll be moving the bars around so we'll need to keyframe those next. Open up the Scripting workspace, create a new script and don't forget to name it something useful. As always, we'll start with importing our modules. In this case we'll only need the bpy module. Next, we'll need a list of the name of all our bar objects so here we're telling Python to store the name of every object with the word 'Cube' in it into a list called objList. maxFr is the same as in the previous section.
We've got some nested for loops again. The outer-most loop sets the frames we want to key. The first nested loop uses an if statement to compare the elements in objList. The comparison is done for two elements at a time. If the second element is longer than the first than their object locations on the grid get swapped as do their places within the objList. In this way we're using the objList as a ranking system.
This second nested for loop goes through each object in objList and sets keyframes for the new positions.
If you get lost or confused a full version of the script is available in the appendix of the HTML Jupyter Notebook found at the end of this tutorial. When you run the script you should get a similar result to below:
![broken image](http://custom-images.strikinglycdn.com/res/hrscywv4p/image/upload/c_limit,fl_lossy,h_9000,w_1200,f_auto,q_60/735811/821730_87077.gif)
Optional Rendering Snippets
I have some final bits of code here for those wanting to generate column graphs with cameras and lights already set to their desired locations. These bits of code are purely optional but I include then here for those who might find them useful. Just stick the snippets to the end of your script. They shouldn't interfere with anything else already written in.
A final word from Kit
Thank you for reading this tutorial. Hopefully you were able to get things up and running without too much trouble. I recommend that you download the HTML Jupyter Notebook for offline use. It has a full copy of all scripts for you to reference if you get stuck and some extra tidbits at the end including animating text with the Blender addon Animation Nodes. :)
The download link for the HTML Jupyter Notebook can be found here: Data Visualisation in Blender Part 2
If you have any questions you're welcome to send messages to this email address: steambeanblog@gmail.com
Stay safe everyone!