| dmitriy@146 | 1 | #!/usr/bin/env python |
| dmitriy@146 | 2 | |
| dmitriy@181 | 3 | from dionysus import Simplex, CohomologyPersistence, points_file, PairwiseDistances, ExplicitDistances, Rips, data_dim_cmp |
| dmitriy@146 | 4 | from sys import argv, exit |
| dmitriy@146 | 5 | import time |
| dmitriy@146 | 6 | |
| dmitriy@146 | 7 | def main(filename, skeleton, max, prime = 11): |
| dmitriy@146 | 8 | points = [p for p in points_file(filename)] |
| dmitriy@146 | 9 | print '#', time.asctime(), "Points read" |
| dmitriy@146 | 10 | distances = PairwiseDistances(points) |
| dmitriy@146 | 11 | distances = ExplicitDistances(distances) # speeds up generation of the Rips complex at the expense of memory usage |
| dmitriy@146 | 12 | rips = Rips(distances) |
| dmitriy@146 | 13 | print '#', time.asctime(), "Rips initialized" |
| dmitriy@146 | 14 | |
| dmitriy@146 | 15 | simplices = [] |
| dmitriy@146 | 16 | rips.generate(skeleton, max, simplices.append) |
| dmitriy@146 | 17 | print '#', time.asctime(), "Generated complex: %d simplices" % len(simplices) |
| dmitriy@146 | 18 | |
| dmitriy@146 | 19 | # While this step is unnecessary (Filtration below can be passed rips.cmp), |
| dmitriy@146 | 20 | # it greatly speeds up the running times |
| dmitriy@146 | 21 | for s in simplices: s.data = rips.eval(s) |
| dmitriy@173 | 22 | print '#', time.asctime(), simplices[0], '...', simplices[-1] |
| dmitriy@146 | 23 | |
| dmitriy@146 | 24 | simplices.sort(data_dim_cmp) |
| dmitriy@146 | 25 | print '#', time.asctime(), "Simplices sorted" |
| dmitriy@146 | 26 | |
| dmitriy@146 | 27 | ch = CohomologyPersistence(prime) |
| dmitriy@146 | 28 | complex = {} |
| dmitriy@146 | 29 | |
| dmitriy@146 | 30 | for s in simplices: |
| dmitriy@173 | 31 | i,d = ch.add([complex[sb] for sb in s.boundary], (s.dimension(), s.data), store = (s.dimension() < skeleton)) |
| dmitriy@146 | 32 | complex[s] = i |
| dmitriy@146 | 33 | if d: |
| dmitriy@146 | 34 | dimension, birth = d |
| dmitriy@146 | 35 | print dimension, birth, s.data |
| dmitriy@146 | 36 | # else birth |
| dmitriy@146 | 37 | |
| dmitriy@146 | 38 | for ccl in ch: |
| dmitriy@146 | 39 | dimension, birth = ccl.birth |
| dmitriy@146 | 40 | if dimension >= skeleton: continue |
| dmitriy@146 | 41 | print dimension, birth, 'inf' # dimension, simplex data = birth |
| dmitriy@146 | 42 | print "# Cocycle at (dim=%d, birth=%f)" % ccl.birth |
| dmitriy@146 | 43 | for e in ccl: |
| dmitriy@159 | 44 | print "# ", e.si.order, normalized(e.coefficient, prime) |
| dmitriy@146 | 45 | |
| dmitriy@146 | 46 | def normalized(coefficient, prime): |
| dmitriy@146 | 47 | if coefficient > prime/2: |
| dmitriy@146 | 48 | return coefficient - prime |
| dmitriy@146 | 49 | return coefficient |
| dmitriy@146 | 50 | |
| dmitriy@146 | 51 | if __name__ == '__main__': |
| dmitriy@146 | 52 | if len(argv) < 4: |
| dmitriy@146 | 53 | print "Usage: %s POINTS SKELETON MAX [PRIME=11]" % argv[0] |
| dmitriy@146 | 54 | exit() |
| dmitriy@146 | 55 | |
| dmitriy@146 | 56 | filename = argv[1] |
| dmitriy@146 | 57 | skeleton = int(argv[2]) |
| dmitriy@146 | 58 | max = float(argv[3]) |
| dmitriy@146 | 59 | prime = (len(argv) > 4 and argv[4]) or 11 |
| dmitriy@146 | 60 | |
| dmitriy@146 | 61 | main(filename, skeleton, max, prime) |