FlyRanch / figurefirst

A layout-first approach to figure making
http://flyranch.github.io/figurefirst
MIT License
80 stars 15 forks source link

recursive runtime error (when using template feature) #17

Open florisvb opened 7 years ago

florisvb commented 7 years ago
  1. Create layout with a template containing many axes (say, 7), and a figure referencing that template
  2. Run figurefirst / plot script, save output
  3. Try to open that output as a new layout using figure first > results in a recursive runtime error.

Attached files include a layout which can be opened (layout = figurefirst.svg_to_axes.FigureLayout('figure1_output_test2_works.svg') with figurefirst, and one that is the output from my script, which produces the runtime error (layout = figurefirst.svg_to_axes.FigureLayout('figure1_output_test2.svg'). Deleting the layers added by figurefirst eliminates the runtime error.

Note: change .txt to .svg

figure1_output_test2_works.txt figure1_output_test2.txt

Error:

File "/home/caveman/Documents/src/python/ANALYSIS/lib/python2.7/site-packages/figurefirst/svg_to_axes.py", line 541, in __init__ figuretree,grouptree,leafs,svgitemtree = self.make_group_tree() File "/home/caveman/Documents/src/python/ANALYSIS/lib/python2.7/site-packages/figurefirst/svg_to_axes.py", line 702, in make_group_tree newv = copy.deepcopy(figuretree[l.template_source]) File "/usr/lib/python2.7/copy.py", line 190, in deepcopy y = _reconstruct(x, rv, 1, memo) File "/usr/lib/python2.7/copy.py", line 334, in _reconstruct state = deepcopy(state, memo) File "/usr/lib/python2.7/copy.py", line 163, in deepcopy y = copier(x, memo) File "/usr/lib/python2.7/copy.py", line 257, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) File "/usr/lib/python2.7/copy.py", line 163, in deepcopy y = copier(x, memo)

florisvb commented 7 years ago

problem arises in the deepcopy command (ln 702).

https://docs.python.org/2/library/copy.html

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original. Two problems often exist with deep copy operations that don’t exist with shallow copy operations: Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.

Using a standard (shallow) copy allows the layout to be loaded, and assigns all the correct figure / axis objects, but then produces an error in make_mplfigures().

In [11]: layout.make_mplfigures()

AttributeError Traceback (most recent call last)

in () ----> 1 layout.make_mplfigures() /home/caveman/Documents/src/python/ANALYSIS/lib/python2.7/site-packages/figurefirst/svg_to_axes.pyc in make_mplfigures(self) 815 for figname,figgroup in self.figures.items(): 816 if len(figgroup.keys()): --> 817 leafs = flatten_dict(figgroup) 818 fw_in = tounit(self.layout_width, 'in') 819 fh_in = tounit(self.layout_height, 'in') /home/caveman/Documents/src/python/ANALYSIS/lib/python2.7/site-packages/figurefirst/svg_to_axes.pyc in flatten_dict(d) 91 yield [l for l in traverse(new_keylist,value)] 92 flat_dict = {} ---> 93 fd_list = [fd for fd in flatten_list(list(traverse(keylist,d)))] 94 [flat_dict.update(fd) for fd in flatten_list(list(traverse(keylist,d)))] 95 return flat_dict /home/caveman/Documents/src/python/ANALYSIS/lib/python2.7/site-packages/figurefirst/svg_to_axes.pyc in traverse(kl, d) 89 new_keylist = copy.copy(kl) 90 new_keylist.append(key) ---> 91 yield [l for l in traverse(new_keylist,value)] 92 flat_dict = {} 93 fd_list = [fd for fd in flatten_list(list(traverse(keylist,d)))] /home/caveman/Documents/src/python/ANALYSIS/lib/python2.7/site-packages/figurefirst/svg_to_axes.pyc in traverse(kl, d) 89 new_keylist = copy.copy(kl) 90 new_keylist.append(key) ---> 91 yield [l for l in traverse(new_keylist,value)] 92 flat_dict = {} 93 fd_list = [fd for fd in flatten_list(list(traverse(keylist,d)))] /home/caveman/Documents/src/python/ANALYSIS/lib/python2.7/site-packages/figurefirst/svg_to_axes.pyc in traverse(kl, d) 86 yield {tuple(kl):d} 87 else: ---> 88 for key,value in d.items(): 89 new_keylist = copy.copy(kl) 90 new_keylist.append(key) AttributeError: 'unicode' object has no attribute 'items' In [12]: ax = layout.axes[(u'windypad_template', u'vinegar_60sccm')]
florisvb commented 7 years ago

Possible hacky solution: make it possible to clear the target layers BEFORE make_group_tree is called. This might require saving an intermediate svg file, which is then reloaded?