-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanalysis.py
240 lines (188 loc) · 7.72 KB
/
analysis.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
import numpy as n
import json
from pyknotid.spacecurves import Knot
from pyknotid.make.torus import torus_knot
from cache import CachedGaussCode, db
def text_to_json(text):
points = []
for line in text.split('\n'):
values = line.split(' ')
if len(values) == 1 and len(values[0]) == 0:
continue
if len(values) != 3:
raise ValueError('Invalid text passed.')
points.append([float(v) for v in values])
k = Knot(points, verbose=False)
return knot_to_json(k)
def knot_to_json(k):
k.rotate(n.array([0.001, 0.002, 0.0015]))
k.zero_centroid()
max_extent = n.max(n.max(n.abs(k.points), axis=0))
analysis = representation_to_json(k.representation())
analysis['num_points'] = len(k.points)
return (json.dumps(k.points.tolist()), 2.5*max_extent, analysis)
def gauss_code_to_json(gc):
from pyknotid.representations.representation import Representation
if len(gc) > 5000:
return(True, 'Gauss code too long')
if 'c' in gc or 'a' in gc:
try:
representation = Representation(str(gc))
except:
import traceback
traceback.print_exc()
return (True, 'Gauss code could not be parsed')
else:
try:
representation = Representation.calculating_orientations(str(gc))
except:
import traceback
traceback.print_exc()
return (True, 'Gauss code could not be parsed')
try:
result = representation_to_json(representation)
except:
import traceback
traceback.print_exc()
return (True, 'Something went wrong during parsing or analysis')
return (False, result)
def dt_code_to_json(dt):
from pyknotid.representations.dtnotation import DTNotation
if len(dt) > 2000:
return(True, 'DT code too long')
try:
dt = DTNotation(str(dt))
representation = dt.representation()
except:
import traceback
traceback.print_exc()
return (True, 'Something went wrong during parsing or analysis')
return (False, representation_to_json(representation))
def cached_from_gauss_code(gc):
'''
Takes a Gauss code as a string, checks if it is in the cache
database, and returns it if so.
'''
db.connect()
cached = CachedGaussCode.select().where(CachedGaussCode.gauss_code == gc)
first = cached.first() # this may be None
if first is not None:
first.num_times_accessed = first.num_times_accessed + 1
first.save()
db.close()
return first
def representation_to_json(rep):
gc_string = str(rep)
gc_length = len(rep)
analysis = {'gauss_code': gc_string,
'num_crossings': gc_length}
if gc_length > 5000:
analysis['error'] = ('Gauss code initial length too long for'
'further analysis. Found '
'{} crossings, max is {}'.format(
gc_length, 5000))
return analysis
is_virtual = rep.is_virtual()
self_linking = rep.self_linking()
if is_virtual:
return {'is_virtual': is_virtual,
'self_linking': self_linking}
rep.simplify()
simplified_gc_string = str(rep)
simplified_gc_length = len(rep)
analysis['simplified_gauss_code'] = simplified_gc_string
analysis['reduced_num_crossings'] = simplified_gc_length
if simplified_gc_length > 3000:
analysis['error'] = ('Gauss code reduced length is too large. '
'Reduced to {} crossings, but max for further '
'analysis is {}'.format(simplified_gc_length))
return analysis
from pyknotid.catalogue.database import Knot
cached = cached_from_gauss_code(simplified_gc_string)
if cached is not None:
return analysis_from_cache(cached, gc_string, gc_length)
identification = [
(knot.identifier,
identifier_to_latex(knot.identifier)) for knot in rep.identify()]
identification_perfect = len(rep) < 14
analysis.update({'identification': identification,
'identification_perfect': identification_perfect,
'reduced_num_crossings': simplified_gc_length,
'simplified_gauss_code': simplified_gc_string,
'alex_roots': rep.alexander_at_root((2, 3, 4),
force_no_simplify=True),
# 'hyp_vol': str(k.hyperbolic_volume()),
'vassiliev_degree_2': rep.vassiliev_degree_2(False),
})
if len(rep) < 20:
analysis['vassiliev_degree_3'] = rep.vassiliev_degree_3(False)
# try:
# gc = k.gauss_code()
# if len(gc) < 100:
# extra_stuff['alexander'] = str(
# k.alexander_polynomial(mode='cypari')).replace('*', '')
# print(extra_stuff['alexander'])
# except ValueError, RuntimeError:
# print('ValueError in alexander calculation, only a problem '
# 'if running in debug mode.')
cache_from_analysis(analysis)
return analysis
def analysis_from_cache(cache, gauss_code, num_crossings):
analysis = {'gauss_code': gauss_code,
'num_crossings': num_crossings}
analysis['simplified_gauss_code'] = cache.gauss_code
analysis['reduced_num_crossings'] = cache.num_crossings
if cache.alexander is not None:
analysis['alexander'] = cache.alexander
if cache.determinant is not None:
analysis['alex_roots'] = (cache.determinant,
cache.alex_imag_3,
cache.alex_imag_4)
if cache.vassiliev_degree_2 is not None:
analysis['vassiliev_degree_2'] = cache.vassiliev_degree_2
if cache.vassiliev_degree_3 is not None:
analysis['vassiliev_degree_3'] = cache.vassiliev_degree_3
if cache.identification is not None:
identification = json.loads(cache.identification)
analysis['identification'] = identification
else:
analysis['identification'] = []
if cache.identification_perfect is not None:
analysis['identification_perfect'] = cache.identification_perfect
else:
analysis['identification_perfect'] = False
analysis['cached'] = True
analysis['num_times_accessed'] = cache.num_times_accessed
return analysis
def cache_from_analysis(analysis):
db.connect()
cache = CachedGaussCode(gauss_code=analysis['simplified_gauss_code'])
if 'reduced_num_crossings' in analysis:
cache.num_crossings = analysis['reduced_num_crossings']
if 'alexander' in analysis:
cache.alexander = analysis['alexander']
if 'hyp_vol' in analysis:
cache.alexander = str(analysis['hyp_vol'])
if 'alex_roots' in analysis:
roots = analysis['alex_roots']
cache.determinant = roots[0]
cache.alex_imag_3 = roots[1]
cache.alex_imag_4 = roots[2]
if 'vassiliev_degree_2' in analysis:
cache.vassiliev_degree_2 = analysis['vassiliev_degree_2']
if 'vassiliev_degree_3' in analysis:
cache.vassiliev_degree_3 = analysis['vassiliev_degree_3']
if 'identification' in analysis:
cache.identification = json.dumps(analysis['identification'])
if 'identification_perfect' in analysis:
cache.identification_perfect = analysis['identification_perfect']
cache.save()
db.close()
def torus_knot_to_json(p, q):
k = torus_knot(p, q, 300)
k.points *= 10
return knot_to_json(k)
def identifier_to_latex(i):
if '_' in i:
return ''.join([i.replace('_', '_{'), '}'])
return i