/
20110513a.py
262 lines (242 loc) · 9.66 KB
/
20110513a.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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
"""Draw some TikZ figures to illustrate an ad hoc tree topology resolution.
"""
from StringIO import StringIO
import Form
import FormOut
import tikz
import latexutil
g_segment_length = 1.0
g_cross_radius = 0.2
g_figure_label = 'fig:subfloats'
g_figure_caption = """\
This figure illustrates an ad-hoc tree topology resolution,
given that the signs of the entries of the
$v^2$ (Fiedler) eigenvector of $L*$
partition the leaves like $\\{1,2\\},\\{3,4,5\\}$
while the signs of the entries of the
$v^3$ eigenvector of $L*$
partition the leaves like $\\{1,2,3,4\\},\\{5\\}$.
Because the harmonically extended Fiedler vector cuts a single edge
separating leaves 1 and 2 from the rest of the leaves, we know
that the tree topology is like (a).
This cuts the tree into \'thick\' and \'thin\' nodal domains,
each of which is cut exactly once by the zeros of the harmonically
extended $v^3$ vector.
Because the $v^3$ signs of 1 and 2 are the same,
the single $v^3$ cut of the \'thick\' domain
must be again on the edge that separates leaves 1 and 2
from the rest of the leaves.
Subfigures (b), (c), (d), and (e)
represent the four possible tree topologies given that leaves
1 and 2 are separated by a single branch from the remaining leaves.
The 15 dotted lines of (b), (c), (d), and (e) show potential
locations for the second zero of $v^3$,
given that the second zero must be somewhere in the \'thin\' domain.
Two of these 15 potential locations are illustrated by subfigures (f) and (g).
Subfigure (f) shows $v^3$ zeros which induce
a $\\{1,2,3\\},\\{4,5\\}$ sign partition of the leaves,
which is incompatible
with the observed $\\{1,2,3,4\\},\\{5\\}$ $v^3$ partition.
On the other hand subfigure (g) induces the observed sign partition.
Furthermore, (g) represents the only such combination
of a tree topology and a second $v^3$ cut which induces this sign partition.
Therefore we can deduce that its topology is the only
topology compatible with the tree
from which the $v^2$ and $v^3$ were jointly calculated.
So given only the leaf partitions induced by the
signs of the first two nonconstant eigenvectors of $L*$
we are in this case able to deduce the topology of the tree.
In general this is not always possible.\
"""
def get_form():
"""
@return: a list of form objects
"""
# define the form objects
form_objects = [
Form.LatexFormat()]
return form_objects
def get_form_out():
return FormOut.Latex()
def get_tikz_text(tikz_body):
return tikz.get_picture(tikz_body, scale='0.8')
def get_float_figure_lines(subfloat_pictures):
arr = []
for i, picture_text in enumerate(subfloat_pictures):
arr.extend([
'\\subfloat[]{',
'\\label{fig:subfloat-%s}' % i,
picture_text,
'}'])
# add row breaks
if i in (0, 4):
arr.append('\\\\')
return arr
def get_tikz_uncrossed_line(pt, direction):
"""
@param pt: a point
@param direction: a unit vector
@return: some lines of tikz text
"""
ax, ay = pt
dx, dy = direction
bx = ax + g_segment_length * dx
by = ay + g_segment_length * dy
return ['\\draw[color=gray] (%s,%s) -- (%s,%s);' % (ax, ay, bx, by)]
def get_tikz_crossed_line(pt, direction, solid=False):
"""
@param pt: a point
@param direction: a unit vector
@param solid: True if the cross should be solid
@return: some lines of tikz text
"""
ax, ay = pt
dx, dy = direction
bx = ax + g_segment_length * dx
by = ay + g_segment_length * dy
center_x = ax + (g_segment_length / 2.0) * dx
center_y = ay + (g_segment_length / 2.0) * dy
cos_90 = 0
sin_90 = 1
cos_n90 = 0
sin_n90 = -1
qx = center_x + g_cross_radius * (dx*cos_90 - dy*sin_90)
qy = center_y + g_cross_radius * (dx*sin_90 + dy*cos_90)
rx = center_x + g_cross_radius * (dx*cos_n90 - dy*sin_n90)
ry = center_y + g_cross_radius * (dx*sin_n90 + dy*cos_n90)
style = '' if solid else '[densely dotted]'
lines = [
'\n'.join(get_tikz_uncrossed_line(pt, direction)),
'\\draw%s (%s,%s) -- (%s,%s);' % (style, qx, qy, rx, ry)]
return lines
def get_fiedler_tikz_lines():
"""
This should show the Fiedler cut of a tree.
"""
lines = [
'\\node[anchor=south] (1) at (1,1) {1};',
'\\node[anchor=north] (1) at (1,-1) {2};',
'\\node[anchor=west] (x) at (2.4,0) {$\\{3,4,5\\}$};',
'\\draw[color=gray] (1,1) -- (1,0);',
'\\draw[color=gray] (1,0) -- (1,-1);',
'\\draw[color=gray] (1,0) -- (2,0);',
'\\draw[color=gray] (2,0) -- (2.4,0.4);',
'\\draw[color=gray] (2,0) -- (2.4,-0.4);',
'\\draw[color=gray] (2.4,0.4) -- (2.4,-0.4);',
'\\draw (1.5,0.2) -- (1.5,-0.2);']
return lines
def get_preamble_lines():
"""
@return: some tikz lines common to several tikz figures
"""
preamble = [
'\\node[anchor=south] (1) at (1,1) {1};',
'\\node[anchor=north] (2) at (1,-1) {2};',
'\\draw[line width=0.1cm,color=gray] (1,1) -- (1,-1);',
'\\draw[line width=0.1cm,color=gray] (1,0) -- (1.5,0);',
'\\draw[color=gray] (1.5,0) -- (2,0);',
'\\draw (1.2,0.2) -- (1.2,-0.2);']
return preamble
def get_t1_tikz_lines():
preamble = get_preamble_lines()
extra_labels = [
'\\node[anchor=north] (3) at (2,-1) {3};',
'\\node[anchor=north] (4) at (3,-1) {4};',
'\\node[anchor=south] (5) at (3,1) {5};']
crossed_lines = []
crossed_lines.extend(get_tikz_crossed_line((2,0), (0,-1)))
crossed_lines.extend(get_tikz_crossed_line((2,0), (1,0)))
crossed_lines.extend(get_tikz_crossed_line((3,0), (0,-1)))
crossed_lines.extend(get_tikz_crossed_line((3,0), (0,1)))
return preamble + extra_labels + crossed_lines
def get_t2_tikz_lines():
preamble = get_preamble_lines()
extra_labels = [
'\\node[anchor=north] (4) at (2,-1) {4};',
'\\node[anchor=north] (3) at (3,-1) {3};',
'\\node[anchor=south] (5) at (3,1) {5};']
crossed_lines = []
crossed_lines.extend(get_tikz_crossed_line((2,0), (0,-1)))
crossed_lines.extend(get_tikz_crossed_line((2,0), (1,0)))
crossed_lines.extend(get_tikz_crossed_line((3,0), (0,-1)))
crossed_lines.extend(get_tikz_crossed_line((3,0), (0,1)))
return preamble + extra_labels + crossed_lines
def get_t3_tikz_lines():
preamble = get_preamble_lines()
extra_labels = [
'\\node[anchor=north] (5) at (2,-1) {5};',
'\\node[anchor=north] (3) at (3,-1) {3};',
'\\node[anchor=south] (4) at (3,1) {4};']
crossed_lines = []
crossed_lines.extend(get_tikz_crossed_line((2,0), (0,-1)))
crossed_lines.extend(get_tikz_crossed_line((2,0), (1,0)))
crossed_lines.extend(get_tikz_crossed_line((3,0), (0,-1)))
crossed_lines.extend(get_tikz_crossed_line((3,0), (0,1)))
return preamble + extra_labels + crossed_lines
def get_t4_tikz_lines():
preamble = get_preamble_lines()
extra_labels = [
'\\node[anchor=north] (5) at (2,-1) {5};',
'\\node[anchor=west] (4) at (3,0) {4};',
'\\node[anchor=south] (3) at (2,1) {3};']
crossed_lines = []
crossed_lines.extend(get_tikz_crossed_line((2,0), (0,-1)))
crossed_lines.extend(get_tikz_crossed_line((2,0), (1,0)))
crossed_lines.extend(get_tikz_crossed_line((2,0), (0,1)))
return preamble + extra_labels + crossed_lines
def get_fail_tikz_lines():
"""
This is an example of a crossing that fails.
It shows a single failing cut of t1.
"""
preamble = get_preamble_lines()
extra_labels = [
'\\node[anchor=north] (3) at (2,-1) {3};',
'\\node[anchor=north] (4) at (3,-1) {4};',
'\\node[anchor=south] (5) at (3,1) {5};']
lines = []
lines.extend(get_tikz_crossed_line((2,0), (0,-1), True))
lines.extend(get_tikz_uncrossed_line((2,0), (1,0)))
lines.extend(get_tikz_uncrossed_line((3,0), (0,-1)))
lines.extend(get_tikz_uncrossed_line((3,0), (0,1)))
return preamble + extra_labels + lines
def get_success_tikz_lines():
"""
This is an example of a crossing that succeeds.
It shows a single successful cut of t3.
"""
preamble = get_preamble_lines()
extra_labels = [
'\\node[anchor=north] (5) at (2,-1) {5};',
'\\node[anchor=north] (3) at (3,-1) {3};',
'\\node[anchor=south] (4) at (3,1) {4};']
lines = []
lines.extend(get_tikz_uncrossed_line((2,0), (0,-1)))
lines.extend(get_tikz_crossed_line((2,0), (1,0), True))
lines.extend(get_tikz_uncrossed_line((3,0), (0,-1)))
lines.extend(get_tikz_uncrossed_line((3,0), (0,1)))
return preamble + extra_labels + lines
def get_response_content(fs):
"""
@param fs: a FieldStorage object containing the cgi arguments
@return: the response
"""
# get the texts
tikz_fiedler = get_tikz_text('\n'.join(get_fiedler_tikz_lines()))
tikz_t1 = get_tikz_text('\n'.join(get_t1_tikz_lines()))
tikz_t2 = get_tikz_text('\n'.join(get_t2_tikz_lines()))
tikz_t3 = get_tikz_text('\n'.join(get_t3_tikz_lines()))
tikz_t4 = get_tikz_text('\n'.join(get_t4_tikz_lines()))
tikz_fail = get_tikz_text('\n'.join(get_fail_tikz_lines()))
tikz_success = get_tikz_text('\n'.join(get_success_tikz_lines()))
subfloat_pictures = [
tikz_fiedler,
tikz_t1, tikz_t2, tikz_t3, tikz_t4,
tikz_fail, tikz_success]
# return the response
figure_body = '\n'.join(get_float_figure_lines(subfloat_pictures))
packages = ('tikz', 'subfig')
preamble = ''
return latexutil.get_centered_figure_response(
figure_body, fs.latexformat, g_figure_caption, g_figure_label,
packages, preamble)