Fixed bugs in diagram.py and adaptor.py + added coloring of points in show_complex_2D(); Filtration can be initialized from iterator without comparison dev
authorDmitriy Morozov <dmitriy@mrzv.org>
Wed, 06 Jun 2012 23:15:57 -0700
branchdev
changeset 259 84c100980206
parent 258 bb5bc5eff779
child 260 27c47fc33468
Fixed bugs in diagram.py and adaptor.py + added coloring of points in show_complex_2D(); Filtration can be initialized from iterator without comparison
bindings/python/dionysus/adaptor.py
bindings/python/dionysus/circular/__init__.py
bindings/python/dionysus/viewer/complex.py
bindings/python/dionysus/viewer/diagram.py
bindings/python/filtration.cpp
include/topology/filtration.h
--- a/bindings/python/dionysus/adaptor.py	Tue Jun 05 17:53:08 2012 -0700
+++ b/bindings/python/dionysus/adaptor.py	Wed Jun 06 23:15:57 2012 -0700
@@ -83,7 +83,7 @@
         evaluator = lambda s: s.data
 
     if not data:
-        data = lambda s: None
+        data = lambda i: None
 
     dgms = []
     smap = p.make_simplex_map(f)
@@ -96,7 +96,8 @@
 
         b = evaluator(smap[n])
         d = evaluator(smap[n.pair()]) if not n.unpaired() else float('inf')
+        if b == d: continue
 
-        dgms[dim].append((b,d, data(smap[n])))
+        dgms[dim].append((b,d, data(n)))
 
     return dgms
--- a/bindings/python/dionysus/circular/__init__.py	Tue Jun 05 17:53:08 2012 -0700
+++ b/bindings/python/dionysus/circular/__init__.py	Wed Jun 06 23:15:57 2012 -0700
@@ -50,10 +50,12 @@
     if not (sum((D*z_smooth)**2) < tol and sum((D.T*z_smooth)**2) < tol):
         print "Expected a harmonic cocycle:", sum((D*z_smooth)**2), sum((D.T*z_smooth)**2)
 
-    values = {}
+    values = []
     vertices = ((i,s) for (i,s) in enumerate(filtration) if s.dimension() == 0)
     for i,s in vertices:
         v = [v for v in s.vertices][0]
+        if v >= len(values):
+            values.extend((None for i in xrange(len(values), v+1)))
         values[v] = solution[0][i]
 
     return values
--- a/bindings/python/dionysus/viewer/complex.py	Tue Jun 05 17:53:08 2012 -0700
+++ b/bindings/python/dionysus/viewer/complex.py	Wed Jun 06 23:15:57 2012 -0700
@@ -1,11 +1,20 @@
 from    PyQt4       import QtGui, QtCore
+from    dionysus    import Simplex
 
 class ComplexViewer(QtGui.QGraphicsView):
-    def __init__(self, complex, points):
+    def __init__(self, points, complex = None, values = None):
         super(QtGui.QGraphicsView, self).__init__()
 
-        self.complex = [s for s in complex]
         self.points = points
+        if complex:
+            self.complex = [s for s in complex]
+        else:
+            # Create vertex simplices if no complex provided
+            self.complex = [Simplex([i]) for i in xrange(len(self.points))]
+
+        if not values:
+            values = [0]*len(self.points)
+        self.maxval, self.minval = max(values), min(values)
 
         self.setRenderHint(QtGui.QPainter.Antialiasing)
         self.scene = QtGui.QGraphicsScene(self)
@@ -22,18 +31,18 @@
         self.complex.sort(lambda s1, s2: -cmp(s1.dimension(), s2.dimension()))
         for s in self.complex:
             vertices = [v for v in s.vertices]
-            if s.dimension() == 0:
+            if s.dimension() == 0:              # point
                 p = points[vertices[0]]
+                v = values[vertices[0]]
                 item = QtGui.QGraphicsEllipseItem(p[0] - radius/2,p[1] - radius/2,radius,radius)
-                # TODO: vertex colors
-                color = QtCore.Qt.red
+                color = self.colormap(v)
                 item.setBrush(QtGui.QBrush(color))
                 item.setPen(QtGui.QPen(color))
-            elif s.dimension() == 1:
+            elif s.dimension() == 1:            # edge
                 p0 = points[vertices[0]]
                 p1 = points[vertices[1]]
                 item = QtGui.QGraphicsLineItem(p0[0], p0[1], p1[0], p1[1])
-            else:
+            else:                               # higher-d simplex
                 pts = [QtCore.QPointF(points[v][0], points[v][1]) for v in vertices]
                 item = QtGui.QGraphicsPolygonItem(QtGui.QPolygonF(pts))
                 item.setBrush(QtCore.Qt.blue)
@@ -47,10 +56,19 @@
         rect = self.scene.itemsBoundingRect()
         self.fitInView(rect, QtCore.Qt.KeepAspectRatio)
 
+    def colormap(self, v):
+        if self.maxval <= self.minval:
+            t = 0
+        else:
+            t = (v - self.minval)/(self.maxval - self.minval)
+        c = QtGui.QColor()
+        c.setHsv(int(t*255), 255, 255)
+        return c
+
 # TODO: cycle
-def show_complex_2D(complex, points):
+def show_complex_2D(points, complex = None, values = None):
     app = QtGui.QApplication([])
-    view = ComplexViewer(complex, points)
+    view = ComplexViewer(points, complex, values)
     view.show()
     view.raise_()
     app.exec_()
--- a/bindings/python/dionysus/viewer/diagram.py	Tue Jun 05 17:53:08 2012 -0700
+++ b/bindings/python/dionysus/viewer/diagram.py	Wed Jun 06 23:15:57 2012 -0700
@@ -1,14 +1,15 @@
 from    PyQt4       import QtGui, QtCore
 
 class DiagramPoint(QtGui.QGraphicsEllipseItem):
-    def __init__(self,x,y,radius, p, viewer):
-        super(QtGui.QGraphicsEllipseItem, self).__init__(x - radius/2,y - radius/2,radius, radius)
+    def __init__(self,x,y,radius, p):
+        super(QtGui.QGraphicsEllipseItem, self).__init__(x - radius,y - radius,2*radius, 2*radius)
         self.p = p
-        self.viewer = viewer
 
-    def mousePressEvent(self, event):
-        self.viewer.selection = self.p
-        self.viewer.close()
+    # for debugging purposes
+    def color(self):
+        pen = QtGui.QPen()
+        pen.setColor(QtCore.Qt.red)
+        self.setPen(pen)
 
 class DiagramViewer(QtGui.QGraphicsView):
     def __init__(self, dgm):
@@ -20,19 +21,22 @@
         self.scene = QtGui.QGraphicsScene(self)
         self.setScene(self.scene)
 
+        inf = float('inf')
         minx = min(p[0] for p in dgm)
         miny = min(p[1] for p in dgm)
-        maxx = max(p[0] for p in dgm)
-        maxy = max(p[1] for p in dgm)
+        maxx = max(p[0] for p in dgm if p[0] != inf)
+        maxy = max(p[1] for p in dgm if p[1] != inf)
+
+        radius = max(.005, min(maxx - minx, maxy - miny)/200)
+        border = 25
+        self.scene.setSceneRect(minx - border*radius, miny - border*radius, (maxx - minx) + 2*border*radius, (maxy - miny) + 2*border*radius)
 
         self.draw_axes(minx,miny,maxx,maxy)
 
-        radius = min(maxx - minx, maxy - miny)/100
-        self.scene.setSceneRect(minx - 10*radius, miny - 10*radius, (maxx - minx) + 20*radius, (maxy - miny) + 20*radius)
-
         for p in dgm:
             x,y = p[0],p[1]
-            item = DiagramPoint(x,y,radius, p, self)
+            if x == inf or y == inf: continue
+            item = DiagramPoint(x,y,radius, p)
             self.scene.addItem(item)
 
         # Flip y-axis
@@ -42,6 +46,14 @@
         rect = self.scene.itemsBoundingRect()
         self.fitInView(rect, QtCore.Qt.KeepAspectRatio)
 
+    def mousePressEvent(self, event):
+        p = self.mapToScene(event.pos())
+        item = self.scene.itemAt(p)
+        if isinstance(item, DiagramPoint):
+            #item.color()
+            self.selection = item.p
+            self.close()
+
     def draw_axes(self, minx, miny, maxx, maxy):
         # Draw axes and diagonal
         self.scene.addItem(QtGui.QGraphicsLineItem(0,0, maxx, 0))
--- a/bindings/python/filtration.cpp	Tue Jun 05 17:53:08 2012 -0700
+++ b/bindings/python/filtration.cpp	Wed Jun 06 23:15:57 2012 -0700
@@ -11,7 +11,15 @@
 #include "utils.h"           // defines PythonCmp
 namespace dp = dionysus::python;
 
-boost::shared_ptr<dp::PythonFiltration>     init_from_iterator(bp::object iter, bp::object cmp)
+boost::shared_ptr<dp::PythonFiltration>     init_from_iterator(bp::object iter)
+{
+    typedef     dp::PythonFiltration::Simplex   Smplx;
+    boost::shared_ptr<dp::PythonFiltration>     p(new dp::PythonFiltration(bp::stl_input_iterator<Smplx>(iter), 
+                                                                           bp::stl_input_iterator<Smplx>()));
+    return p;
+}
+
+boost::shared_ptr<dp::PythonFiltration>     init_from_iterator_cmp(bp::object iter, bp::object cmp)
 {
     typedef     dp::PythonFiltration::Simplex   Smplx;
     boost::shared_ptr<dp::PythonFiltration>     p(new dp::PythonFiltration(bp::stl_input_iterator<Smplx>(iter), 
@@ -39,6 +47,7 @@
 {
     bp::class_<dp::PythonFiltration>("Filtration")
         .def("__init__",        bp::make_constructor(&init_from_iterator))
+        .def("__init__",        bp::make_constructor(&init_from_iterator_cmp))
 
         .def("append",          &dp::PythonFiltration::push_back)
         .def("sort",            &filtration_sort)
--- a/include/topology/filtration.h	Tue Jun 05 17:53:08 2012 -0700
+++ b/include/topology/filtration.h	Wed Jun 06 23:15:57 2012 -0700
@@ -57,6 +57,11 @@
                                 Filtration()                                    {}
 
         // Constructor: Filtration(bg, end, cmp)
+                                template<class ComplexIndex>
+                                Filtration(ComplexIndex bg, ComplexIndex end):
+                                    container_(bg, end)                         {}
+
+        // Constructor: Filtration(bg, end, cmp)
                                 template<class ComplexIndex, class Comparison>
                                 Filtration(ComplexIndex bg, ComplexIndex end, const Comparison& cmp = Comparison()):
                                     container_(bg, end)                         { sort(cmp); }