]> git.donarmstrong.com Git - lilypond.git/blobdiff - buildscripts/output-distance.py
Fix some bugs in the dynamic engraver and PostScript backend
[lilypond.git] / buildscripts / output-distance.py
index c534d8cb2b8bba1b03ba31e5ec104276cae0c37e..a19380f1f28b4c9cfbd4aad84749d89e3c733954 100644 (file)
@@ -1,9 +1,10 @@
 #!@TARGET_PYTHON@
 import sys
+import optparse
 
-sys.path.insert (0, 'python')
 import safeeval
 
+
 X_AXIS = 0
 Y_AXIS = 1
 INFTY = 1e6
@@ -158,12 +159,19 @@ class SystemLink:
 
         for (g1,g2s) in self.link_list_dict.items ():
             if len (g2s) != 1:
-                print g1, g2s 
                 d += ORPHAN_GROB_PENALTY
 
         return d
-        
+
+################################################################
+# Files/directories
+
+import glob
+import shutil
+import re
+
 def read_signature_file (name):
+    print 'reading', name
     exp_str = ("[%s]" % open (name).read ())
     entries = safeeval.safe_eval (exp_str)
 
@@ -172,29 +180,200 @@ def read_signature_file (name):
     return sig
 
 
+def compare_signature_files (f1, f2):
+    s1 = read_signature_file (f1)
+    s2 = read_signature_file (f2)
+    
+    return SystemLink (s1, s2).distance ()
+
+def paired_files (dir1, dir2, pattern):
+    """
+    Search DIR1 and DIR2 for PATTERN.
+
+    Return (PAIRED, MISSING-FROM-2, MISSING-FROM-1)
+
+    """
+    
+    files1 = dict ((os.path.split (f)[1], 1) for f in glob.glob (dir1 + '/' + pattern))
+    files2 = dict ((os.path.split (f)[1], 1) for f in glob.glob (dir2 + '/' + pattern))
+
+    pairs = []
+    missing = []
+    for f in files1.keys ():
+        try:
+            files2.pop (f)
+            pairs.append (f)
+        except KeyError:
+            missing.append (f)
+
+    return (pairs, files2.keys (), missing)
+    
+class ComparisonData:
+    def __init__ (self):
+        self.result_dict = {}
+        self.missing = []
+        self.added = []
+        
+    def compare_trees (self, dir1, dir2):
+        self.compare_directories (dir1, dir2)
+        
+        (root, files, dirs) = os.walk (dir1).next ()
+        for d in dirs:
+            d1 = os.path.join (dir1, d)
+            d2 = os.path.join (dir2, d)
+            
+            if os.path.isdir (d2):
+                self.compare_trees (d1, d2)
+    
+    def compare_directories (self, dir1, dir2):
+        
+        (paired, m1, m2) = paired_files (dir1, dir2, '*.signature')
+
+        self.missing += [(dir1, m) for m in m1] 
+        self.added += [(dir2, m) for m in m2] 
 
+        for p in paired:
+            f2 = dir2 +  '/' + p
+            f1 = dir1 +  '/' + p
+            distance = compare_signature_files (f1, f2)
+            self.result_dict[f2] = (distance, f1)
+    
+    def create_text_result_page (self, dir1, dir2):
+        self.write_text_result_page (dir2 + '/' + os.path.split (dir1)[1] + '.txt')
+        
+    def write_text_result_page (self, filename):
+        print 'writing "%s"' % filename
+        out = None
+        if filename == '':
+            out = sys.stdout
+        else:
+            out = open (filename, 'w')
+        
+        results = [(score, oldfile, file) for (file, (score, oldfile)) in self.result_dict.items ()]  
+        results.sort ()
+        results.reverse ()
 
-def compare_directories (dir1, dir2):
+        for (s, oldfile, f) in results:
+            out.write ('%-30f %-20s\n' % (s, f))
 
-    pass
+        for (dir, file) in self.missing:
+            out.write ('%10s%-20s %s\n' % ('', 'missing',os.path.join (dir, file)))
+        for (dir, file) in self.added:
+            out.write ('%20s%-10s %s\n' % ('','added', os.path.join (dir, file)))
 
+    def print_results (self):
+        self.write_text_result_page ('')
+        
+    def create_html_result_page (self, dir1, dir2):
+        dir1 = dir1.replace ('//', '/')
+        dir2 = dir2.replace ('//', '/')
+        
+        threshold = 1.0
+        
+        results = [(score, oldfile, file) for (file, (score, oldfile)) in self.result_dict.items ()
+                   if score > threshold]
+
+        results.sort ()
+        results.reverse ()
+
+        html = ''
+        old_prefix = os.path.split (dir1)[1]
+        os.mkdir (dir2 + '/' + old_prefix)
+        for (score, oldfile, newfile) in  results:
+            old_base = re.sub ("-[0-9]+.signature", '', os.path.split (oldfile)[1])
+            new_base = re.sub ("-[0-9]+.signature", '', newfile)
+            
+            for ext in 'png', 'ly':
+                shutil.copy2 (old_base + '.' + ext, dir2 + '/' + old_prefix)
+
+            img_1 = os.path.join (old_prefix, old_base + '.png')
+            ly_1 = os.path.join (old_prefix, old_base + '.ly')
+
+            img_2 = new_base.replace (dir2, '') + '.png'
+            img_2 = re.sub ("^/*", '', img_2)
+
+            ly_2 = img_2.replace ('.png','.ly')
+
+            def img_cell (ly, img):
+                return '''
+<td align="center">
+<a href="%(img)s">
+<img src="%(img)s" style="border-style: none; max-width: 500px;">
+</a><br>
+<font size="-2">(<a href="%(ly)s">source</a>)
+</font>
+</td>
+''' % locals ()
+            
+            html_entry = '''
+<tr>
+<td>
+%f
+</td>
+
+%s
+%s
+</tr>
+''' % (score, img_cell (ly_1, img_1), img_cell (ly_2, img_2))
+
+
+            html += html_entry
+
+        html = '''<html>
+<table>
+<tr>
+<th>distance</th>
+<th>old</th>
+<th>new</th>
+</tr>
+%(html)s
+</table>
+</html>''' % locals()
+            
+        open (os.path.join (dir2, old_prefix) + '.html', 'w').write (html)
+        
+        
 
+def compare_trees (dir1, dir2):
+    data =  ComparisonData ()
+    data.compare_trees (dir1, dir2)
+    data.print_results ()
+    data.create_html_result_page (dir1, dir2)
+    data.create_text_result_page (dir1, dir2)
+    
 ################################################################
 # TESTING
 
-def test ():
-    def system (x):
-        print 'invoking', x
-        stat = os.system (x)
-        assert stat == 0
-        
-    import os
-    dir = 'output-distance-test'
+import os
+def system (x):
+    
+    print 'invoking', x
+    stat = os.system (x)
+    assert stat == 0
 
-    print 'test results in dir'
-    system ('rm -rf ' + dir)
-    os.mkdir (dir)
-    os.chdir (dir)
+
+def test_paired_files ():
+    print paired_files (os.environ["HOME"] + "/src/lilypond/scripts/",
+                        os.environ["HOME"] + "/src/lilypond-stable/buildscripts/", '*.py')
+                  
+    
+def test_compare_trees ():
+    system ('rm -rf dir1 dir2')
+    system ('mkdir dir1 dir2')
+    system ('cp 20{-0.signature,.ly,.png} dir1')
+    system ('cp 20{-0.signature,.ly,.png} dir2')
+    system ('cp 20expr{-0.signature,.ly,.png} dir1')
+    system ('cp 19{-0.signature,.ly,.png} dir2/')
+    system ('cp 19{-0.signature,.ly,.png} dir1/')
+    system ('cp 20grob{-0.signature,.ly,.png} dir2/')
+
+    ## introduce difference
+    system ('cp 19-0.signature dir2/20-0.signature')
+
+    compare_trees ('dir1', 'dir2')
+
+
+def test_basic_compare ():
     ly_template = r"""#(set! toplevel-score-handler print-score-with-defaults)
 #(set! toplevel-music-handler
  (lambda (p m)
@@ -202,10 +381,6 @@ def test ():
     (print-score-with-defaults
     p (scorify-music m p)))))
 
-#(ly:set-option 'point-and-click)
-
-
-
 %(papermod)s
 
 \relative c {
@@ -213,7 +388,6 @@ def test ():
   }
 """
 
-
     dicts = [{ 'papermod' : '',
                'name' : '20',
                'extragrob': '',
@@ -231,23 +405,20 @@ def test ():
                'extragrob': 'c4',
                'userstring': 'test' }]
 
-
     for d in dicts:
         open (d['name'] + '.ly','w').write (ly_template % d)
         
     names = [d['name'] for d in dicts]
     
-    system ('lilypond -ddump-signatures -b eps ' + ' '.join (names))
+    system ('lilypond -ddump-signatures --png -b eps ' + ' '.join (names))
     
     sigs = dict ((n, read_signature_file ('%s-0.signature' % n)) for n in names)
-
     combinations = {}
     for (n1, s1) in sigs.items():
         for (n2, s2) in sigs.items():
             combinations['%s-%s' % (n1, n2)] = SystemLink (s1,s2).distance ()
-            
 
-    results =   combinations.items ()
+    results = combinations.items ()
     results.sort ()
     for k,v in results:
         print '%-20s' % k, v
@@ -263,11 +434,45 @@ def test_sigs (a,b):
     link = SystemLink (sa, sb)
     print link.distance()
 
-if __name__ == '__main__':
-    if sys.argv[1:]:
-        test_sigs (sys.argv[1],
-                    sys.argv[2])
-    else:
-        test ()
 
+def run_tests ():
+    do_clean = 1
+    dir = 'output-distance-test'
+
+    print 'test results in ', dir
+    if do_clean:
+        system ('rm -rf ' + dir)
+        system ('mkdir ' + dir)
+        
+    os.chdir (dir)
+
+    test_basic_compare ()
+    test_compare_trees ()
+    
+################################################################
+#
+
+def main ():
+    p = optparse.OptionParser ("output-distance - compare LilyPond formatting runs")
+    p.usage = 'output-distance.py [options] tree1 tree2'
+    
+    p.add_option ('', '--test',
+                  dest="run_test",
+                  action="store_true",
+                  help='run test method')
+
+    (o,a) = p.parse_args ()
+
+    if o.run_test:
+        run_tests ()
+        sys.exit (0)
+
+    if len (a) != 2:
+        p.print_usage()
+        sys.exit (2)
+
+    compare_trees (a[0], a[1])
+
+if __name__ == '__main__':
+    main()