These Python scripts generate simple anatomical videos in Blender, following the conventions common in neuroscience research on the Drosophila fruit fly. The input is a JSON file giving a high-level description of anatomical elements (e.g., segmented neurons, regions of interest, synapses) and how they are animated (e.g., the camera frames on some neurons, then those neurons fade out while the camera orbits around them). An experimental application can create the JSON from natural language using generative AI. Renderings of high quality can be done with a path-tracing renderer: Blender's Cycles, or the OTOY Octane renderer (which requires a commercial license). Here is a video scripted with neuVid
and rendered with Octane (with titles added separately in iMovie):
See more examples in the neuVid gallery.
These scripts also support volumetric data sets with no explicit segmentation. An example is the H5J format volumes in the Janelia FlyLight Split-GAL4 driver collection. This kind of data is rendered with direct volume rendering by VVDViewer.
neuPrint
The simplest way to start using neuVid
is to import data from neuPrint
, a web-based system for browsing the neurons and synapses in connectomes. The set-up involves just two downloads, and the hands-on time can be as little as a few minutes, as demonstrated in the following tutorial video:
Here are the steps:
Install Blender. These scripts will work with the latest version, and older versions back to 2.79.
Open a terminal (shell) and clone this repository.
Find some neurons (and synapses if desired) in neuPrint
, and switch to neuPrint
's Neuroglancer tab.
Press the "Copy view URL to clipboard" button (icon: two overlapping squares) at right side of the Neuroglancer header bar.
Run the script to read the clipboard and output the JSON file that specifies the video. In the following, blender
is shorthand for the actual platform-specific path to the Blender executable: /Applications/Blender.app/Contents/MacOS/Blender
on macOS; something like /usr/local/blender/blender-3.4.1-linux-x64/blender
on Linux; something like "C:\Program Files\Blender Foundation\Blender 3.4\blender.exe"
on Windows, with the quotes being necessary due to the spaces in the path. Note also that with Windows PowerShell, the executable must be preceded by &
, as in & "C:\Program Files\Blender Foundation\Blender 3.4\blender.exe"
.
blender --background --python neuVid/neuVid/importNg.py -- -o ex1.json
Note that on Windows, the path to the Blender executable may well contain spaces, as in C:\Program Files\Blender Foundation\Blender 3.3\blender.exe
. To run it in the command shell, put quotes around the path, as in "C:\Program Files\Blender Foundation\Blender 3.3\blender.exe" --background --python ...
.
Experimental option -t
(or --typesplit
): groups imported neurons by type, where available.
Run the script to download meshes and create the basic Blender file (without animation) in the same directory as the JSON file. This stage also creates directories for downloaded mesh files (neuVidNeuronMeshes
, neuVidRoiMeshes
, neuVidSynapseMeshes
) in the same directory as the JSON file.
blender --background --python neuVid/neuVid/importMeshes.py -- -i ex1.json
Run the script to create a second Blender file with animation. Adding animation is a separate step since it can take significantly less time than creating the basic Blender file, and may need to be done repeatedly as the animation specification is refined.
blender --background --python neuVid/neuVid/addAnimation.py -- -i ex1.json
If desired, preview the animation by opening the second blender file (ex1Anim.blend
) in a normal interactive (not background) Blender session.
Run the script to render the animation with Blender's Cycles renderer. This step takes the longest (tens of minutes on a modern desktop or laptop computer). The rendered frames go to a subdirectory (ex1-frames
) in the same directory as the JSON file.
blender --background --python neuVid/neuVid/render.py -- -i ex1.json
Run the script to assemble the rendered frames into a video (named ex1-frames/0001-N.avi
, where N
is the number of rendered frames).
blender --background --python neuVid/neuVid/assembleFrames.py -- -i ex1.json
A second tutorial shows how to make more sophisticated videos with more camera motion:
Note how the neuPrint
workflow involves Neuroglancer, a WebGL-based viewer for large data sets like those from connectomics. Neuroglancer handles other data sets, and some of them can be imported into neuVid
, too. An example from neuroscience is the FAFB data set in its FlyWire Codex and FFN1 forms (FAFB synapses are not yet supported), and an example from cell biology is the interphase HeLa cell from the OpenOrganelle collection:
When importing from Neuroglancer outside neuPrint
, some extra Python modules are needed. These modules process the Neuroglancer "precomputed" format that stores multiresolution and/or sharded meshes, converting the meshes to OBJ files for futher processing in neuVid
. A good way to manage the installation of these modules (so they do not interfere with other uses of Python) is to use the Miniforge version of Conda (which is free of license fees for educational and non-profit institutions). First, install Miniforge itself. (Note that there is an "arm64" version of Conda for Apple silicon, like the M1 chip, but the packages needed here do not yet work with it; use the legacy "x86_64" version of Conda instead.) Next, create an environment (named "neuVid-NG", for example) with the extra modules, like MeshParty:
conda create --name neuVid-NG python=3.9
conda activate neuVid-NG
python -m pip install meshparty==1.16.7 open3d==0.15.1 trimesh==3.15.1 'numpy<2'
Note that as of Q4 2024, the explicit versions for meshparty
, open3d
and trimesh
, and the requirement of not using numpy
version 2, seem to be necessary to get the (arguably fragile) process of importing from FlyWire to work successfuly.
Then follow these steps to use neuVid
:
Make sure Blender is installed, and this repository is cloned, as above.
Make sure that the browser is showing Neuroglancer with a URL visible. For example, with FlyWire Codex, press the "NGL↗" button.
In Neuroglancer, make the desired segments visible (e.g., right-click on the layer tab to get the side bar, switch to the "Seg" tab, click the top check box to make all IDs visible).
Click on the browser URL for Neuroglancer to select it, and copy it to the clipboard. (It is a very long URL.)
In a terminal (shell), activate the Conda environment to make the extra modules available:
conda activate neuVid-NG
Run the script to convert the Neuroglancer URL in the clipboard into the JSON file that specifies the video. Remember that blender
is shorthand for the actual platform-specific path to the Blender executable, as described above.
blender --background --python neuVid/neuVid/importNg.py -- -o ex2.json
Run the script that fetches the meshes from the Neuroglancer sources. Note that this script runs with python
directly instead of using Blender (which does not know about the extra Python modules).
python neuVid/neuVid/fetchMeshes.py -i ex2.json
(Don't worry if a spurious error like Exception ignored in: <function Pool.__del__ at 0x7f97b9d13e50>
appears as this script completes.)
Edit the ex2.json
file to create the desired animation; see the detailed neuVid
documentation. That documentation discusses another approach to defining the animation, involving multiple Neuroglancer URLs that define key moments in the animation.
Run the remaining neuVid
scripts as above:
blender --background --python neuVid/neuVid/importMeshes.py -- -i ex2.json
blender --background --python neuVid/neuVid/addAnimation.py -- -i ex2.json
blender --background --python neuVid/neuVid/render.py -- -i ex2.json
blender --background --python neuVid/neuVid/assembleFrames.py -- -i ex2.json
If you feel comfortable specifying the mesh sources and segment IDs by hand, as described in the detailed neuVid
documentation, then there is no need to start with neuPrint
or Neuroglancer:
ex3.json
) to specify the sources and animation.Run the last four neuVid
script as above. Remember that blender
is shorthand for the actual platform-specific path to the Blender executable, as described above.
blender --background --python neuVid/neuVid/importMeshes.py -- -i ex3.json
blender --background --python neuVid/neuVid/addAnimation.py -- -i ex3.json
blender --background --python neuVid/neuVid/render.py -- -i ex3.json
blender --background --python neuVid/neuVid/assembleFrames.py -- -i ex3.json
Neuroglancer synapse layers from neuPrint
are imported as described above, but in some cases it is useful to have more control over the details of the synapses. This control is provided by the neuprint-python
module. As mentioned on its project page, neuprint-python
can be installed with either Conda or Pip. Here are the steps:
To use Conda, first install the Miniforge version of Conda.
Create a new Conda environment and install neuprint-python
from the flyem-forge
channel.
conda create --name neuVid-synapses
conda activate neuVid-synapses
conda install -c flyem-forge neuprint-python
Or add neuprint-python
to an existing Conda environment, like neuVid-NG
created above.
The neuprint-python
code requires neuPrint
credentials. In a web browser, visit https://neuprint.janelia.org
and log on. Click on the second button on the top right, and choose the "Account" menu item to show the "Account" page.
Copy the three-or-so-line-long string from the "Auth Token:" section and use it to set the NEUPRINT_APPLICATION_CREDENTIALS
environment variable in the shell where neuVid
is to be run. For a bash
shell, use a command like the following:
export NEUPRINT_APPLICATION_CREDENTIALS="eyJhbGci...xwRYI3dg"
Run the script to query the synapses. This stage creates a directory for the synapse meshes, neuVidSynapseMeshes
, in the same directory as the JSON file. Note that this script runs with python
directly instead of using Blender (which does not know about the neuprint-python
module).
python neuVid/neuVid/buildSynapses.py -i ex4.json
Run the last four neuVid
scripts as above. Remember that blender
is shorthand for the actual platform-specific path to the Blender executable, as described above.
blender --background --python neuVid/neuVid/importMeshes.py -- -i ex4.json
blender --background --python neuVid/neuVid/addAnimation.py -- -i ex4.json
blender --background --python neuVid/neuVid/render.py -- -i ex4.json
blender --background --python neuVid/neuVid/assembleFrames.py -- -i ex4.json
Some projects, such as the Janelia MouseLight project, represent neurons in SWC format. The extra step of converting SWC files to OBJ files is handled automatically by neuVid
.
Create an input JSON file that mentions the SWC files, as in the examples from the detailed documentation.
Run importMeshes.py
as in the other examples. It will create OBJ files (in the neuVidNeuronMeshes
directory, a sibling to the input JSON file) from the SWC files. See the detailed documentation for some options related to the size and resolution of the generated OBJ files.
Use buildSynapses.py
, addAnimation.py
, render.py
, compLabels.py
(described below) and assembleFrames.py
as in the other examples.
Rendering can be performed on a compute cluster, a collection of computers shared between users to meet a facility's needs for high-performance computing (HPC). IBM Spectrum LSF is the HPC platform that neuVid
assumes is available. Rendering on a cluster involves the following steps:
importNg.py
, buildSynapses.py
, importMeshes.py
and addAnimation.py
as in the other examples..json
and .blend
files, the Blender executable, and the directory for the final rendered frames.The neuVid
script for rendering on a cluster is clusterRender.py
, and its arguments are almost identical to those for the standard render.py
script. Say standard rendering would be invoked as follows:
blender --background --python neuVid/neuVid/render.py -- ...
Cluster rendering then would be invoked in this way:
blender --background --python neuVid/neuVid/clusterRender.py -- -P account ...
The new argument, -P account
, specifies the account to be billed for the time on the cluster. Note that this use of the clusterRendering.py
script is synchronous: the script does not finish until the cluster job comes off the "pending" queue and runs to completion.
In some videos, it is helpful to include a small set of arrows in the corner indicating biological directions like anterior, posterior, dorsal, ventral. Such axes can be added by running the compAxes.py
script before assembling the final video with assembleFrames.py
. The compAxes.py
script uses the camera from the Blender file produced by addAnimation.py
so the axes match the camera motion. This approach involves the following steps:
importNg.py
, fetchMeshes.py
, importMeshes.py
, buildSynapses.py
, addAnimation.py
, and render.py
as in the other examples.axes
category as a sibling to neurons
, rois
and synapses
, to specify the arrow's orientations and identifying labels (see the detailed documentation).fade
commands.Composite the axes onto the rendered frames:
blender --background --python neuVid/neuVid/compAxes.py -- -i ex5.json
The resulting frames will be in the directory (folder) ex5-frames-axes
.
axes
category and fade
commands and run only compAxes.py
again. Doing so is much faster than running render.py
.Assemble the final video from these frames:
blender --background --python neuVid/neuVid/assembleFrames.py -- -i ex5-frames-axes
One way to add textual labels and titles is to add them to the finished video with an interactive editing application like iMovie or Premiere. Another way is to describe the labels in neuVid
's input JSON file and use the compLabels.py
script to add the labels before assembling the final video with assembleFrames.py
. The latter approach makes it simpler to keep track of multiple labels, and to coordinate the timing of the labels with the timing of the animation. This approach involves the following steps:
importNg.py
, fetchMeshes.py
, importMeshes.py
, buildSynapses.py
, addAnimation.py
, render.py
, and compAxes.py
as in the other examples.label
commands in the JSON file (see the detailed documentation).Composite the labels onto the rendered frames:
blender --background --python neuVid/neuVid/compLabels.py -- -i ex6.json
The resulting frames will be in the directory (folder) ex6-frames-labeled
. If axes have been added already, add the -if
(--inputFrames
) argument to indicate the directory with the input frames (produced by compAxes.py
):
blender --background --python neuVid/neuVid/compLabels.py -- -i ex6.json -if ex6-frames-axes
The resulting frames will be in the directory ex6-frames-axes-labeled
.
label
commands and run only compLabels.py
again. Doing so is much faster than running render.py
.Assemble the final video from these frames:
blender --background --python neuVid/neuVid/assembleFrames.py -- -i ex6-frames-labeled
Or:
blender --background --python neuVid/neuVid/assembleFrames.py -- -i ex6-frames-axes-labeled
An experimental component of neuVid
takes a description of a video in natural language and translates it to JSON using
generative AI. For now, at least, an Anthropic API key or OpenAI API key is required to use this component. Use the following steps:
The generate
desktop application launches the user interface for entering descriptions and generating JSON. Install generate
by downloading an executable from the releases page of this repository. Chrome on macOS or Windows raises a dialog that incorrectly calls the compressed (.zip) file with the executable "suspicious" or "uncommon". To unblock and complete the donwload, press the right arrow on the dialog, then press the download button that appears. On Windows a "protected your PC" dialog may then appear; press "More info" and then "Run anyway". Safari on macOS and Chrome on Linux do not have these problems. After downloading, extract the executable from the .zip file: double-click on macOS, or right-click on Windows and choose "Extract All" or an item from the "7-Zip" menu, or use the unzip
command on Linux. Move the executable to a standard place, like /Applications
on macOS, or C:\Program Files\newVid
on Windows, or ~/bin
on Linux.
The first time generate
is run, it prompts for the name of the large-language model (LLM) to use. Enter an Anthropic model (e.g., claude-3-opus-20240229
, the best peforming model so far) or an OpenAI model (e.g., gpt-4-0613
, which works better than gpt-4-turbo-preview
for neuVid input). The model name is saved for use in futures sessions, and it can be changed using the "Settings/Model..." menu item.
Then generate
prompts for an API key, from either Anthropic or OpenAI based on the model just chosen. The entered key is saved for future sessions, and can be changed using the "Settings/API Key..." menu item.
Type the description of the video in the lower text area, and press the "Generate" button.
After some processing time (which could be a minute or so for longer descriptions), the generated JSON will appear in the upper text area. Press the "Save..." button to save it to a file for use as input to the other neuVid
scripts.
For more information, see the detailed documentation.
For volumetric data sets lacking a segmentation, use the following approach.
Install VVDViewer. The simplest approach is to download an installer from the releases page.
Install animateVvd
by downloading an executable from the releases page of this repository. It will be a compressed (.zip) file, so extract it on macOS by double-clicking; or extract it on Windows by right-clicking and choosing "Extract All" or an item from the "7-Zip" menu; or extract it on Linux with the unzip
command. Move the executable to a standard place, like /Applications
on macOS, or C:\Program Files\newVid
on Windows, or ~/bin
on Linux.
To get a head start on the animation, animateVvd
can build a basic JSON from a directory of volumes in H5J format, say, exampleVolumes
. In a shell (terminal), run the following, where animateVvd
is shorthand for the actual platform-specific path to the executable (something like /Applications/animateVvd.app/Contents/MacOS/animateVvd
on macOS; or like "C:\Program Files\neuVid\animateVvd.exe"
on Windows, where the quotes are significant since the path contains a space; or like ~/bin/animateVvd.bin
on Linux).
animateVvd -i exampleVolumes
Edit exampleVolumes.json
to add more animation commands. See the detailed documentation.
Use animateVvd
again, to convert exampleVolumes.json
into a project file for VVDViewer, exampleVolumes.vrp
:
animateVvd -i exampleVolumes.json
Run VVDViewer, and press the "Open Project" button at the top to load exampleVolumes.vrp
.
Close all the VVDViewer panels except "Render: View 1" and "Record/Export" to make the rendered view as big as possible (as its size is the size of the final video).
In the "Record/Export" panel, switch to the "Advanced" tab.
Press the "Save..." button to render the video. Do not press the "Play" button and then rewind back to the start before pressing "Save...", as doing so sometimes causes glitches in the saved video.
These scripts come from a collaboration at HHMI's Janelia Research Campus between the FlyEM project and the Scientific Computing Software group.
The first use was for the hemibrain connectome release in January, 2020. Videos made with neuVid
were the winner and second runner up for the 2021 Drosophila Image Award from the Genetics Society of America.
David Ackerman contributed the first version of the code to fetch OpenOrganelle meshes. Marisa Dreher and Frank Loesche helped improve the system's usability.