2
$\begingroup$

Summary

Code which works outside of blender for any sized graph works in Blender for small-sized graphs but causes Blender to crash for moderately and up sized graphs.

detail

I'm trying to write an Addon which lets users manipulate Graph_tool (https://graph-tool.skewed.de/) Graphs in blender. I've been trying to achieve this using Icospheres as vertices and beveled NURMS curves as edges which have constraints on them to get them to stick to one vertex and stretch to another vertex. I've been attempting to save on memory by sharing mesh and curve Datablocks (I think thats the correct word although I am still a noob to blender python scripting).

I've got a basic class working which lets me do this. I've got graphs of around 300 nodes and 400 edges working. It takes about half a second to setup all the icospheres and curves and Blender reports it's using less than 50MB of memory once it's finished. However If I go much bigger than this Blender starts to crash during the execution of the script. I get errors such as terminate called after throwing an instance of 'terminate called recursively or terminate called after throwing an instance of std::bad_allocWriting: /tmp/testing.crash.txt . I've run the code outside of blender and everything seems to work fine (I set bpy to a dummy module), even for much much larger graphs (tens of thousands of nodes, hundreds of thousands of edges). I'm managed to find the line of my script which seems to be causing the issue when I run my script in blender. It works out a layout for the graph and can take quite a long time.

Does anyone have any idea what could be causing this or where to look? Is there any way to memory profile my script as it is run inside blender?

Here's my main class and how I use it:

import bpy
import graph_tool as gt
from graph_tool.draw import sfdp_layout
from graph_tool.generation import lattice

class Graph(gt.Graph):
    def __init__(self,g=None,directed=False,prune=False,vorder=None):
        super().__init__(g,directed,prune,vorder)

        self.pos = None

        self._vertices = Vertices()
        self._edges = Edges()

        self.n = self.num_vertices()

        if g != None:
            self.non_empty_setup()


    def non_empty_setup(self):

        #This is the line blender freaks out on for large graphs:
        self.pos = sfdp_layout(self,C=5)
        #It computes x,y position for each vertex in the graph

        self._vertices.update(self,self.pos)
        self._edges.update(self)

g_ = lattice([200,200]) # an inbuilt graph_tool function to generate a graph of a lattice

g = Graph(g_)

I can post the other helper classes (Vertices and Edges) If that would help.

For reproducibility, I've found the easiest way to install graph_tool for Blender is to sym-link the site-packages directory of Blender's internal python installation to the site-packages directory of a conda python installation of the exact same version and then install graph_tool using https://git.skewed.de/count0/graph-tool/-/wikis/installation-instructions#conda.

Please let me know if you think my strategy of using icospheres and curves is a dumb idea. I'm trying to find the most efficient approach which doesn't look ugly.

Edit

I've realized that my issue can be reproduced by running the following from the text editor:

g = lattice([20,20])
pos = sfdp_layout(g) #  blender crashes here

This occurs even if bpy is not imported. This led me to believe my issue is in fact with how I've set up my python interpreter. I've outlined how I set it up above. Is there a better way? Installing graph-tool is a pain. I've only worked out how to do it using conda.

$\endgroup$

1 Answer 1

0
$\begingroup$

After much messing around I found I was doing two things wrong.

The first was I should have been importing graph tool with from graph_tool.all import graph_tool as gt instead of import graph_tool as gt.

The second problem I was having was not symlinking correctly. Instead of symlinking the whole site-packages I found that only symlinking what I actually needed worked.

I wrote the following bash script which will do all the necessary sym-linking given the name of the blender installation folder(this is so it will work for different versions of blender). You'll have to change the paths specifying where your conda installation is and what folder your blender installation directory is.

#pass it the blender installation directory. You will have to change $Blender_folder_directory to wherever you installed anaconda.
#Also make sure the anaconda environemnt is called blender
condaInstallation=/home/ben
Blender_folder_directory=/home/ben #which directory your blender installation folder is in.
name=$1
version=${name:8:4}

ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/graph_tool $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/scipy $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/cairo $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/matplotlib $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/dateutil $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/mpl_toolkits $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/gi $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages

ln $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/pyparsing.py $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/pyparsing-2.4.7.dist-info $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages

ln $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/cycler.py $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/cycler-0.10.0.dist-info $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages

ln $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/six.py $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/six-1.15.0.dist-info $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages


ln $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/kiwisolver.cpython-37m-x86_64-linux-gnu.so $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
ln -s $condaInstallation/anaconda3/envs/blender/lib/python3.7/site-packages/kiwisolver-1.2.0.dist-info $Blender_folder_directory/$name/$version/python/lib/python3.7/site-packages
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .