Fixed bugs in diagram.py and adaptor.py + added coloring of points in show_complex_2D(); Filtration can be initialized from iterator without comparison
--- 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); }