4 sys.path.insert (0, 'python')
11 OUTPUT_EXPRESSION_PENALTY = 100
12 ORPHAN_GROB_PENALTY = 1000
14 def max_distance (x1, x2):
17 for (p,q) in zip (x1, x2):
18 dist = max (abs (p-q), dist)
23 empty_interval = (INFTY, -INFTY)
24 empty_bbox = (empty_interval, empty_interval)
26 def interval_length (i):
27 return max (i[1]-i[0], 0)
29 def interval_union (i1, i2):
30 return (min (i1[0], i2[0]),
33 def interval_intersect (i1, i2):
34 return (max (i1[0], i2[0]),
37 def bbox_union (b1, b2):
38 return (interval_union (b1[X_AXIS], b2[X_AXIS]),
39 interval_union (b2[Y_AXIS], b2[Y_AXIS]))
41 def bbox_intersection (b1, b2):
42 return (interval_intersect (b1[X_AXIS], b2[X_AXIS]),
43 interval_intersect (b2[Y_AXIS], b2[Y_AXIS]))
46 return interval_length (b[X_AXIS]) * interval_length (b[Y_AXIS])
48 def bbox_diameter (b):
49 return max (interval_length (b[X_AXIS]),
50 interval_length (b[Y_AXIS]))
53 def difference_area (a, b):
54 return bbox_area (a) - bbox_area (bbox_intersection (a,b))
57 def __init__ (self, exp_list):
58 (self.name, self.origin, bbox_x,
59 bbox_y, self.output_expression) = tuple (exp_list)
61 self.bbox = (bbox_x, bbox_y)
62 self.centroid = (bbox_x[0] + bbox_x[1], bbox_y[0] + bbox_y[1])
65 return '%s: (%.2f,%.2f), (%.2f,%.2f)\n' % (self.name,
71 def axis_centroid (self, axis):
72 return apply (sum, self.bbox[axis]) / 2
74 def centroid_distance (self, other, scale):
75 return max_distance (self.centroid, other.centroid) / scale
77 def bbox_distance (self, other):
78 divisor = bbox_area (self.bbox) + bbox_area (other.bbox)
81 return (difference_area (self.bbox, other.bbox) +
82 difference_area (other.bbox, self.bbox)) / divisor
86 def expression_distance (self, other):
87 if self.output_expression == other.output_expression:
90 return OUTPUT_EXPRESSION_PENALTY
92 def distance(self, other, max_distance):
93 return (self.expression_distance (other)
94 + self.centroid_distance (other, max_distance)
95 + self.bbox_distance (other))
97 class SystemSignature:
98 def __init__ (self, grob_sigs):
101 val = d.setdefault (g.name, [])
105 self.set_all_bbox (grob_sigs)
107 def set_all_bbox (self, grobs):
108 self.bbox = empty_bbox
110 self.bbox = bbox_union (g.bbox, self.bbox)
112 def closest (self, grob_name, centroid):
116 grobs = self.grob_dict[grob_name]
119 d = max_distance (g.centroid, centroid)
130 return reduce (lambda x,y: x+y, self.grob_dict.values(), [])
133 def __init__ (self, system1, system2):
134 self.system1 = system1
135 self.system2 = system2
137 self.link_list_dict = {}
138 self.back_link_dict = {}
140 for g in system1.grobs ():
141 closest = system2.closest (g.name, g.centroid)
143 self.link_list_dict.setdefault (closest, [])
144 self.link_list_dict[closest].append (g)
145 self.back_link_dict[g] = closest
150 scale = max (bbox_diameter (self.system1.bbox),
151 bbox_diameter (self.system2.bbox))
153 for (g1,g2) in self.back_link_dict.items ():
155 d += ORPHAN_GROB_PENALTY
157 d += g1.distance (g2, scale)
159 for (g1,g2s) in self.link_list_dict.items ():
162 d += ORPHAN_GROB_PENALTY
166 def read_signature_file (name):
167 exp_str = ("[%s]" % open (name).read ())
168 entries = safeeval.safe_eval (exp_str)
170 grob_sigs = [GrobSignature (e) for e in entries]
171 sig = SystemSignature (grob_sigs)
177 def compare_directories (dir1, dir2):
182 ################################################################
192 dir = 'output-distance-test'
194 print 'test results in dir'
195 system ('rm -rf ' + dir)
198 ly_template = r"""#(set! toplevel-score-handler print-score-with-defaults)
199 #(set! toplevel-music-handler
201 (if (not (eq? (ly:music-property m 'void) #t))
202 (print-score-with-defaults
203 p (scorify-music m p)))))
205 #(ly:set-option 'point-and-click)
212 c^"%(userstring)s" %(extragrob)s
217 dicts = [{ 'papermod' : '',
220 'userstring': 'test' },
221 { 'papermod' : '#(set-global-staff-size 19.5)',
224 'userstring': 'test' },
228 'userstring': 'blabla' },
232 'userstring': 'test' }]
236 open (d['name'] + '.ly','w').write (ly_template % d)
238 names = [d['name'] for d in dicts]
240 system ('lilypond -ddump-signatures -b eps ' + ' '.join (names))
242 sigs = dict ((n, read_signature_file ('%s-0.signature' % n)) for n in names)
245 for (n1, s1) in sigs.items():
246 for (n2, s2) in sigs.items():
247 combinations['%s-%s' % (n1, n2)] = SystemLink (s1,s2).distance ()
250 results = combinations.items ()
255 assert combinations['20-20'] == 0.0
256 assert combinations['20-20expr'] > 50.0
257 assert combinations['20-19'] < 10.0
261 sa = read_signature_file (a)
262 sb = read_signature_file (b)
263 link = SystemLink (sa, sb)
264 print link.distance()
266 if __name__ == '__main__':
268 test_sigs (sys.argv[1],