sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.39k stars 472 forks source link

Tachyon fails on empty graphics objects #10442

Open vbraun opened 13 years ago

vbraun commented 13 years ago

I get the following error when trying to plot 3d cones with the taychon raytracer (which is the default for 3d plots in SageTeX):

sage: c = Cone(identity_matrix(3).columns())
sage: c.rays()
(N(0, 0, 1), N(0, 1, 0), N(1, 0, 0))
sage: c.plot(viewer='tachyon')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/vbraun/opt/sage-4.6/<ipython console> in <module>()

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/IPython/Prompts.pyc in __call__(self, arg)
    549 
    550             # and now call a possibly user-defined print mechanism
--> 551             manipulated_val = self.display(arg)
    552             
    553             # user display hooks can change the variable to be stored in

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/IPython/Prompts.pyc in _display(self, arg)
    575             return IPython.generics.result_display(arg)
    576         except TryNext:            
--> 577             return self.shell.hooks.result_display(arg)
    578 
    579     # Assign the default display method:

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/IPython/hooks.pyc in __call__(self, *args, **kw)
    139             #print "prio",prio,"cmd",cmd #dbg
    140             try:
--> 141                 ret = cmd(*args, **kw)
    142                 return ret
    143             except ipapi.TryNext, exc:

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/misc/displayhook.pyc in result_display(ip_self, obj)
    148     # IPython's default result_display() uses the IPython.genutils.Term.cout stream.
    149     # See also local/lib/python2.6/site-packages/IPython/hooks.py.
--> 150     print_obj(IPython.genutils.Term.cout, obj)
    151 
    152 def displayhook(obj):

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/misc/displayhook.pyc in print_obj(out_stream, obj)
    140             if _check_tall_list_and_print(out_stream, obj):
    141                 return
--> 142     print >>out_stream, `obj`
    143 
    144 def result_display(ip_self, obj):

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/plot/plot3d/base.so in sage.plot.plot3d.base.Graphics3d.__repr__ (sage/plot/plot3d/base.c:2451)()

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/plot/plot3d/base.so in sage.plot.plot3d.base.Graphics3d.show (sage/plot/plot3d/base.c:9832)()

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/plot/plot3d/base.so in sage.plot.plot3d.base.Graphics3d.tachyon (sage/plot/plot3d/base.c:4741)()

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/plot/plot3d/base.so in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13136)()

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/plot/plot3d/base.so in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13136)()

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/plot/plot3d/base.so in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13136)()

/home/vbraun/Sage/sage/local/lib/python2.6/site-packages/sage/plot/plot3d/base.so in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13152)()

TypeError: reduce() of empty sequence with no initial value

Somewhat puzzling, the following work fine:

sage: c.plot(viewer='jmol')
sage: Fan([c]).plot(viewer='jmol')
sage: Fan([c]).plot(viewer='tachyon')

so its the combination of a Cone (not a Fan) with tachyon that causes this.

CC: @novoselt @nilesjohnson

Component: graphics

Issue created by migration from https://trac.sagemath.org/ticket/10442

novoselt commented 13 years ago
comment:1

This is sad, but I have no idea why this is happening and would claim that this is an error related to general tachyon code, since jmol plots work fine and look exactly the same, as they should.

Tachyon also handles alpha on a totally different scale, our default 0.4 looks awful (but works great in both jmol and matplotlib with similar effect).

novoselt commented 13 years ago
comment:2

I think this is the issue:

sage: (point([0,1,1])).show(viewer='tachyon')

works, while

sage: (point([0,1,1]) + Graphics()).show(viewer='tachyon')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "_sage_input_55.py", line 10, in <module>
    exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("KHBvaW50KFswLDEsMV0pICsgR3JhcGhpY3MoKSkuc2hvdyh2aWV3ZXI9J3RhY2h5b24nKQ=="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))
  File "", line 1, in <module>

  File "/tmp/tmpEJzM5T/___code___.py", line 3, in <module>
    exec compile(u"(point([_sage_const_0 ,_sage_const_1 ,_sage_const_1 ]) + Graphics()).show(viewer='tachyon')" + '\n', '', 'single')
  File "", line 1, in <module>

  File "base.pyx", line 1081, in sage.plot.plot3d.base.Graphics3d.show (sage/plot/plot3d/base.c:9834)
  File "base.pyx", line 524, in sage.plot.plot3d.base.Graphics3d.tachyon (sage/plot/plot3d/base.c:4743)
  File "base.pyx", line 1410, in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13141)
  File "base.pyx", line 1410, in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13141)
  File "base.pyx", line 1410, in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13141)
  File "base.pyx", line 1410, in sage.plot.plot3d.base.Graphics3dGroup.texture_set (sage/plot/plot3d/base.c:13157)
TypeError: reduce() of empty sequence with no initial value

In cones plotting of labels and rays was separated for the sake of non-strictly convex cones (I assume that you have that patch applied, since in plain sage-4.6 there are no problems, unless you add, say, ray_label=None option). It may lead to addition of an empty graphics object to the final plot. I do NOT consider it a bug of cones as I think that empty plots are exactly what should be returned by plotting functions if there is nothing to plot and viewers should handle it correctly, as jmol and matplotlib do:

sage: (point([0,1,1]) + Graphics()).show(viewer='jmol')
sage: (point([0,1]) + Graphics()).show()
sage: (Graphics()).show()

All of these work as expected.

07773d35-e75e-45c9-9ddb-1ae443bbe8fe commented 10 years ago
comment:4

This looks to me like an easy fix.

In 6.1.1, the Graphics3dGroup.texture_set() method is defined by line sage/plot/plot3d/base.pyx:1501:

return reduce(set.union, [g.texture_set() for g in self.all])

It chokes on empty graphics because reduce() chokes on an empty list. Adding an initializer resolves the issue:

return reduce(set.union, [g.texture_set() for g in self.all], set())

Being in a hurry at the moment, I just used an external workaround:

    def texture_set(g):
        try:
            return g.texture_set()
        except TypeError:
            return reduce(set.union, [texture_set(gi) for gi in g.all], set())