Beispiel #1
0
    def test_elementsbyname(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")
        n3 = MeiElement("note")
        n4 = MeiElement("note")

        mei.addChild(mus)
        mus.addChild(body)
        body.addChild(staff)
        body.addChild(staff2)
        staff.addChild(n1)
        staff.addChild(n2)
        staff.addChild(n3)
        staff2.addChild(n4)

        doc = MeiDocument()

        doc.root = mei

        notes = doc.getElementsByName("note")
        self.assertEqual(4, len(notes))

        rests = doc.getElementsByName("rest")
        self.assertEqual(0, len(rests))

        n5 = MeiElement("note")
        staff2.addChild(n5)
        notes_new = doc.getElementsByName('note')
        self.assertEqual(5, len(notes_new))
Beispiel #2
0
    def test_documentpointers(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")
        n3 = MeiElement("note")

        self.assertEqual(None, mei.document)
        mei.addChild(mus)
        self.assertEqual(None, mus.document)

        doc = MeiDocument()
        mus.addChild(body)
        doc.root = mei

        self.assertEqual(doc, mei.document)
        self.assertEqual(doc, mus.document)
        self.assertEqual(doc, body.document)

        self.assertEqual(None, staff.document)
        body.addChild(staff)
        self.assertEqual(doc, staff.document)
Beispiel #3
0
    def test_documentpointers(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")
        n3 = MeiElement("note")

        self.assertEqual(None, mei.document)
        mei.addChild(mus)
        self.assertEqual(None, mus.document)

        doc = MeiDocument()
        mus.addChild(body)
        doc.root = mei

        self.assertEqual(doc, mei.document)
        self.assertEqual(doc, mus.document)
        self.assertEqual(doc, body.document)

        self.assertEqual(None, staff.document)
        body.addChild(staff)
        self.assertEqual(doc, staff.document)
Beispiel #4
0
    def test_getpositionindocument(self):
        m = MeiElement("mei")
        m1 = MeiElement("music")
        musicid = m1.id
        b1 = MeiElement("body")
        s1 = MeiElement("staff")
        n1 = MeiElement("note")
        noteid = n1.id
        n2 = MeiElement("note")
        n3 = MeiElement("note")
        n4 = MeiElement("note")
        note4id = n4.id

        m.addChild(m1)
        m1.addChild(b1)
        b1.addChild(s1)
        s1.addChild(n1)
        s1.addChild(n2)
        s1.addChild(n3)

        doc = MeiDocument()
        doc.root = m

        self.assertEqual(4, n1.getPositionInDocument())

        # an unattached element will return -1
        self.assertEqual(-1, n4.getPositionInDocument())
Beispiel #5
0
    def test_getpositionindocument(self):
        m = MeiElement("mei")
        m1 = MeiElement("music")
        musicid = m1.id
        b1 = MeiElement("body")
        s1 = MeiElement("staff")
        n1 = MeiElement("note")
        noteid = n1.id
        n2 = MeiElement("note")
        n3 = MeiElement("note")
        n4 = MeiElement("note")
        note4id = n4.id

        m.addChild(m1)
        m1.addChild(b1)
        b1.addChild(s1)
        s1.addChild(n1)
        s1.addChild(n2)
        s1.addChild(n3)

        doc = MeiDocument()
        doc.root = m

        self.assertEqual(4, n1.getPositionInDocument())

        # an unattached element will return -1
        self.assertEqual(-1, n4.getPositionInDocument())
Beispiel #6
0
    def test_effective_meter(self):
        music   = MeiElement('music')
        body    = MeiElement('body')
        mdiv    = MeiElement('mdiv')
        score   = MeiElement('score')
        sctn    = MeiElement('section')
        scD1    = MeiElement('scoreDef')
        scD2    = MeiElement('scoreDef')
        stG1    = MeiElement('staffGrp')
        stG2    = MeiElement('staffGrp')
        stD1    = MeiElement('staffDef')
        stD2    = MeiElement('staffDef')

        m1      = MeiElement('measure')
        m2      = MeiElement('measure')
        l1      = MeiElement('layer')
        l2      = MeiElement('layer')
        s1      = MeiElement('staff')
        s2      = MeiElement('staff')

        mR1     = MeiElement('mRest')
        mR2     = MeiElement('mRest')

        scD1.addAttribute('meter.unit', '2')
        stD1.addAttribute('meter.count', '2')
        stD2.addAttribute('meter.count', '3')

        s1.addAttribute('n', '1')
        
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(sctn)
        sctn.addChild(scD1)
        scD1.addChild(stG1)
        stG1.addChild(stD1)
        sctn.addChild(m1)
        m1.addChild(s1)
        s1.addChild(l1)
        l1.addChild(mR1)

        sctn.addChild(scD2)
        scD2.addChild(stG2)
        stG2.addChild(stD2)
        sctn.addChild(m2)
        m2.addChild(s2)
        s2.addChild(l2)
        l2.addChild(mR2)

        doc = MeiDocument()
        doc.setRootElement(music)

        meter1  = utilities.effective_meter(mR1)
        meter2  = utilities.effective_meter(mR2)

        self.assertEqual(meter1.count, '2')
        self.assertEqual(meter1.unit, '2')
        self.assertEqual(meter2.count, '3')
        self.assertEqual(meter2.unit, '2')
Beispiel #7
0
 def test_documentwritefailure(self):
     doc = MeiDocument()
     root = MeiElement("mei")
     root.id = "myid"
     doc.root = root
     with self.assertRaises(FileWriteFailureException) as cm:
         ret = XmlExport.meiDocumentToFile(doc, "C:/StupidPath")
     self.assertTrue(isinstance(cm.exception, FileWriteFailureException))
    def test_effective_meter(self):
        music = MeiElement("music")
        body = MeiElement("body")
        mdiv = MeiElement("mdiv")
        score = MeiElement("score")
        sctn = MeiElement("section")
        scD1 = MeiElement("scoreDef")
        scD2 = MeiElement("scoreDef")
        stG1 = MeiElement("staffGrp")
        stG2 = MeiElement("staffGrp")
        stD1 = MeiElement("staffDef")
        stD2 = MeiElement("staffDef")

        m1 = MeiElement("measure")
        m2 = MeiElement("measure")
        l1 = MeiElement("layer")
        l2 = MeiElement("layer")
        s1 = MeiElement("staff")
        s2 = MeiElement("staff")

        mR1 = MeiElement("mRest")
        mR2 = MeiElement("mRest")

        scD1.addAttribute("meter.unit", "2")
        stD1.addAttribute("meter.count", "2")
        stD2.addAttribute("meter.count", "3")

        s1.addAttribute("n", "1")
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(sctn)
        sctn.addChild(scD1)
        scD1.addChild(stG1)
        stG1.addChild(stD1)
        sctn.addChild(m1)
        m1.addChild(s1)
        s1.addChild(l1)
        l1.addChild(mR1)

        sctn.addChild(scD2)
        scD2.addChild(stG2)
        stG2.addChild(stD2)
        sctn.addChild(m2)
        m2.addChild(s2)
        s2.addChild(l2)
        l2.addChild(mR2)

        doc = MeiDocument()
        doc.setRootElement(music)

        meter1 = utilities.effective_meter(mR1)
        meter2 = utilities.effective_meter(mR2)

        self.assertEqual(meter1.count, "2")
        self.assertEqual(meter1.unit, "2")
        self.assertEqual(meter2.count, "3")
        self.assertEqual(meter2.unit, "2")
Beispiel #9
0
    def test_exporttostring(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"
        doc.root = root

        expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mei xml:id=\"myid\" xmlns=\"http://www.music-encoding.org/ns/mei\" meiversion=\"2013\" />\n"
        ret = documentToText(doc)
        self.assertEqual(expected, ret)
Beispiel #10
0
    def test_exporttostring(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"
        doc.root = root

        expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mei xml:id=\"myid\" xmlns=\"http://www.music-encoding.org/ns/mei\" meiversion=\"2013\" />\n"
        ret = documentToText(doc)
        self.assertEqual(expected, ret)
Beispiel #11
0
    def test_dur_in_semibreves_mRests(self):
        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        sctn = MeiElement('section')
        scD1 = MeiElement('scoreDef')
        scD2 = MeiElement('scoreDef')
        stG1 = MeiElement('staffGrp')
        stG2 = MeiElement('staffGrp')
        stD1 = MeiElement('staffDef')
        stD2 = MeiElement('staffDef')

        m1 = MeiElement('measure')
        m2 = MeiElement('measure')
        l1 = MeiElement('layer')
        l2 = MeiElement('layer')
        s1 = MeiElement('staff')
        s2 = MeiElement('staff')

        mR1 = MeiElement('mRest')
        mR2 = MeiElement('mRest')

        scD1.addAttribute('meter.unit', '2')
        stD1.addAttribute('meter.count', '2')
        stD2.addAttribute('meter.count', '3')

        s1.addAttribute('n', '1')

        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(sctn)

        sctn.addChild(scD1)
        scD1.addChild(stG1)
        stG1.addChild(stD1)
        sctn.addChild(m1)
        m1.addChild(l1)
        l1.addChild(s1)
        s1.addChild(mR1)

        sctn.addChild(scD2)
        scD2.addChild(stG2)
        stG2.addChild(stD2)
        sctn.addChild(m2)
        m2.addChild(l2)
        l2.addChild(s2)
        s2.addChild(mR2)

        doc = MeiDocument()
        doc.setRootElement(music)

        self.assertEqual(doc.lookBack(body, 'music'), music)

        self.assertEqual(utilities.dur_in_semibreves(mR1), 1)
        self.assertEqual(utilities.dur_in_semibreves(mR2), 1.5)
    def test_dur_in_semibreves_mRests(self):
        music = MeiElement("music")
        body = MeiElement("body")
        mdiv = MeiElement("mdiv")
        score = MeiElement("score")
        sctn = MeiElement("section")
        scD1 = MeiElement("scoreDef")
        scD2 = MeiElement("scoreDef")
        stG1 = MeiElement("staffGrp")
        stG2 = MeiElement("staffGrp")
        stD1 = MeiElement("staffDef")
        stD2 = MeiElement("staffDef")

        m1 = MeiElement("measure")
        m2 = MeiElement("measure")
        l1 = MeiElement("layer")
        l2 = MeiElement("layer")
        s1 = MeiElement("staff")
        s2 = MeiElement("staff")

        mR1 = MeiElement("mRest")
        mR2 = MeiElement("mRest")

        scD1.addAttribute("meter.unit", "2")
        stD1.addAttribute("meter.count", "2")
        stD2.addAttribute("meter.count", "3")

        s1.addAttribute("n", "1")

        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(sctn)

        sctn.addChild(scD1)
        scD1.addChild(stG1)
        stG1.addChild(stD1)
        sctn.addChild(m1)
        m1.addChild(l1)
        l1.addChild(s1)
        s1.addChild(mR1)

        sctn.addChild(scD2)
        scD2.addChild(stG2)
        stG2.addChild(stD2)
        sctn.addChild(m2)
        m2.addChild(l2)
        l2.addChild(s2)
        s2.addChild(mR2)

        doc = MeiDocument()
        doc.setRootElement(music)

        self.assertEqual(doc.lookBack(body, "music"), music)

        self.assertEqual(utilities.dur_in_semibreves(mR1), 1)
        self.assertEqual(utilities.dur_in_semibreves(mR2), 1.5)
Beispiel #13
0
    def test_documentwritefailure(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"
        doc.root = root
        with self.assertRaises(FileWriteFailureException) as cm:
            ret = documentToFile(doc, "C:/StupidPath")

        self.assertTrue(isinstance(cm.exception, FileWriteFailureException))
Beispiel #14
0
    def test_setdocument(self):
        m = MeiElement("mei")
        doc = MeiDocument()

        with self.assertRaises(DocumentRootNotSetException) as cm:
            m.setDocument(doc)
        self.assertTrue(isinstance(cm.exception, DocumentRootNotSetException))
        doc.setRootElement(m)

        self.assertEqual(doc.root, m)
Beispiel #15
0
    def test_setdocument(self):
        m = MeiElement("mei")
        doc = MeiDocument()

        with self.assertRaises(DocumentRootNotSetException) as cm:
            m.setDocument(doc)
        self.assertTrue(isinstance(cm.exception, DocumentRootNotSetException))
        doc.setRootElement(m)

        self.assertEqual(doc.root, m)
Beispiel #16
0
    def test_exportcomment(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"

        doc.root = root

        comment = MeiElement("_comment")
        comment.value = "comment"
        comment.tail = "t"

        root.addChild(comment)
        expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mei xml:id=\"myid\" xmlns=\"http://www.music-encoding.org/ns/mei\" meiversion=\"2013\">\n\t<!--comment-->t</mei>\n"
        ret = documentToText(doc)
        self.assertEqual(expected, ret)
Beispiel #17
0
    def test_exportnamespace(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"
        doc.root = root

        xlink = MeiNamespace("xlink", "http://www.w3.org/1999/xlink")
        attr = MeiAttribute(xlink, "title", "my awesome thing")
        root.addAttribute(attr)

        expected = "<?xml version=\"1.0\"?>\n<mei xmlns=\"http://www.music-encoding.org/ns/mei\" \
xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"myid\" xlink:title=\"my awesome thing\" meiversion=\"2013\"/>\n";

        ret = XmlExport.meiDocumentToText(doc)
        self.assertEqual(expected, ret)
Beispiel #18
0
    def test_exportcomment(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"

        doc.root = root

        comment = MeiElement("_comment")
        comment.value = "comment"
        comment.tail = "t"

        root.addChild(comment)
        expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mei xml:id=\"myid\" xmlns=\"http://www.music-encoding.org/ns/mei\" meiversion=\"2013\">\n\t<!--comment-->t</mei>\n"
        ret = documentToText(doc)
        self.assertEqual(expected, ret)
Beispiel #19
0
    def test_exportvalueandtail(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"
        doc.root = root

        note = MeiElement("note")
        note.id = "noteid"
        note.value = "value"
        note.tail = "tail"
        root.addChild(note)

        expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mei xml:id=\"myid\" xmlns=\"http://www.music-encoding.org/ns/mei\" meiversion=\"2013\">\n\t<note xml:id=\"noteid\">value</note>tail</mei>\n"
        ret = documentToText(doc)

        self.assertEqual(expected, ret)
Beispiel #20
0
    def test_exportvalueandtail(self):
        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"
        doc.root = root

        note = MeiElement("note")
        note.id = "noteid"
        note.value = "value"
        note.tail = "tail"
        root.addChild(note)

        expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mei xml:id=\"myid\" xmlns=\"http://www.music-encoding.org/ns/mei\" meiversion=\"2013\">\n\t<note xml:id=\"noteid\">value</note>tail</mei>\n"
        ret = documentToText(doc)

        self.assertEqual(expected, ret)
Beispiel #21
0
    def test_getnamespace(self):
        doc = MeiDocument()
        ns = MeiNamespace("prefix", "http://example.com/ns")
        self.assertEqual("http://www.music-encoding.org/ns/mei",
                         doc.getNamespaces()[0].href)

        doc.addNamespace(ns)
        self.assertEqual(2, len(doc.getNamespaces()))
        self.assertEqual(ns, doc.getNamespace("http://example.com/ns"))

        self.assertTrue(
            doc.hasNamespace("http://www.music-encoding.org/ns/mei"))
        self.assertFalse(doc.hasNamespace("http://www.mcgill.ca"))
Beispiel #22
0
    def test_lookback(self):
        m = MeiElement("mei")
        m1 = MeiElement("music")
        b1 = MeiElement("body")
        s1 = MeiElement("staff")
        n1 = MeiElement("note")

        doc = MeiDocument()
        doc.setRootElement(m)
        m.addChild(m1)
        m1.addChild(b1)
        b1.addChild(s1)
        s1.addChild(n1)
        
        self.assertEqual(m1.lookBack('mei'), m)

        self.assertEqual(s1.lookBack('mei'), m)
Beispiel #23
0
    def test_lookback(self):
        m = MeiElement("mei")
        m1 = MeiElement("music")
        b1 = MeiElement("body")
        s1 = MeiElement("staff")
        n1 = MeiElement("note")

        doc = MeiDocument()
        doc.setRootElement(m)
        m.addChild(m1)
        m1.addChild(b1)
        b1.addChild(s1)
        s1.addChild(n1)

        self.assertEqual(m1.lookBack('mei'), m)

        self.assertEqual(s1.lookBack('mei'), m)
Beispiel #24
0
    def test_getnamespace(self):
        doc = MeiDocument()
        ns = MeiNamespace("prefix", "http://example.com/ns")
        self.assertEqual("http://www.music-encoding.org/ns/mei", doc.getNamespaces()[0].href)

        doc.addNamespace(ns)
        self.assertEqual(2, len(doc.getNamespaces()))
        self.assertEqual(ns, doc.getNamespace("http://example.com/ns"))

        self.assertTrue(doc.hasNamespace("http://www.music-encoding.org/ns/mei"))
        self.assertFalse(doc.hasNamespace("http://www.mcgill.ca"))
Beispiel #25
0
    def test_exportProcessingInstructions(self):
        procinst = XmlInstructions()

        xpi1 = XmlProcessingInstruction("xml-model", "href=\"mei-2012.rng\" type=\"application/xml\" schematypens=\"http://purl.oclc.org/dsdl/schematron\"")
        xpi2 = XmlProcessingInstruction("xml-stylesheet", "href=\"mei-2012.rng\" type=\"application/xml\" schematypens=\"http://purl.oclc.org/dsdl/schematron\"")

        procinst.extend([xpi1, xpi2])

        doc = MeiDocument()
        root = MeiElement("mei")
        root.id = "myid"
        doc.root = root

        ret = XmlExport.meiDocumentToText(doc, procinst)

        expected = "<?xml version=\"1.0\"?>\n<?xml-model href=\"mei-2012.rng\" type=\"application/xml\" \
schematypens=\"http://purl.oclc.org/dsdl/schematron\"?>\n<?xml-stylesheet href=\"mei-2012.rng\" type=\"application/xml\" \
schematypens=\"http://purl.oclc.org/dsdl/schematron\"?>\n<mei xmlns=\"http://www.music-encoding.org/ns/mei\" \
xml:id=\"myid\" meiversion=\"2013\"/>\n"

        self.assertEqual(expected, ret)
Beispiel #26
0
    def test_elementsbyname(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")
        n3 = MeiElement("note")
        n4 = MeiElement("note")

        mei.addChild(mus)
        mus.addChild(body)
        body.addChild(staff)
        body.addChild(staff2)
        staff.addChild(n1)
        staff.addChild(n2)
        staff.addChild(n3)
        staff2.addChild(n4)

        doc = MeiDocument()

        doc.root = mei

        notes = doc.getElementsByName("note")
        self.assertEqual(4, len(notes))

        rests = doc.getElementsByName("rest")
        self.assertEqual(0, len(rests))

        n5 = MeiElement("note")
        staff2.addChild(n5)
        notes_new = doc.getElementsByName('note')
        self.assertEqual(5, len(notes_new))
Beispiel #27
0
    def test_printElement(self):
        m = MeiElement("mei")
        m1 = MeiElement("music")
        b1 = MeiElement("body")
        s1 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")

        m.addAttribute("meiversion", "2013")

        doc = MeiDocument()
        doc.setRootElement(m)
        m.addChild(m1)
        m1.addChild(b1)
        b1.addChild(s1)
        s1.addChild(n1)
        s1.addChild(n2)

        n1.addAttribute('headshape', 'diamond')
        n1.addAttribute('pname', 'c')
        n2.addAttribute('pname', 'd')

        m.printElement()
Beispiel #28
0
    def test_printElement(self):
        m = MeiElement("mei")
        m1 = MeiElement("music")
        b1 = MeiElement("body")
        s1 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")

        m.addAttribute("meiversion", "2013")

        doc = MeiDocument()
        doc.setRootElement(m)
        m.addChild(m1)
        m1.addChild(b1)
        b1.addChild(s1)
        s1.addChild(n1)
        s1.addChild(n2)

        n1.addAttribute('headshape', 'diamond')
        n1.addAttribute('pname', 'c')
        n2.addAttribute('pname', 'd')

        m.printElement()
Beispiel #29
0
    def test_elementbyid(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        wantedId = n1.id
        n2 = MeiElement("note")
        n3 = MeiElement("note")
        n4 = MeiElement("note")

        mei.addChild(mus)
        mus.addChild(body)
        body.addChild(staff)
        body.addChild(staff2)
        staff.addChild(n1)
        staff.addChild(n2)
        staff.addChild(n3)
        staff2.addChild(n4)

        doc = MeiDocument()
        self.assertEqual(None, doc.getElementById(wantedId))

        doc.root = mei

        self.assertEqual(n1, doc.getElementById(wantedId))

        self.assertEqual(None, doc.getElementById("unknownID"))

        n5 = MeiElement("note")
        newid = n5.id
        staff2.addChild(n5)

        self.assertEqual(n5, doc.getElementById(newid))
        staff2.removeChild(n5)
        self.assertEqual(None, doc.getElementById(newid))
Beispiel #30
0
    def test_elementbyid(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        wantedId = n1.id
        n2 = MeiElement("note")
        n3 = MeiElement("note")
        n4 = MeiElement("note")

        mei.addChild(mus)
        mus.addChild(body)
        body.addChild(staff)
        body.addChild(staff2)
        staff.addChild(n1)
        staff.addChild(n2)
        staff.addChild(n3)
        staff2.addChild(n4)

        doc = MeiDocument()
        self.assertEqual(None, doc.getElementById(wantedId))

        doc.root = mei

        self.assertEqual(n1, doc.getElementById(wantedId))

        self.assertEqual(None, doc.getElementById("unknownID"))

        n5 = MeiElement("note")
        newid = n5.id
        staff2.addChild(n5)

        self.assertEqual(n5, doc.getElementById(newid))
        staff2.removeChild(n5)
        self.assertEqual(None, doc.getElementById(newid))
Beispiel #31
0
    def bardata_to_mei(self, sg_hint, image_path, image_width, image_height, image_dpi=72):
        '''
        Perform the data conversion to mei
        '''

        self.meidoc = MeiDocument()
        mei = MeiElement('mei')
        self.meidoc.setRootElement(mei)

        ###########################
        #         MetaData        #
        ###########################
        mei_head = self._create_header()
        mei.addChild(mei_head)

        ###########################
        #           Body          #
        ###########################
        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')
        section = MeiElement('section')

        # physical location data
        facsimile = MeiElement('facsimile')
        surface = MeiElement('surface')

        graphic = self._create_graphic(image_path, image_width, image_height)
        surface.addChild(graphic)

        # parse staff group hint to generate staff group
        sg_hint = sg_hint.split(" ")
        systems = []
        for s in sg_hint:
            parser = nestedExpr()
            sg_list = parser.parseString(s).asList()[0]
            staff_grp, n = self._create_staff_group(sg_list, MeiElement('staffGrp'), 0)

            # parse repeating staff groups (systems)
            num_sb = 1
            match = re.search('(?<=x)(\d+)$', s)
            if match is not None:
                # there are multiple systems of this staff grouping
                num_sb = int(match.group(0))

            for i in range(num_sb):
                systems.append(staff_grp)

            if self.verbose:
                print "number of staves in system: %d x %d system(s)" % (n, num_sb)

        # there may be hidden staves in a system
        # make the encoded staff group the largest number of staves in a system
        final_staff_grp = max(systems, key=lambda x: len(x.getDescendantsByName('staffDef')))

        mei.addChild(music)
        music.addChild(facsimile)
        facsimile.addChild(surface)

        # list of staff bounding boxes within a system
        staves = []
        for staff_bb in self.staff_bb:
            # get bounding box of the staff
            # parse bounding box integers
            #staff_bb = [int(x) for x in staff_bb]
            staves.append(staff_bb[1:])

        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(final_staff_grp)
        score.addChild(section)

        # parse barline data file [staffnum][barlinenum_ulx]
        barlines = []
        for i, bar in enumerate(self.bar_bb):
            staff_num = int(bar[0])
            ulx = bar[1]
            try:
                barlines[staff_num - 1].append(ulx)
            except IndexError:
                barlines.append([ulx])

        staff_offset = 0
        n_measure = 1
        b1_thresh = 1.25
        bn_thresh = 1.25
        # for each system
        for s_ind, s in enumerate(systems):
            # measures in a system
            s_measures = []
            staff_defs = s.getDescendantsByName('staffDef')
            # for each staff in the system
            for i in range(len(staff_defs)):
                staff_num = staff_offset + i
                s_bb = staves[staff_num]
                # bounding box of the staff
                s_ulx = s_bb[0]
                s_uly = s_bb[1]
                s_lrx = s_bb[2]
                s_lry = s_bb[3]

                # for each barline on this staff
                try:
                    staff_bars = barlines[staff_num]
                except IndexError:
                    # a staff was found, but no bar candidates have been found on the staff
                    continue

                # check the first barline candidate
                # If it is sufficiently close to the beginning of the staff then ignore it.
                b1_x = staff_bars[0]
                if abs(b1_x / image_dpi - s_ulx / image_dpi) < b1_thresh:
                    del staff_bars[0]

                # check the last barline candidate
                # if there is no candidate near the end of the interior of the staff, add one
                bn_x = staff_bars[-1]
                if bn_x < s_lrx and abs(bn_x / image_dpi - s_lrx / image_dpi) > bn_thresh:
                    staff_bars.append(s_lrx)

                for n, b in enumerate(staff_bars):
                    # calculate bounding box of the measure
                    m_uly = s_uly
                    m_lry = s_lry

                    m_lrx = b
                    if n == len(staff_bars) - 1:
                        m_lrx = s_lrx

                    if n == 0:
                        m_ulx = s_ulx
                    else:
                        m_ulx = staff_bars[n - 1]

                    # create staff element
                    zone = self._create_zone(m_ulx, m_uly, m_lrx, m_lry)
                    surface.addChild(zone)
                    if len(sg_hint) == 1 or len(staff_defs) == len(final_staff_grp.getDescendantsByName('staffDef')):
                        staff_n = str(i + 1)
                    else:
                        # take into consideration hidden staves
                        staff_n = i + self._calc_staff_num(len(staff_defs), [final_staff_grp])

                    staff = self._create_staff(staff_n, zone)

                    try:
                        s_measures[n].addChild(staff)
                    except IndexError:
                        # create a new measure
                        measure = self._create_measure(str(n_measure))
                        s_measures.append(measure)
                        section.addChild(measure)
                        measure.addChild(staff)
                        n_measure += 1

            # calculate min/max of measure/staff bounding boxes to get measure zone
            self._calc_measure_zone(s_measures)

            staff_offset += len(staff_defs)

            # add a system break, if necessary
            if s_ind + 1 < len(systems):
                sb = MeiElement('sb')
                section.addChild(sb)
Beispiel #32
0
def generate_base_document():
    '''
    Generates a generic template for an MEI document for neume notation.

    Currently a bit of this is hardcoded and should probably be made more customizable.
    '''
    meiDoc = MeiDocument("4.0.0")

    mei = MeiElement("mei")
    mei.addAttribute("meiversion", "4.0.0")
    meiDoc.root = mei

    # placeholder meiHead
    meihead = MeiElement('meiHead')
    mei.addChild(meihead)
    fileDesc = MeiElement('fileDesc')
    meihead.addChild(fileDesc)
    titleSt = MeiElement('titleStmt')
    fileDesc.addChild(titleSt)
    title = MeiElement('title')
    titleSt.addChild(title)
    title.setValue('MEI Encoding Output (%s)' % __version__)
    pubStmt = MeiElement('pubStmt')
    fileDesc.addChild(pubStmt)

    music = MeiElement("music")
    mei.addChild(music)

    facs = MeiElement("facsimile")
    music.addChild(facs)

    surface = MeiElement("surface")
    facs.addChild(surface)

    body = MeiElement('body')
    music.addChild(body)

    mdiv = MeiElement('mdiv')
    body.addChild(mdiv)

    score = MeiElement('score')
    mdiv.addChild(score)

    scoreDef = MeiElement('scoreDef')
    score.addChild(scoreDef)

    staffGrp = MeiElement('staffGrp')
    scoreDef.addChild(staffGrp)

    staffDef = MeiElement('staffDef')
    staffGrp.addChild(staffDef)

    # these hardcoded attributes define a single staff with 4 lines, neume notation, with a default c clef
    staffDef.addAttribute('n', '1')
    staffDef.addAttribute('lines', '4')
    staffDef.addAttribute('notationtype', 'neume')
    staffDef.addAttribute('clef.line', '3')
    staffDef.addAttribute('clef.shape', 'C')

    section = MeiElement('section')
    score.addChild(section)

    staff = MeiElement('staff')
    section.addChild(staff)

    layer = MeiElement('layer')
    staff.addChild(layer)

    return meiDoc, surface, layer
Beispiel #33
0
    def test_flattenedtree(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")
        n3 = MeiElement("note")

        doc = MeiDocument()

        mei.addChild(mus)

        doc.root = mei

        mus.addChild(body)
        body.addChild(staff)
        body.addChild(staff2)
        staff.addChild(n1)
        staff.addChild(n2)
        staff2.addChild(n3)

        doc.lookBack(n2, "mei")
        self.assertEqual(8, len(doc.getFlattenedTree()))

        staff.removeChild(n2)
        self.assertEqual(7, len(doc.getFlattenedTree()))

        self.assertEqual(staff2, doc.getFlattenedTree()[5])

        staff.removeChildrenWithName("note")
        self.assertEqual(6, len(doc.getFlattenedTree()))

        body.deleteAllChildren()
        self.assertEqual(3, len(doc.getFlattenedTree()))

        children = MeiElementList()
        staff3 = MeiElement("staff")
        staff4 = MeiElement("staff")
        children.append(staff3)
        children.append(staff4)

        body.children = children

        self.assertEqual(5, len(doc.getFlattenedTree()))

        elements = [mei, mus, body, staff3, staff4]

        for i, el in enumerate(doc.getFlattenedTree()):
            self.assertEqual(elements[i], doc.getFlattenedTree()[i])
    def write_mei(self, notes, output_path=None):
        # begin constructing mei document
        meidoc = MeiDocument()
        mei = MeiElement('mei')
        meidoc.setRootElement(mei)
        mei_head = MeiElement('meiHead')
        mei.addChild(mei_head)

        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')

        # assume 4/4 time signature
        meter_count = 4
        meter_unit = 4
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))
        
        staff_def = MeiElement('staffDef')
        staff_def.addAttribute('n', '1')
        staff_def.addAttribute('label.full', 'Electric Guitar')
        staff_def.addAttribute('clef.shape', 'TAB')

        instr_def = MeiElement('instrDef')
        instr_def.addAttribute('n', 'Electric_Guitar')
        instr_def.addAttribute('midi.channel', '1')
        instr_def.addAttribute('midi.instrnum', '28')

        mei.addChild(music)
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(staff_def)
        staff_def.addChild(instr_def)

        section = MeiElement('section')
        score.addChild(section)
        # another score def
        score_def = MeiElement('scoreDef')
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))
        section.addChild(score_def)
        
        # start writing pitches to file
        note_container = None
        for i, frame_n in enumerate(notes):
            if i % meter_count == 0:
                measure = MeiElement('measure')
                measure.addAttribute('n', str(int(i/meter_count + 1)))
                staff = MeiElement('staff')
                staff.addAttribute('n', '1')
                layer = MeiElement('layer')
                layer.addAttribute('n', '1')
                section.addChild(measure)
                measure.addChild(staff)
                staff.addChild(layer)
                note_container = layer

            if len(frame_n) > 1:
                chord = MeiElement('chord')
                for n in frame_n:
                    note = MeiElement('note')
                    pname = n['pname'][0].upper()
                    note.addAttribute('pname', pname)
                    note.addAttribute('oct', str(n['oct']))
                    if len(n['pname']) > 1 and n['pname'][1] == '#':
                        # there is an accidental
                        note.addAttribute('accid.ges', 's')
                    note.addAttribute('dur', str(meter_unit))
                    chord.addChild(note)
                note_container.addChild(chord)
            else:
                n = frame_n[0]
                note = MeiElement('note')
                pname = n['pname'][0].upper()
                note.addAttribute('pname', pname)
                note.addAttribute('oct', str(n['oct']))
                if len(n['pname']) > 1 and n['pname'][1] == '#':
                    # there is an accidental
                    note.addAttribute('accid.ges', 's')
                note.addAttribute('dur', str(meter_unit))
                note_container.addChild(note)

        if output_path is not None:
            XmlExport.meiDocumentToFile(meidoc, output_path)
        else:
            return XmlExport.meiDocumentToText(meidoc)
Beispiel #35
0
 def test_setversion(self):
     doc = MeiDocument()
     self.assertEqual("2012", doc.version)
Beispiel #36
0
class AomrMeiOutput(object):
    # define the form of a neume.
    # form: [ num, interval_dir... ]
    # e.g., clivis: [2, 'd']
    # torculus: [3, 'u', 'd']
    NEUME_NOTES = {
        'punctum': [],
        'virga': [],
        'cephalicus': ['d'],
        'clivis': ['d'],
        'epiphonus': ['u'],
        'podatus': ['u'],
        'porrectus': ['d', 'u'],
        'salicus': ['u', 'u'],
        'scandicus': ['u', 'u'],
        'torculus': ['u', 'd'],
        'ancus': ['d', 'd'],  # See note 1 below
    }

    # given an alternate form, how many notes does it add to the neume?
    ADD_NOTES = {
        'flexus': ['d'],  # scandicus.flexus, porrectus.flexus
        'resupinus': ['u'],  # torculus.resupinus
    }

    SCALE = ['a', 'b', 'c', 'd', 'e', 'f', 'g']

    def __init__(self, incoming_data, original_image, page_number=None):
        self._recognition_results = incoming_data
        # self.mei = mod.mei_()
        self.mei = MeiElement("mei")
        self.staff = None

        # Hack: I'm not sure what staff_num is. In any case it's strange to set it to None.
        # I therefore set it to 0 if page_number is None.
        if page_number is not None:
            self.staff_num = int(page_number)
        else:
            self.staff_num = 0
        self.glyph = None

        self._note_elements = None
        self._neume_pitches = []

        # set up a basic MEI document structure

        # header
        # self.meihead = mod.meiHead_()
        self.meihead = MeiElement("meiHead")
        # self.filedesc = mod.fileDesc_()
        self.filedesc = MeiElement("fileDesc")
        # self.titlestmt = mod.titleStmt_()
        self.titlestmt = MeiElement("titleStmt")
        # self.title = mod.title_()
        self.title = MeiElement("title")
        # self.pubstmt = mod.pubStmt_()
        self.pubstmt = MeiElement("pubStmt")

        self.titlestmt.addChild(self.title)

        self.filedesc.addChild(self.titlestmt)
        self.filedesc.addChild(self.pubstmt)

        self.meihead.addChild(self.filedesc)
        self.mei.addChild(self.meihead)

        # music
        # self.music = mod.music_()
        self.music = MeiElement("music")
        self.facsimile = self._create_facsimile_element()
        self.surface = self._create_surface_element()
        self.graphic = self._create_graphic_element(original_image)
        lg.debug("SELF GRAPHIC:{0}".format(XmlExport.meiElementToText(self.graphic)))

        self.surface.addChild(self.graphic)
        self.facsimile.addChild(self.surface)
        self.music.addChild(self.facsimile)

        self.layout = self._create_layout_element()
        self.pg = self._create_page_element()
        if page_number:
            # self.pg.attributes = {"n": page_number}
            self.pg.addAttribute("n", page_number)

        self.layout.addChild(self.pg)
        self.music.addChild(self.layout)

        # self.body = mod.body_()
        self.body = MeiElement("body")
        self.music.addChild(self.body)

        self.mdiv = MeiElement("mdiv")
        # self.mdiv = mod.mdiv_()
        self.mdiv.addAttribute("type", "solesmes")
        self.body.addChild(self.mdiv)

        # self.score = mod.score_()
        self.score = MeiElement("score")
        self.mdiv.addChild(self.score)

        # self.scoredef = mod.scoreDef_()
        self.scoredef = MeiElement("scoreDef")
        self.score.addChild(self.scoredef)

        # self.section = mod.section_()
        self.section = MeiElement("section")
        self.pagebreak = self._create_pb_element()
        # self.pagebreak.attributes = {"pageref": self.pg.id}
        self.pagebreak.addAttribute("pageref", self.pg.id)

        self.section.addChild(self.pagebreak)
        self.score.addChild(self.section)

        self.staffgrp = self._create_staffgrp_element()
        self.staffdef = self._create_staffdef_element()
        self.staffdef.addAttribute("n", str(self.staff_num))   # trouble

        self.staffgrp.addChild(self.staffdef)
        self.scoredef.addChild(self.staffgrp)

        self.layer = self._create_layer_element()
        self.layer.addAttribute("n", "1")

        self.staffel = self._create_staff_element()
        self.staffel.addAttribute("n", str(self.staff_num))   # trouble
        self.section.addChild(self.staffel)
        self.staffel.addChild(self.layer)

        for sysnum in sorted(self._recognition_results.keys()):
            syst = self._recognition_results[sysnum]
            lg.debug("sysnum:{0}".format(sysnum))
            self.system = syst
            self.systembreak = self._parse_system(sysnum, syst)
            # z = mod.zone_()
            z = MeiElement("zone")
            # z.id = self._idgen()
            # z.attributes = {'ulx': self.system['coord'][0], 'uly': self.system['coord'][1], \
            #                     'lrx': self.system['coord'][2], 'lry': self.system['coord'][3]}
            z.addAttribute("ulx", str(self.system['coord'][0]))
            z.addAttribute("uly", str(self.system['coord'][1]))
            z.addAttribute("lrx", str(self.system['coord'][2]))
            z.addAttribute("lry", str(self.system['coord'][3]))
            self.surface.addChild(z)
            # self.system.facs = z.id
            s = self._create_system_element()
            s.facs = z.id
            s.addAttribute("facs", s.facs)
            self.pg.addChild(s)
            self.systembreak.addAttribute("systemref", s.id)

        self.mei.addChild(self.music)

        # if not self.staffel.descendants_by_name('neume'):
        if not self.staffel.getDescendantsByName("neume"):
            self.staffgrp.removeChild(self.staffdef)
            self.section.removeChild(self.staffel)

        # self.md = MeiDocument.MeiDocument()
        # self.md.addelement(self.mei)
        self.md = MeiDocument()
        self.md.setRootElement(self.mei)
        print XmlExport.meiElementToText(self.md.getElementById(self.graphic.getId()))

    def _parse_system(self, sysnum, syst):
        sysbrk = self._create_sb_element()
        # sysbrk.attributes = {"n": sysnum + 1}
        sysnum = int(sysnum)
        sysbrk.addAttribute("n", "%d" % (sysnum+1))
        self.layer.addChild(sysbrk)
        # staffel = self._create_staff_element()
        # staffel.addAttribute("n", stfnum)

        for c in self.system['content']:
            # parse the glyphs per staff.
            self.glyph = c
            if c['type'] == 'neume':
                if not self.glyph['form']:
                    lg.debug("Skipping glyph: {0}".format(self.glyph))
                    continue
                if self.glyph['form'][0] not in self.NEUME_NOTES.keys():
                    continue
                else:
                    self.layer.addChild(self._create_neume_element())

            elif c['type'] == 'clef':
                self.layer.addChild(self._create_clef_element())
            elif c['type'] == 'division':
                self.layer.addChild(self._create_division_element())
                if "final" in c['form']:
                    self.staff_num += 1
                    new_staff = self._create_staff_element()
                    new_staffdef = self._create_staffdef_element()
                    # new_staffdef.attributes = {'n': self.staff_num} TROUBLE
                    new_staffdef.addAttribute('n', str(self.staff_num))
                    # new_staff.attributes = {'n': self.staff_num} TROUBLE
                    new_staff.addAttribute('n', str(self.staff_num))
                    new_layer = self._create_layer_element()
                    # new_layer.attributes = {'n': 1} TROUBLE
                    new_layer.addAttribute('n', str(1))
                    self.layer = new_layer
                    self.staffel = new_staff
                    self.staffdef = new_staffdef
                    self.staffgrp.addChild(self.staffdef)
                    self.staffel.addChild(self.layer)
                    self.section.addChild(self.staffel)

            elif c['type'] == 'custos':
                self.layer.addChild(self._create_custos_element())

            elif c['type'] == "alteration":
                # staffel.addChild(self._create_alteration_element()) #GVM_OLD
                pass
        return sysbrk

    def _create_graphic_element(self, imgfile):
        graphic = MeiElement("graphic")
        # xlink = MeiNamespace("xlink", "http://www.w3.org/1999/xlink")
        # ns_attr = MeiAttribute("xlink")
        graphic.addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink")
        graphic.addAttribute("xlink:href", imgfile)
        return graphic

    def _create_alteration_element(self):
        # accid = mod.accid_()
        accid = MeiElement("accid")
        accid.id = self._idgen()
        if self.glyph['form'] is "sharp":
            accid.addAttribute("accid", "s")
        elif self.glyph['form'] is "flat":
            accid.addAttribute("accid", "f")

        # zone = self._create_zone_element()
        # note.facs = zone.id
        return accid

    def _create_surface_element(self):
        # surface = mod.surface_()
        surface = MeiElement("surface")
        return surface

    def _create_facsimile_element(self):
        # facsimile = mod.facsimile_()
        facsimile = MeiElement("facsimile")
        # facsimile.id = self._idgen()
        return facsimile

    def _create_zone_element(self):
        zone = MeiElement("zone")
        # zone = mod.zone_()
        # zone.id = self._idgen()
        # zone.attributes = {'ulx': self.glyph['coord'][0], 'uly': self.glyph['coord'][1], \
        #                     'lrx': self.glyph['coord'][2], 'lry': self.glyph['coord'][3]}

        zone.addAttribute("ulx", str(self.glyph['coord'][0]))
        zone.addAttribute("uly", str(self.glyph['coord'][1]))
        zone.addAttribute("lrx", str(self.glyph['coord'][2]))
        zone.addAttribute("lry", str(self.glyph['coord'][3]))
        self.surface.addChild(zone)
        return zone

    def _create_layer_element(self):
        layer = MeiElement("layer")
        # layer = mod.layer_()
        # layer.id = self._idgen()
        lg.debug("layer:{0}".format(layer))
        return layer

    def _create_staffgrp_element(self):
        # stfgrp = mod.staffGrp_()
        stfgrp = MeiElement("staffGrp")
        # stfgrp.id = self._idgen()
        return stfgrp

    def _create_staffdef_element(self):
        stfdef = MeiElement("staffDef")
        # stfdef = mod.staffDef_()
        # stfdef.id = self._idgen()
        return stfdef

    def _create_staff_element(self):
        # staff = mod.staff_()
        staff = MeiElement("staff")
        # staff.id = self._idgen()
        return staff

    def _create_sb_element(self):
        sb = MeiElement("sb")
        # sb = mod.sb_()
        # sb.id = self._idgen()
        return sb

    def _create_pb_element(self):
        # pb = mod.pb_()
        pb = MeiElement("pb")
        # pb.id = self._idgen()
        return pb

    def _create_layout_element(self):
        layout = MeiElement("layout")           # GVM_FIXED
        return layout

    def _create_page_element(self):
        page = MeiElement("page")               # FIXED?
        # page = mod.page_()
        # page.id = self._idgen()
        return page

    def _create_system_element(self):
        system = MeiElement("system")           # FIXED?
        # system = mod.system_()
        # system.id = self._idgen()
        return system

    def _create_episema_element(self):
        epi = MeiElement("episema")
        # epi = mod.episema_()
        # epi.id = self._idgen()
        return epi

    def _create_neume_element(self):
        full_width_episema = False
        has_dot = False
        has_vertical_episema = False
        has_horizontal_episema = False
        has_quilisma = False
        this_neume_form = None
        local_horizontal_episema = None

        start_octave = self.glyph['octv']
        clef_pos = self.glyph['clef_pos']
        clef_type = self.glyph['clef'].split(".")[-1]  # f or c.

        # neume = mod.neume_()
        neume = MeiElement("neume")                            # CHECK!
        # neume.id = self._idgen()
        zone = self._create_zone_element()
        neume.facs = zone.id
        neume.addAttribute("facs", neume.facs)

        # neumecomponent = mod.nc_()
        neumecomponent = MeiElement("nc")                      # CHECK!
        # neumecomponent.id = self._idgen()
        neume.addChild(neumecomponent)
        if self.glyph['form'][0] == "he":
            full_width_episema = True
            del self.glyph['form'][0]

        # we've removed any global he's, so
        # any leftovers should be local.
        if 'he' in self.glyph['form']:
            has_horizontal_episema = True

        if 'dot' in self.glyph['form']:
            has_dot = True

        if 'q' in self.glyph['form']:
            has_quilisma = True

        if 've' in self.glyph['form']:
            has_vertical_episema = True

        if 'inclinatum' in self.glyph['form']:
            # neumecomponent.attributes = {'inclinatum': 'true'}
            neumecomponent.addAttribute("inclinatum", "true")

        # neume.attributes = {'name': self.glyph['form'][0]}
        neume.addAttribute("name", str(self.glyph['form'][0]))

        if 'compound' in self.glyph['form']:
            # do something and create a new set of pitch contours
            this_neume_form = [y for y in (self.__parse_contour(n) for n in self.glyph['form']) if y]
            self._note_elements = [y for y in (self.__parse_steps(n) for n in self.glyph['form']) if y]
        else:
            this_neume_form = copy.deepcopy(self.NEUME_NOTES[self.glyph['form'][0]])
            self._note_elements = self.glyph['form'][1:]
        # get the form so we can find the number of notes we need to construct.

        num_notes = len(this_neume_form) + 1
        # we don't have an off-by-one problem here, since an added interval means an added note
        check_additional = [i for i in self.ADD_NOTES.keys() if i in self.glyph['form'][1:]]
        if check_additional:
            for f in check_additional:
                this_neume_form.extend(self.ADD_NOTES[f])

                ## THIS SHOULD BE CHANGED. Otherwise we may end up with two attributes with the
                # same name.
                neume.addAttribute("variant", str(f))

            num_notes = num_notes + len(check_additional)

        self._neume_pitches = []
        # note elements are everything after the first form. This determines the shape a note takes.
        self._neume_pitches.append(self.glyph['strt_pitch'])
        nc = []
        note_octaves = [start_octave]
        if num_notes > 1:
            # we need to figure out the rest of the pitches in the neume.
            ivals = [int(d) for d in self._note_elements if d.isdigit()]
            idx = self.SCALE.index(self.glyph['strt_pitch'])

            if len(ivals) != (num_notes - 1):
                if 'scandicus' in self.glyph['form']:
                    diffr = abs(len(ivals) - (num_notes - 1))
                    num_notes = num_notes + diffr
                    this_neume_form.extend(diffr * 'u')
                else:
                    raise AomrMeiNoteIntervalMismatchError("There is a mismatch between the number of notes and number of intervals.")

            # note elements = torculus.2.2.he.ve
            # ivals = [2,2]
            # torculus = ['u','d']
            this_pos = copy.deepcopy(self.glyph['strt_pos'])
            for n in xrange(len(ivals)):
                # get the direction
                dir = this_neume_form[n]
                iv = ivals[n]
                n_idx = idx
                if dir == "u":
                    n_idx = ((idx + iv) % len(self.SCALE)) - 1
                    this_pos -= (iv - 1)
                elif dir == "d":
                    n_idx = idx - (iv - 1)
                    this_pos += (iv - 1)
                    if n_idx < 0:
                        n_idx += len(self.SCALE)
                idx = n_idx
                self._neume_pitches.append(self.SCALE[n_idx])

                actual_line = 10 - (2*(clef_pos-1))

                if clef_type:
                    if this_pos <= actual_line:
                        note_octaves.append(4)
                    elif this_pos > actual_line + 7:
                        note_octaves.append(2)
                    else:
                        note_octaves.append(3)
                # elif clef_type == "f":
                #     if (actual_line + 3) >= this_pos > (actual_line - 3):
                #         note_octaves.append(3)
                #     elif this_pos < (actual_line - 3):
                #         note_octaves.append(4)
                #     elif this_pos > (actual_line + 3):
                #         note_octaves.append(2)

        if full_width_episema is True:
            epi = self._create_episema_element()
            # epi.attributes = {"form": "horizontal"} TROUBLE
            epi.addAttribute("form", "horizontal")
            self.layer.addChild(epi)

        qidxs = []
        if has_quilisma:
            self.__note_addition_figurer_outer("q", qidxs)

        dotidxs = []
        if has_dot:
            self.__note_addition_figurer_outer("dot", dotidxs)

        veidxs = []
        if has_vertical_episema:
            self.__note_addition_figurer_outer("ve", veidxs)

        heidxs = []
        if has_horizontal_episema:
            self.__note_addition_figurer_outer("he", heidxs)

        for n in xrange(num_notes):
            p = self._neume_pitches[n]
            o = note_octaves[n]
            # lg.debug("n:{0}, p:{1}, o:{2}".format(n, p, o))
            nt = self._create_note_element(p)
            nt.addAttribute("oct", str(o))
            # lg.debug("nt.pitchname:{0}".format(nt.pname))
            if n == 0 and full_width_episema is True:
                epi.addAttribute("startid", str(nt.id))
            elif n == num_notes and full_width_episema is True:
                epi.addAttribute("endid", str(nt.id))

            if has_quilisma:
                if n in qidxs:
                    neumecomponent.addAttribute("quilisma", "true")

            if has_dot:
                if n in dotidxs:
                    d = self._create_dot_element()
                    nt.addChild(d)

            if has_vertical_episema:
                if n in veidxs:
                    ep = self._create_episema_element()
                    ep.addAttribute("form", "vertical")
                    ep.addAttribute("startid", str(nt.id))
                    self.layer.addChild(ep)

            if has_horizontal_episema:
                if n in heidxs:
                    local_horizontal_episema = self._create_episema_element()
                    local_horizontal_episema.addAttribute("form", "horizontal")
                    local_horizontal_episema.addAttribute("startid", str(nt.id))
                    self.layer.addChild(local_horizontal_episema)

            if n == num_notes - 1 and local_horizontal_episema:
                # we've reached the end, and we have an HE we need to close up.
                local_horizontal_episema.addAttribute("endid", str(nt.id))

            nc.append(nt)

        for c in nc:
            neumecomponent.addChild(c)
        return neume

    def _create_note_element(self, pname=None):
        # note = mod.note_()
        note = MeiElement("note")
        # note.id = self._idgen()
        note.addAttribute("pname", str(pname))
        return note

    def _create_dot_element(self):
        # dot = mod.dot_()
        dot = MeiElement("dot")
        # dot.id = self._idgen()
        dot.addAttribute("form", "aug")
        return dot

    def _create_custos_element(self):
        custos = MeiElement("custos")
        # custos = mod.custos_()
        # custos.id = self._idgen()
        zone = self._create_zone_element()
        custos.facs = zone.id
        custos.addAttribute("pname", str(self.glyph['strt_pitch']))
        custos.addAttribute("oct", str(self.glyph['octv']))
        custos.addAttribute("facs", str(custos.facs))
        return custos

    def _create_clef_element(self):
        clef = MeiElement("clef")
        # clef = mod.clef_()
        # clef.id = self._idgen()
        zone = self._create_zone_element()
        clef.facs = zone.id
        clef.addAttribute("facs", str(clef.facs))

        # clef.attributes = {"line": self.glyph['strt_pos'], 'shape': self.glyph['form'][0].upper() }
        clef.addAttribute("line", str(self.glyph['strt_pos']))
        clef.addAttribute("shape", str(self.glyph['form'][0].upper()))
        lg.debug("clef:{0}".format(clef))
        return clef

    def _create_division_element(self):
        division = MeiElement("division")
        # division = mod.division_()
        # division.id = self._idgen()
        zone = self._create_zone_element()
        division.addAttribute("facs", str(zone.id))

        if self.glyph['form']:
            div = str(self.glyph['form'][0])
        else:
            div = "minor"

        division.addAttribute("form", div)
        return division

    def __parse_contour(self, form):
        # removes the contour indicator from the neume
        # and creates a neume form.
        if len(form) is 2 and (form.startswith("u") or form.startswith("d")):
            # do something
            return form[0]
        else:
            return None

    def __parse_steps(self, form):
        if len(form) is 2 and (form.startswith("u") or form.startswith("d")):
            return form[1]
        else:
            return None

    def __note_addition_figurer_outer(self, ntype, idxarray):
        for i,n in enumerate(self.glyph['form']):
            if n == ntype:
                j = copy.copy(i) - 1
                if j == 0:
                    idxarray.append(0)
                while j:
                    if self.__is_valid_note_indicator(self.glyph['form'][j]):
                        idxarray.append(j)
                        break
                    else:
                        j -= 1

    def __is_valid_note_indicator(self, form):
        # used to test if a form is a valid indicator of a note (and not a q, dot, or anything else)
        if form.isdigit():
            return True
        elif len(form) == 2 and form.startswith("u") or form.startswith("d"):
            return True
        else:
            return False
Beispiel #37
0
    def test_getroot(self):
        doc = MeiDocument()
        mei = MeiElement("mei")
        doc.root = mei

        self.assertEqual(mei, doc.root)
Beispiel #38
0
    def __init__(self, incoming_data, original_image, page_number=None):
        self._recognition_results = incoming_data
        # self.mei = mod.mei_()
        self.mei = MeiElement("mei")
        self.staff = None

        # Hack: I'm not sure what staff_num is. In any case it's strange to set it to None.
        # I therefore set it to 0 if page_number is None.
        if page_number is not None:
            self.staff_num = int(page_number)
        else:
            self.staff_num = 0
        self.glyph = None

        self._note_elements = None
        self._neume_pitches = []

        # set up a basic MEI document structure

        # header
        # self.meihead = mod.meiHead_()
        self.meihead = MeiElement("meiHead")
        # self.filedesc = mod.fileDesc_()
        self.filedesc = MeiElement("fileDesc")
        # self.titlestmt = mod.titleStmt_()
        self.titlestmt = MeiElement("titleStmt")
        # self.title = mod.title_()
        self.title = MeiElement("title")
        # self.pubstmt = mod.pubStmt_()
        self.pubstmt = MeiElement("pubStmt")

        self.titlestmt.addChild(self.title)

        self.filedesc.addChild(self.titlestmt)
        self.filedesc.addChild(self.pubstmt)

        self.meihead.addChild(self.filedesc)
        self.mei.addChild(self.meihead)

        # music
        # self.music = mod.music_()
        self.music = MeiElement("music")
        self.facsimile = self._create_facsimile_element()
        self.surface = self._create_surface_element()
        self.graphic = self._create_graphic_element(original_image)
        lg.debug("SELF GRAPHIC:{0}".format(XmlExport.meiElementToText(self.graphic)))

        self.surface.addChild(self.graphic)
        self.facsimile.addChild(self.surface)
        self.music.addChild(self.facsimile)

        self.layout = self._create_layout_element()
        self.pg = self._create_page_element()
        if page_number:
            # self.pg.attributes = {"n": page_number}
            self.pg.addAttribute("n", page_number)

        self.layout.addChild(self.pg)
        self.music.addChild(self.layout)

        # self.body = mod.body_()
        self.body = MeiElement("body")
        self.music.addChild(self.body)

        self.mdiv = MeiElement("mdiv")
        # self.mdiv = mod.mdiv_()
        self.mdiv.addAttribute("type", "solesmes")
        self.body.addChild(self.mdiv)

        # self.score = mod.score_()
        self.score = MeiElement("score")
        self.mdiv.addChild(self.score)

        # self.scoredef = mod.scoreDef_()
        self.scoredef = MeiElement("scoreDef")
        self.score.addChild(self.scoredef)

        # self.section = mod.section_()
        self.section = MeiElement("section")
        self.pagebreak = self._create_pb_element()
        # self.pagebreak.attributes = {"pageref": self.pg.id}
        self.pagebreak.addAttribute("pageref", self.pg.id)

        self.section.addChild(self.pagebreak)
        self.score.addChild(self.section)

        self.staffgrp = self._create_staffgrp_element()
        self.staffdef = self._create_staffdef_element()
        self.staffdef.addAttribute("n", str(self.staff_num))   # trouble

        self.staffgrp.addChild(self.staffdef)
        self.scoredef.addChild(self.staffgrp)

        self.layer = self._create_layer_element()
        self.layer.addAttribute("n", "1")

        self.staffel = self._create_staff_element()
        self.staffel.addAttribute("n", str(self.staff_num))   # trouble
        self.section.addChild(self.staffel)
        self.staffel.addChild(self.layer)

        for sysnum in sorted(self._recognition_results.keys()):
            syst = self._recognition_results[sysnum]
            lg.debug("sysnum:{0}".format(sysnum))
            self.system = syst
            self.systembreak = self._parse_system(sysnum, syst)
            # z = mod.zone_()
            z = MeiElement("zone")
            # z.id = self._idgen()
            # z.attributes = {'ulx': self.system['coord'][0], 'uly': self.system['coord'][1], \
            #                     'lrx': self.system['coord'][2], 'lry': self.system['coord'][3]}
            z.addAttribute("ulx", str(self.system['coord'][0]))
            z.addAttribute("uly", str(self.system['coord'][1]))
            z.addAttribute("lrx", str(self.system['coord'][2]))
            z.addAttribute("lry", str(self.system['coord'][3]))
            self.surface.addChild(z)
            # self.system.facs = z.id
            s = self._create_system_element()
            s.facs = z.id
            s.addAttribute("facs", s.facs)
            self.pg.addChild(s)
            self.systembreak.addAttribute("systemref", s.id)

        self.mei.addChild(self.music)

        # if not self.staffel.descendants_by_name('neume'):
        if not self.staffel.getDescendantsByName("neume"):
            self.staffgrp.removeChild(self.staffdef)
            self.section.removeChild(self.staffel)

        # self.md = MeiDocument.MeiDocument()
        # self.md.addelement(self.mei)
        self.md = MeiDocument()
        self.md.setRootElement(self.mei)
        print XmlExport.meiElementToText(self.md.getElementById(self.graphic.getId()))
Beispiel #39
0
class BarlineDataConverter:
    '''
    Convert the output of the barline detection algorithm
    to MEI.
    '''

    def __init__(self, staff_bb, bar_bb, verbose=False):
        '''
        Initialize the converter
        '''

        self.staff_bb = staff_bb
        self.bar_bb = bar_bb
        self.verbose = verbose

    def bardata_to_mei(self, sg_hint, image_path, image_width, image_height, image_dpi=72):
        '''
        Perform the data conversion to mei
        '''

        self.meidoc = MeiDocument()
        mei = MeiElement('mei')
        self.meidoc.setRootElement(mei)

        ###########################
        #         MetaData        #
        ###########################
        mei_head = self._create_header()
        mei.addChild(mei_head)

        ###########################
        #           Body          #
        ###########################
        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')
        section = MeiElement('section')

        # physical location data
        facsimile = MeiElement('facsimile')
        surface = MeiElement('surface')

        graphic = self._create_graphic(image_path, image_width, image_height)
        surface.addChild(graphic)

        # parse staff group hint to generate staff group
        sg_hint = sg_hint.split(" ")
        systems = []
        for s in sg_hint:
            parser = nestedExpr()
            sg_list = parser.parseString(s).asList()[0]
            staff_grp, n = self._create_staff_group(sg_list, MeiElement('staffGrp'), 0)

            # parse repeating staff groups (systems)
            num_sb = 1
            match = re.search('(?<=x)(\d+)$', s)
            if match is not None:
                # there are multiple systems of this staff grouping
                num_sb = int(match.group(0))

            for i in range(num_sb):
                systems.append(staff_grp)

            if self.verbose:
                print "number of staves in system: %d x %d system(s)" % (n, num_sb)

        # there may be hidden staves in a system
        # make the encoded staff group the largest number of staves in a system
        final_staff_grp = max(systems, key=lambda x: len(x.getDescendantsByName('staffDef')))

        mei.addChild(music)
        music.addChild(facsimile)
        facsimile.addChild(surface)

        # list of staff bounding boxes within a system
        staves = []
        for staff_bb in self.staff_bb:
            # get bounding box of the staff
            # parse bounding box integers
            #staff_bb = [int(x) for x in staff_bb]
            staves.append(staff_bb[1:])

        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(final_staff_grp)
        score.addChild(section)

        # parse barline data file [staffnum][barlinenum_ulx]
        barlines = []
        for i, bar in enumerate(self.bar_bb):
            staff_num = int(bar[0])
            ulx = bar[1]
            try:
                barlines[staff_num - 1].append(ulx)
            except IndexError:
                barlines.append([ulx])

        staff_offset = 0
        n_measure = 1
        b1_thresh = 1.25
        bn_thresh = 1.25
        # for each system
        for s_ind, s in enumerate(systems):
            # measures in a system
            s_measures = []
            staff_defs = s.getDescendantsByName('staffDef')
            # for each staff in the system
            for i in range(len(staff_defs)):
                staff_num = staff_offset + i
                s_bb = staves[staff_num]
                # bounding box of the staff
                s_ulx = s_bb[0]
                s_uly = s_bb[1]
                s_lrx = s_bb[2]
                s_lry = s_bb[3]

                # for each barline on this staff
                try:
                    staff_bars = barlines[staff_num]
                except IndexError:
                    # a staff was found, but no bar candidates have been found on the staff
                    continue

                # check the first barline candidate
                # If it is sufficiently close to the beginning of the staff then ignore it.
                b1_x = staff_bars[0]
                if abs(b1_x / image_dpi - s_ulx / image_dpi) < b1_thresh:
                    del staff_bars[0]

                # check the last barline candidate
                # if there is no candidate near the end of the interior of the staff, add one
                bn_x = staff_bars[-1]
                if bn_x < s_lrx and abs(bn_x / image_dpi - s_lrx / image_dpi) > bn_thresh:
                    staff_bars.append(s_lrx)

                for n, b in enumerate(staff_bars):
                    # calculate bounding box of the measure
                    m_uly = s_uly
                    m_lry = s_lry

                    m_lrx = b
                    if n == len(staff_bars) - 1:
                        m_lrx = s_lrx

                    if n == 0:
                        m_ulx = s_ulx
                    else:
                        m_ulx = staff_bars[n - 1]

                    # create staff element
                    zone = self._create_zone(m_ulx, m_uly, m_lrx, m_lry)
                    surface.addChild(zone)
                    if len(sg_hint) == 1 or len(staff_defs) == len(final_staff_grp.getDescendantsByName('staffDef')):
                        staff_n = str(i + 1)
                    else:
                        # take into consideration hidden staves
                        staff_n = i + self._calc_staff_num(len(staff_defs), [final_staff_grp])

                    staff = self._create_staff(staff_n, zone)

                    try:
                        s_measures[n].addChild(staff)
                    except IndexError:
                        # create a new measure
                        measure = self._create_measure(str(n_measure))
                        s_measures.append(measure)
                        section.addChild(measure)
                        measure.addChild(staff)
                        n_measure += 1

            # calculate min/max of measure/staff bounding boxes to get measure zone
            self._calc_measure_zone(s_measures)

            staff_offset += len(staff_defs)

            # add a system break, if necessary
            if s_ind + 1 < len(systems):
                sb = MeiElement('sb')
                section.addChild(sb)

    def _calc_staff_num(self, num_staves, staff_grps):
        '''
        In the case where there are hidden staves,
        search for the correct staff number within the staff
        group definition.
        '''

        if len(staff_grps) == 0:
            # termination condition (or no match found)
            return 0
        else:
            sg_staves = staff_grps[0].getChildrenByName('staffDef')
            sgs = staff_grps[0].getChildrenByName('staffGrp')
            if num_staves == len(sg_staves):
                # no need to look at subsequent staff groups
                n = int(sg_staves[0].getAttribute('n').value)
            else:
                n = self._calc_staff_num(num_staves, sgs)

            return n + self._calc_staff_num(num_staves, staff_grps[1:])

    def _calc_measure_zone(self, measures):
        '''
        Calculate the bounding box of the provided measures
        by calculating the min and max of the bounding boxes
        of the staves which compose the measure.
        '''

        # for each measure
        for m in measures:
            min_ulx = sys.maxint
            min_uly = sys.maxint
            max_lrx = -sys.maxint - 1
            max_lry = -sys.maxint - 1
            for s in m.getChildrenByName('staff'):
                # have to skip # at the beginning of the id ref since using URIs
                s_zone = self.meidoc.getElementById(s.getAttribute('facs').value[1:])
                ulx = int(s_zone.getAttribute('ulx').value)
                if ulx < min_ulx:
                    min_ulx = ulx

                uly = int(s_zone.getAttribute('uly').value)
                if uly < min_uly:
                    min_uly = uly

                lrx = int(s_zone.getAttribute('lrx').value)
                if lrx > max_lrx:
                    max_lrx = lrx

                lry = int(s_zone.getAttribute('lry').value)
                if lry > max_lry:
                    max_lry = lry

            m_zone = self._create_zone(min_ulx, min_uly, max_lrx, max_lry)
            m.addAttribute('facs', '#' + m_zone.getId())
            surface = self.meidoc.getElementsByName('surface')[0]
            surface.addChild(m_zone)

    def _create_header(self, rodan_version='0.1'):
        '''
        Create a meiHead element
        '''

        mei_head = MeiElement('meiHead')
        today = datetime.date.today().isoformat()

        app_name = 'RODAN/barlineFinder'

        # file description
        file_desc = MeiElement('fileDesc')

        title_stmt = MeiElement('titleStmt')
        title = MeiElement('title')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        title_stmt.addChild(title)
        title_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)

        pub_stmt = MeiElement('pubStmt')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        pub_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)

        mei_head.addChild(file_desc)
        file_desc.addChild(title_stmt)
        file_desc.addChild(pub_stmt)

        # encoding description
        encoding_desc = MeiElement('encodingDesc')
        app_info = MeiElement('appInfo')
        application = MeiElement('application')
        application.addAttribute('version', rodan_version)
        name = MeiElement('name')
        name.setValue(app_name)
        ptr = MeiElement('ptr')
        ptr.addAttribute('target', 'https://github.com/DDMAL/barlineFinder')

        mei_head.addChild(encoding_desc)
        encoding_desc.addChild(app_info)
        app_info.addChild(application)
        application.addChild(name)
        application.addChild(ptr)

        # revision description
        revision_desc = MeiElement('revisionDesc')
        change = MeiElement('change')
        change.addAttribute('n', '1')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        change_desc = MeiElement('changeDesc')
        ref = MeiElement('ref')
        ref.addAttribute('target', '#' + application.getId())
        ref.setValue(app_name)
        ref.setTail('.')
        p = MeiElement('p')
        p.addChild(ref)
        p.setValue('Encoded using ')
        date = MeiElement('date')
        date.setValue(today)

        mei_head.addChild(revision_desc)
        revision_desc.addChild(change)
        change.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        change.addChild(change_desc)
        change_desc.addChild(p)
        change.addChild(date)

        return mei_head

    def _create_graphic(self, image_path, image_width, image_height):
        '''
        Create a graphic element.
        '''

        graphic = MeiElement('graphic')
        graphic.addAttribute('height', str(image_height))
        graphic.addAttribute('width', str(image_width))
        graphic.addAttribute('target', str(image_path))
        graphic.addAttribute('unit', 'px')

        return graphic

    def _create_staff_group(self, sg_list, staff_grp, n):
        '''
        Recursively create the staff group element from the parsed
        user input of the staff groupings
        '''
        if not sg_list:
            return staff_grp, n
        else:
            if type(sg_list[0]) is list:
                new_staff_grp, n = self._create_staff_group(sg_list[0], MeiElement('staffGrp'), n)
                staff_grp.addChild(new_staff_grp)
            else:
                # check for barthrough character
                if sg_list[0][-1] == '|':
                    # the barlines go through all the staves in the staff group
                    staff_grp.addAttribute('barthru', 'true')
                    # remove the barthrough character, should now only be an integer
                    sg_list[0] = sg_list[0][:-1]

                n_staff_defs = int(sg_list[0])
                # get current staffDef number
                for i in range(n_staff_defs):
                    staff_def = MeiElement('staffDef')
                    staff_def.addAttribute('n', str(n + i + 1))
                    staff_def.addAttribute('lines', '5')
                    staff_grp.addChild(staff_def)
                n += n_staff_defs

            return self._create_staff_group(sg_list[1:], staff_grp, n)

    def _create_staff(self, n, zone):
        '''
        Create a staff element, and attach a zone reference to it
        '''

        staff = MeiElement('staff')
        staff.addAttribute('n', str(n))
        staff.addAttribute('facs', '#' + zone.getId())

        return staff

    def _create_measure(self, n, zone=None):
        '''
        Create a measure element and attach a zone reference to it.
        The zone element is optional, since the zone of the measure is
        calculated once all of the staves within a measure have been added
        to the MEI.
        '''

        measure = MeiElement('measure')
        measure.addAttribute('n', str(n))

        if zone is not None:
            measure.addAttribute('facs', '#' + zone.getId())

        return measure

    def _create_zone(self, ulx, uly, lrx, lry):
        '''
        Create a zone element
        '''

        zone = MeiElement('zone')
        zone.addAttribute('ulx', str(ulx))
        zone.addAttribute('uly', str(uly))
        zone.addAttribute('lrx', str(lrx))
        zone.addAttribute('lry', str(lry))

        return zone

    def output_mei(self, output_path):
        '''
        Write the generated mei to disk
        '''

        # output mei file
        XmlExport.meiDocumentToFile(self.meidoc, output_path)

    def get_wrapped_mei(self):
        '''
        Return the generated mei document
        '''

        mw = MeiWrapper(self.meidoc)

        return mw
Beispiel #40
0
class AomrMeiOutput(object):
    # define the form of a neume.
    # form: [ num, interval_dir... ]
    # e.g., clivis: [2, 'd']
    # torculus: [3, 'u', 'd']
    NEUME_NOTES = {
        'punctum': [],
        'virga': [],
        'cephalicus': ['d'],
        'clivis': ['d'],
        'epiphonus': ['u'],
        'podatus': ['u'],
        'porrectus': ['d', 'u'],
        'salicus': ['u', 'u'],
        'scandicus': ['u', 'u'],
        'torculus': ['u', 'd'],
        'ancus': ['d', 'd'],  # See note 1 below
    }

    # given an alternate form, how many notes does it add to the neume?
    ADD_NOTES = {
        'flexus': ['d'],  # scandicus.flexus, porrectus.flexus
        'resupinus': ['u'],  # torculus.resupinus
    }

    SCALE = ['a', 'b', 'c', 'd', 'e', 'f', 'g']

    def __init__(self, incoming_data, original_image, page_number=None):
        self._recognition_results = incoming_data
        # self.mei = mod.mei_()
        self.mei = MeiElement("mei")
        self.staff = None

        # Hack: I'm not sure what staff_num is. In any case it's strange to set it to None.
        # I therefore set it to 0 if page_number is None.
        if page_number is not None:
            self.staff_num = int(page_number)
        else:
            self.staff_num = 0
        self.glyph = None

        self._note_elements = None
        self._neume_pitches = []

        # set up a basic MEI document structure

        # header
        # self.meihead = mod.meiHead_()
        self.meihead = MeiElement("meiHead")
        # self.filedesc = mod.fileDesc_()
        self.filedesc = MeiElement("fileDesc")
        # self.titlestmt = mod.titleStmt_()
        self.titlestmt = MeiElement("titleStmt")
        # self.title = mod.title_()
        self.title = MeiElement("title")
        # self.pubstmt = mod.pubStmt_()
        self.pubstmt = MeiElement("pubStmt")

        self.titlestmt.addChild(self.title)

        self.filedesc.addChild(self.titlestmt)
        self.filedesc.addChild(self.pubstmt)

        self.meihead.addChild(self.filedesc)
        self.mei.addChild(self.meihead)

        # music
        # self.music = mod.music_()
        self.music = MeiElement("music")
        self.facsimile = self._create_facsimile_element()
        self.surface = self._create_surface_element()
        self.graphic = self._create_graphic_element(original_image)
        lg.debug("SELF GRAPHIC:{0}".format(
            XmlExport.meiElementToText(self.graphic)))

        self.surface.addChild(self.graphic)
        self.facsimile.addChild(self.surface)
        self.music.addChild(self.facsimile)

        self.layout = self._create_layout_element()
        self.pg = self._create_page_element()
        if page_number:
            # self.pg.attributes = {"n": page_number}
            self.pg.addAttribute("n", page_number)

        self.layout.addChild(self.pg)
        self.music.addChild(self.layout)

        # self.body = mod.body_()
        self.body = MeiElement("body")
        self.music.addChild(self.body)

        self.mdiv = MeiElement("mdiv")
        # self.mdiv = mod.mdiv_()
        self.mdiv.addAttribute("type", "solesmes")
        self.body.addChild(self.mdiv)

        # self.score = mod.score_()
        self.score = MeiElement("score")
        self.mdiv.addChild(self.score)

        # self.scoredef = mod.scoreDef_()
        self.scoredef = MeiElement("scoreDef")
        self.score.addChild(self.scoredef)

        # self.section = mod.section_()
        self.section = MeiElement("section")
        self.pagebreak = self._create_pb_element()
        # self.pagebreak.attributes = {"pageref": self.pg.id}
        self.pagebreak.addAttribute("pageref", self.pg.id)

        self.section.addChild(self.pagebreak)
        self.score.addChild(self.section)

        self.staffgrp = self._create_staffgrp_element()
        self.staffdef = self._create_staffdef_element()
        self.staffdef.addAttribute("n", str(self.staff_num))  # trouble

        self.staffgrp.addChild(self.staffdef)
        self.scoredef.addChild(self.staffgrp)

        self.layer = self._create_layer_element()
        self.layer.addAttribute("n", "1")

        self.staffel = self._create_staff_element()
        self.staffel.addAttribute("n", str(self.staff_num))  # trouble
        self.section.addChild(self.staffel)
        self.staffel.addChild(self.layer)

        for sysnum in sorted(self._recognition_results.keys()):
            syst = self._recognition_results[sysnum]
            lg.debug("sysnum:{0}".format(sysnum))
            self.system = syst
            self.systembreak = self._parse_system(sysnum, syst)
            # z = mod.zone_()
            z = MeiElement("zone")
            # z.id = self._idgen()
            # z.attributes = {'ulx': self.system['coord'][0], 'uly': self.system['coord'][1], \
            #                     'lrx': self.system['coord'][2], 'lry': self.system['coord'][3]}
            z.addAttribute("ulx", str(self.system['coord'][0]))
            z.addAttribute("uly", str(self.system['coord'][1]))
            z.addAttribute("lrx", str(self.system['coord'][2]))
            z.addAttribute("lry", str(self.system['coord'][3]))
            self.surface.addChild(z)
            # self.system.facs = z.id
            s = self._create_system_element()
            s.facs = z.id
            s.addAttribute("facs", s.facs)
            self.pg.addChild(s)
            self.systembreak.addAttribute("systemref", s.id)

        self.mei.addChild(self.music)

        # if not self.staffel.descendants_by_name('neume'):
        if not self.staffel.getDescendantsByName("neume"):
            self.staffgrp.removeChild(self.staffdef)
            self.section.removeChild(self.staffel)

        # self.md = MeiDocument.MeiDocument()
        # self.md.addelement(self.mei)
        self.md = MeiDocument()
        self.md.setRootElement(self.mei)
        print XmlExport.meiElementToText(
            self.md.getElementById(self.graphic.getId()))

    def _parse_system(self, sysnum, syst):
        sysbrk = self._create_sb_element()
        # sysbrk.attributes = {"n": sysnum + 1}
        sysnum = int(sysnum)
        sysbrk.addAttribute("n", "%d" % (sysnum + 1))
        self.layer.addChild(sysbrk)
        # staffel = self._create_staff_element()
        # staffel.addAttribute("n", stfnum)

        for c in self.system['content']:
            # parse the glyphs per staff.
            self.glyph = c
            if c['type'] == 'neume':
                if not self.glyph['form']:
                    lg.debug("Skipping glyph: {0}".format(self.glyph))
                    continue
                if self.glyph['form'][0] not in self.NEUME_NOTES.keys():
                    continue
                else:
                    self.layer.addChild(self._create_neume_element())

            elif c['type'] == 'clef':
                self.layer.addChild(self._create_clef_element())
            elif c['type'] == 'division':
                self.layer.addChild(self._create_division_element())
                if "final" in c['form']:
                    self.staff_num += 1
                    new_staff = self._create_staff_element()
                    new_staffdef = self._create_staffdef_element()
                    # new_staffdef.attributes = {'n': self.staff_num} TROUBLE
                    new_staffdef.addAttribute('n', str(self.staff_num))
                    # new_staff.attributes = {'n': self.staff_num} TROUBLE
                    new_staff.addAttribute('n', str(self.staff_num))
                    new_layer = self._create_layer_element()
                    # new_layer.attributes = {'n': 1} TROUBLE
                    new_layer.addAttribute('n', str(1))
                    self.layer = new_layer
                    self.staffel = new_staff
                    self.staffdef = new_staffdef
                    self.staffgrp.addChild(self.staffdef)
                    self.staffel.addChild(self.layer)
                    self.section.addChild(self.staffel)

            elif c['type'] == 'custos':
                self.layer.addChild(self._create_custos_element())

            elif c['type'] == "alteration":
                # staffel.addChild(self._create_alteration_element()) #GVM_OLD
                pass
        return sysbrk

    def _create_graphic_element(self, imgfile):
        graphic = MeiElement("graphic")
        # xlink = MeiNamespace("xlink", "http://www.w3.org/1999/xlink")
        # ns_attr = MeiAttribute("xlink")
        graphic.addAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink")
        graphic.addAttribute("xlink:href", imgfile)
        return graphic

    def _create_alteration_element(self):
        # accid = mod.accid_()
        accid = MeiElement("accid")
        accid.id = self._idgen()
        if self.glyph['form'] is "sharp":
            accid.addAttribute("accid", "s")
        elif self.glyph['form'] is "flat":
            accid.addAttribute("accid", "f")

        # zone = self._create_zone_element()
        # note.facs = zone.id
        return accid

    def _create_surface_element(self):
        # surface = mod.surface_()
        surface = MeiElement("surface")
        return surface

    def _create_facsimile_element(self):
        # facsimile = mod.facsimile_()
        facsimile = MeiElement("facsimile")
        # facsimile.id = self._idgen()
        return facsimile

    def _create_zone_element(self):
        zone = MeiElement("zone")
        # zone = mod.zone_()
        # zone.id = self._idgen()
        # zone.attributes = {'ulx': self.glyph['coord'][0], 'uly': self.glyph['coord'][1], \
        #                     'lrx': self.glyph['coord'][2], 'lry': self.glyph['coord'][3]}

        zone.addAttribute("ulx", str(self.glyph['coord'][0]))
        zone.addAttribute("uly", str(self.glyph['coord'][1]))
        zone.addAttribute("lrx", str(self.glyph['coord'][2]))
        zone.addAttribute("lry", str(self.glyph['coord'][3]))
        self.surface.addChild(zone)
        return zone

    def _create_layer_element(self):
        layer = MeiElement("layer")
        # layer = mod.layer_()
        # layer.id = self._idgen()
        lg.debug("layer:{0}".format(layer))
        return layer

    def _create_staffgrp_element(self):
        # stfgrp = mod.staffGrp_()
        stfgrp = MeiElement("staffGrp")
        # stfgrp.id = self._idgen()
        return stfgrp

    def _create_staffdef_element(self):
        stfdef = MeiElement("staffDef")
        # stfdef = mod.staffDef_()
        # stfdef.id = self._idgen()
        return stfdef

    def _create_staff_element(self):
        # staff = mod.staff_()
        staff = MeiElement("staff")
        # staff.id = self._idgen()
        return staff

    def _create_sb_element(self):
        sb = MeiElement("sb")
        # sb = mod.sb_()
        # sb.id = self._idgen()
        return sb

    def _create_pb_element(self):
        # pb = mod.pb_()
        pb = MeiElement("pb")
        # pb.id = self._idgen()
        return pb

    def _create_layout_element(self):
        layout = MeiElement("layout")  # GVM_FIXED
        return layout

    def _create_page_element(self):
        page = MeiElement("page")  # FIXED?
        # page = mod.page_()
        # page.id = self._idgen()
        return page

    def _create_system_element(self):
        system = MeiElement("system")  # FIXED?
        # system = mod.system_()
        # system.id = self._idgen()
        return system

    def _create_episema_element(self):
        epi = MeiElement("episema")
        # epi = mod.episema_()
        # epi.id = self._idgen()
        return epi

    def _create_neume_element(self):
        full_width_episema = False
        has_dot = False
        has_vertical_episema = False
        has_horizontal_episema = False
        has_quilisma = False
        this_neume_form = None
        local_horizontal_episema = None

        start_octave = self.glyph['octv']
        clef_pos = self.glyph['clef_pos']
        clef_type = self.glyph['clef'].split(".")[-1]  # f or c.

        # neume = mod.neume_()
        neume = MeiElement("neume")  # CHECK!
        # neume.id = self._idgen()
        zone = self._create_zone_element()
        neume.facs = zone.id
        neume.addAttribute("facs", neume.facs)

        # neumecomponent = mod.nc_()
        neumecomponent = MeiElement("nc")  # CHECK!
        # neumecomponent.id = self._idgen()
        neume.addChild(neumecomponent)
        if self.glyph['form'][0] == "he":
            full_width_episema = True
            del self.glyph['form'][0]

        # we've removed any global he's, so
        # any leftovers should be local.
        if 'he' in self.glyph['form']:
            has_horizontal_episema = True

        if 'dot' in self.glyph['form']:
            has_dot = True

        if 'q' in self.glyph['form']:
            has_quilisma = True

        if 've' in self.glyph['form']:
            has_vertical_episema = True

        if 'inclinatum' in self.glyph['form']:
            # neumecomponent.attributes = {'inclinatum': 'true'}
            neumecomponent.addAttribute("inclinatum", "true")

        # neume.attributes = {'name': self.glyph['form'][0]}
        neume.addAttribute("name", str(self.glyph['form'][0]))

        if 'compound' in self.glyph['form']:
            # do something and create a new set of pitch contours
            this_neume_form = [
                y for y in (self.__parse_contour(n)
                            for n in self.glyph['form']) if y
            ]
            self._note_elements = [
                y for y in (self.__parse_steps(n) for n in self.glyph['form'])
                if y
            ]
        else:
            this_neume_form = copy.deepcopy(
                self.NEUME_NOTES[self.glyph['form'][0]])
            self._note_elements = self.glyph['form'][1:]
        # get the form so we can find the number of notes we need to construct.

        num_notes = len(this_neume_form) + 1
        # we don't have an off-by-one problem here, since an added interval means an added note
        check_additional = [
            i for i in self.ADD_NOTES.keys() if i in self.glyph['form'][1:]
        ]
        if check_additional:
            for f in check_additional:
                this_neume_form.extend(self.ADD_NOTES[f])

                ## THIS SHOULD BE CHANGED. Otherwise we may end up with two attributes with the
                # same name.
                neume.addAttribute("variant", str(f))

            num_notes = num_notes + len(check_additional)

        self._neume_pitches = []
        # note elements are everything after the first form. This determines the shape a note takes.
        self._neume_pitches.append(self.glyph['strt_pitch'])
        nc = []
        note_octaves = [start_octave]
        if num_notes > 1:
            # we need to figure out the rest of the pitches in the neume.
            ivals = [int(d) for d in self._note_elements if d.isdigit()]
            idx = self.SCALE.index(self.glyph['strt_pitch'])

            if len(ivals) != (num_notes - 1):
                if 'scandicus' in self.glyph['form']:
                    diffr = abs(len(ivals) - (num_notes - 1))
                    num_notes = num_notes + diffr
                    this_neume_form.extend(diffr * 'u')
                else:
                    raise AomrMeiNoteIntervalMismatchError(
                        "There is a mismatch between the number of notes and number of intervals."
                    )

            # note elements = torculus.2.2.he.ve
            # ivals = [2,2]
            # torculus = ['u','d']
            this_pos = copy.deepcopy(self.glyph['strt_pos'])
            for n in xrange(len(ivals)):
                # get the direction
                dir = this_neume_form[n]
                iv = ivals[n]
                n_idx = idx
                if dir == "u":
                    n_idx = ((idx + iv) % len(self.SCALE)) - 1
                    this_pos -= (iv - 1)
                elif dir == "d":
                    n_idx = idx - (iv - 1)
                    this_pos += (iv - 1)
                    if n_idx < 0:
                        n_idx += len(self.SCALE)
                idx = n_idx
                self._neume_pitches.append(self.SCALE[n_idx])

                actual_line = 10 - (2 * (clef_pos - 1))

                if clef_type:
                    if this_pos <= actual_line:
                        note_octaves.append(4)
                    elif this_pos > actual_line + 7:
                        note_octaves.append(2)
                    else:
                        note_octaves.append(3)
                # elif clef_type == "f":
                #     if (actual_line + 3) >= this_pos > (actual_line - 3):
                #         note_octaves.append(3)
                #     elif this_pos < (actual_line - 3):
                #         note_octaves.append(4)
                #     elif this_pos > (actual_line + 3):
                #         note_octaves.append(2)

        if full_width_episema is True:
            epi = self._create_episema_element()
            # epi.attributes = {"form": "horizontal"} TROUBLE
            epi.addAttribute("form", "horizontal")
            self.layer.addChild(epi)

        qidxs = []
        if has_quilisma:
            self.__note_addition_figurer_outer("q", qidxs)

        dotidxs = []
        if has_dot:
            self.__note_addition_figurer_outer("dot", dotidxs)

        veidxs = []
        if has_vertical_episema:
            self.__note_addition_figurer_outer("ve", veidxs)

        heidxs = []
        if has_horizontal_episema:
            self.__note_addition_figurer_outer("he", heidxs)

        for n in xrange(num_notes):
            p = self._neume_pitches[n]
            o = note_octaves[n]
            # lg.debug("n:{0}, p:{1}, o:{2}".format(n, p, o))
            nt = self._create_note_element(p)
            nt.addAttribute("oct", str(o))
            # lg.debug("nt.pitchname:{0}".format(nt.pname))
            if n == 0 and full_width_episema is True:
                epi.addAttribute("startid", str(nt.id))
            elif n == num_notes and full_width_episema is True:
                epi.addAttribute("endid", str(nt.id))

            if has_quilisma:
                if n in qidxs:
                    neumecomponent.addAttribute("quilisma", "true")

            if has_dot:
                if n in dotidxs:
                    d = self._create_dot_element()
                    nt.addChild(d)

            if has_vertical_episema:
                if n in veidxs:
                    ep = self._create_episema_element()
                    ep.addAttribute("form", "vertical")
                    ep.addAttribute("startid", str(nt.id))
                    self.layer.addChild(ep)

            if has_horizontal_episema:
                if n in heidxs:
                    local_horizontal_episema = self._create_episema_element()
                    local_horizontal_episema.addAttribute("form", "horizontal")
                    local_horizontal_episema.addAttribute(
                        "startid", str(nt.id))
                    self.layer.addChild(local_horizontal_episema)

            if n == num_notes - 1 and local_horizontal_episema:
                # we've reached the end, and we have an HE we need to close up.
                local_horizontal_episema.addAttribute("endid", str(nt.id))

            nc.append(nt)

        for c in nc:
            neumecomponent.addChild(c)
        return neume

    def _create_note_element(self, pname=None):
        # note = mod.note_()
        note = MeiElement("note")
        # note.id = self._idgen()
        note.addAttribute("pname", str(pname))
        return note

    def _create_dot_element(self):
        # dot = mod.dot_()
        dot = MeiElement("dot")
        # dot.id = self._idgen()
        dot.addAttribute("form", "aug")
        return dot

    def _create_custos_element(self):
        custos = MeiElement("custos")
        # custos = mod.custos_()
        # custos.id = self._idgen()
        zone = self._create_zone_element()
        custos.facs = zone.id
        custos.addAttribute("pname", str(self.glyph['strt_pitch']))
        custos.addAttribute("oct", str(self.glyph['octv']))
        custos.addAttribute("facs", str(custos.facs))
        return custos

    def _create_clef_element(self):
        clef = MeiElement("clef")
        # clef = mod.clef_()
        # clef.id = self._idgen()
        zone = self._create_zone_element()
        clef.facs = zone.id
        clef.addAttribute("facs", str(clef.facs))

        # clef.attributes = {"line": self.glyph['strt_pos'], 'shape': self.glyph['form'][0].upper() }
        clef.addAttribute("line", str(self.glyph['strt_pos']))
        clef.addAttribute("shape", str(self.glyph['form'][0].upper()))
        lg.debug("clef:{0}".format(clef))
        return clef

    def _create_division_element(self):
        division = MeiElement("division")
        # division = mod.division_()
        # division.id = self._idgen()
        zone = self._create_zone_element()
        division.addAttribute("facs", str(zone.id))

        if self.glyph['form']:
            div = str(self.glyph['form'][0])
        else:
            div = "minor"

        division.addAttribute("form", div)
        return division

    def __parse_contour(self, form):
        # removes the contour indicator from the neume
        # and creates a neume form.
        if len(form) is 2 and (form.startswith("u") or form.startswith("d")):
            # do something
            return form[0]
        else:
            return None

    def __parse_steps(self, form):
        if len(form) is 2 and (form.startswith("u") or form.startswith("d")):
            return form[1]
        else:
            return None

    def __note_addition_figurer_outer(self, ntype, idxarray):
        for i, n in enumerate(self.glyph['form']):
            if n == ntype:
                j = copy.copy(i) - 1
                if j == 0:
                    idxarray.append(0)
                while j:
                    if self.__is_valid_note_indicator(self.glyph['form'][j]):
                        idxarray.append(j)
                        break
                    else:
                        j -= 1

    def __is_valid_note_indicator(self, form):
        # used to test if a form is a valid indicator of a note (and not a q, dot, or anything else)
        if form.isdigit():
            return True
        elif len(form) == 2 and form.startswith("u") or form.startswith("d"):
            return True
        else:
            return False
Beispiel #41
0
class BarlineDataConverter:
    '''
    Convert the output of the barline detection algorithm
    to MEI.
    '''

    def __init__(self, staff_bb, bar_bb, verbose):
        '''
        Initialize the converter
        '''

        self.staff_bb = staff_bb
        self.bar_bb = bar_bb
        self.verbose = verbose

    def bardata_to_mei(self, sg_hint, image_path, image_width, image_height, image_dpi):
        '''
        Perform the data conversion to mei
        '''

        self.meidoc = MeiDocument()
        mei = MeiElement('mei')
        self.meidoc.setRootElement(mei)

        ###########################
        #         MetaData        #
        ###########################
        mei_head = self._create_header()
        mei.addChild(mei_head)

        ###########################
        #           Body          #
        ###########################
        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')
        section = MeiElement('section')

        # physical location data
        facsimile = MeiElement('facsimile')
        surface = MeiElement('surface')

        graphic = self._create_graphic(image_path, image_width, image_height)
        surface.addChild(graphic)

        # parse staff group hint to generate staff group
        sg_hint = sg_hint.split(" ")
        systems = []
        for s in sg_hint:
            parser = nestedExpr()
            sg_list = parser.parseString(s).asList()[0]
            staff_grp, n = self._create_staff_group(sg_list, MeiElement('staffGrp'), 0)

            # parse repeating staff groups (systems)
            num_sb = 1
            match = re.search('(?<=x)(\d+)$', s)
            if match is not None:
                # there are multiple systems of this staff grouping
                num_sb = int(match.group(0))
            
            for i in range(num_sb):
                systems.append(staff_grp)

            if self.verbose:
                print "number of staves in system: %d x %d system(s)" % (n, num_sb)

        # there may be hidden staves in a system
        # make the encoded staff group the largest number of staves in a system
        final_staff_grp = max(systems, key=lambda x: len(x.getDescendantsByName('staffDef')))

        mei.addChild(music)
        music.addChild(facsimile)
        facsimile.addChild(surface)
        
        # list of staff bounding boxes within a system
        staves = []
        for staff_bb in self.staff_bb:
            # get bounding box of the staff
            # parse bounding box integers
            #staff_bb = [int(x) for x in staff_bb]
            staves.append(staff_bb[1:])
        
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(final_staff_grp)
        score.addChild(section)

        # parse barline data file [staffnum][barlinenum_ulx]
        barlines = []
        for i, bar in enumerate(self.bar_bb):
            staff_num = int(bar[0])
            ulx = bar[1]
            try:
                barlines[staff_num-1].append(ulx)
            except IndexError:
                barlines.append([ulx])

        staff_offset = 0
        n_measure = 1
        for s_ind, s in enumerate(systems):
            # measures in a system
            s_measures = []
            staff_defs = s.getDescendantsByName('staffDef')
            # for each staff in the system
            for i in range(len(staff_defs)):
                staff_num = staff_offset + i
                s_bb = staves[staff_num]
                # bounding box of the staff
                s_ulx = s_bb[0]
                s_uly = s_bb[1]
                s_lrx = s_bb[2]
                s_lry = s_bb[3]

                # for each barline on this staff
                try:
                    staff_bars = barlines[staff_num]
                except IndexError:
                    # a staff was found, but no bar candidates have been found on the staff
                    continue

                # for each barline on this staff
                for n, b in enumerate(staff_bars[:-1]):
                    # calculate bounding box of the measure
                    m_uly = s_uly
                    m_lry = s_lry
                    m_ulx = b
                    m_lrx = staff_bars[n+1]

                    zone = self._create_zone(m_ulx, m_uly, m_lrx, m_lry)
                    surface.addChild(zone)
                    if len(sg_hint) == 1 or len(staff_defs) == len(final_staff_grp.getDescendantsByName('staffDef')):
                        staff_n = str(i+1)    
                    else:
                        # take into consideration hidden staves
                        staff_n = i + self._calc_staff_num(len(staff_defs), [final_staff_grp]) + 1
                    
                    staff = self._create_staff(staff_n, zone)
                    #print '  ', staff_n, m_ulx, m_uly, m_lrx, m_lry
                    try:
                        s_measures[n].addChild(staff)
                    except IndexError:
                        # create a new measure
                        measure = self._create_measure(str(n_measure))
                        s_measures.append(measure)
                        section.addChild(measure)
                        measure.addChild(staff)
                        n_measure += 1

            # calculate min/max of measure/staff bounding boxes to get measure zone
            self._calc_measure_zone(s_measures)

            staff_offset += len(staff_defs)

            # add a system break, if necessary
            if s_ind+1 < len(systems):
                sb = MeiElement('sb')
                section.addChild(sb)

    def _calc_staff_num(self, num_staves, staff_grps):
        '''
        In the case where there are hidden staves,
        search for the correct staff number within the staff
        group definition.
        '''

        if len(staff_grps) == 0:
            # termination condition (or no match found)
            return 0
        else:
            sg_staves = staff_grps[0].getChildrenByName('staffDef')
            sgs = staff_grps[0].getChildrenByName('staffGrp')
            if num_staves == len(sg_staves):
                # no need to look at subsequent staff groups
                n = int(sg_staves[0].getAttribute('n').value)
            else:
                n = self._calc_staff_num(num_staves, sgs)

            return n + self._calc_staff_num(num_staves, staff_grps[1:])
        
    def _calc_measure_zone(self, measures):
        '''
        Calculate the bounding box of the provided measures
        by calculating the min and max of the bounding boxes
        of the staves which compose the measure.
        '''

        # for each measure
        for m in measures:
            staff_measure_zones = []
            min_ulx = sys.maxint
            min_uly = sys.maxint
            max_lrx = -sys.maxint - 1
            max_lry = -sys.maxint - 1
            for s in m.getChildrenByName('staff'):
                # have to skip # at the beginning of the id ref since using URIs
                s_zone = self.meidoc.getElementById(s.getAttribute('facs').value[1:])
                ulx = int(s_zone.getAttribute('ulx').value)
                if ulx < min_ulx:
                    min_ulx = ulx

                uly = int(s_zone.getAttribute('uly').value)
                if uly < min_uly:
                    min_uly = uly

                lrx = int(s_zone.getAttribute('lrx').value)
                if lrx > max_lrx:
                    max_lrx = lrx

                lry = int(s_zone.getAttribute('lry').value)
                if lry > max_lry:
                    max_lry = lry

            m_zone = self._create_zone(min_ulx, min_uly, max_lrx, max_lry)
            m.addAttribute('facs', '#'+m_zone.getId())
            surface = self.meidoc.getElementsByName('surface')[0]
            surface.addChild(m_zone)

    def _create_header(self, rodan_version='0.1'):
        '''
        Create a meiHead element
        '''

        mei_head = MeiElement('meiHead')
        today = datetime.date.today().isoformat()

        app_name = 'RODAN/barlineFinder'

        # file description
        file_desc = MeiElement('fileDesc')

        title_stmt = MeiElement('titleStmt')
        title = MeiElement('title')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        title_stmt.addChild(title)
        title_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        
        pub_stmt = MeiElement('pubStmt')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        pub_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)

        mei_head.addChild(file_desc)
        file_desc.addChild(title_stmt)
        file_desc.addChild(pub_stmt)

        # encoding description
        encoding_desc = MeiElement('encodingDesc')
        app_info = MeiElement('appInfo')
        application = MeiElement('application')
        application.addAttribute('version', rodan_version)
        name = MeiElement('name')
        name.setValue(app_name)
        ptr = MeiElement('ptr')
        ptr.addAttribute('target', 'https://github.com/DDMAL/barlineFinder')

        mei_head.addChild(encoding_desc)
        encoding_desc.addChild(app_info)
        app_info.addChild(application)
        application.addChild(name)
        application.addChild(ptr)

        # revision description
        revision_desc = MeiElement('revisionDesc')
        change = MeiElement('change')
        change.addAttribute('n', '1')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        change_desc = MeiElement('changeDesc')
        ref = MeiElement('ref')
        ref.addAttribute('target', '#'+application.getId())
        ref.setValue(app_name)
        ref.setTail('.')
        p = MeiElement('p')
        p.addChild(ref)
        p.setValue('Encoded using ')
        date = MeiElement('date')
        date.setValue(today)
        
        mei_head.addChild(revision_desc)
        revision_desc.addChild(change)
        change.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        change.addChild(change_desc)
        change_desc.addChild(p)
        change.addChild(date)

        return mei_head

    def _create_graphic(self, image_path, image_width, image_height):
        '''
        Create a graphic element.
        '''

        graphic = MeiElement('graphic')
        graphic.addAttribute('height', str(image_height))
        graphic.addAttribute('width', str(image_width))
        graphic.addAttribute('target', image_path)
        graphic.addAttribute('unit', 'px')

        return graphic

    def _create_staff_group(self, sg_list, staff_grp, n):
        '''
        Recursively create the staff group element from the parsed
        user input of the staff groupings
        '''
        if not sg_list:
            return staff_grp, n
        else:
            if type(sg_list[0]) is list:
                new_staff_grp, n = self._create_staff_group(sg_list[0], MeiElement('staffGrp'), n)
                staff_grp.addChild(new_staff_grp)
            else:
                # check for barthrough character
                if sg_list[0][-1] == '|':
                    # the barlines go through all the staves in the staff group
                    staff_grp.addAttribute('barthru', 'true')
                    # remove the barthrough character, should now only be an integer
                    sg_list[0] = sg_list[0][:-1]

                n_staff_defs = int(sg_list[0])
                # get current staffDef number
                for i in range(n_staff_defs):
                    staff_def = MeiElement('staffDef')
                    staff_def.addAttribute('n', str(n+i+1))
                    staff_def.addAttribute('lines', '5')
                    staff_grp.addChild(staff_def)
                n += n_staff_defs

            return self._create_staff_group(sg_list[1:], staff_grp, n)

    def _create_staff(self, n, zone):
        '''
        Create a staff element, and attach a zone reference to it
        '''

        staff = MeiElement('staff')
        staff.addAttribute('n', str(n))
        staff.addAttribute('facs', '#'+zone.getId())

        return staff

    def _create_measure(self, n, zone = None):
        '''
        Create a measure element and attach a zone reference to it.
        The zone element is optional, since the zone of the measure is
        calculated once all of the staves within a measure have been added
        to the MEI.
        '''

        measure = MeiElement('measure')
        measure.addAttribute('n', str(n))

        if zone is not None:
            measure.addAttribute('facs', '#'+zone.getId())

        return measure

    def _create_zone(self, ulx, uly, lrx, lry):
        '''
        Create a zone element
        '''

        zone = MeiElement('zone')
        zone.addAttribute('ulx', str(ulx))
        zone.addAttribute('uly', str(uly))
        zone.addAttribute('lrx', str(lrx))
        zone.addAttribute('lry', str(lry))

        return zone

    def output_mei(self, output_path):
        '''
        Write the generated mei to disk
        '''

        # output mei file
        XmlExport.meiDocumentToFile(self.meidoc, output_path)
Beispiel #42
0
    def test_getroot(self):
        doc = MeiDocument()
        mei = MeiElement("mei")
        doc.root = mei

        self.assertEqual(mei, doc.root)
Beispiel #43
0
    def test_flattenedtree(self):
        mei = MeiElement("mei")
        mus = MeiElement("music")
        body = MeiElement("body")
        staff = MeiElement("staff")
        staff2 = MeiElement("staff")
        n1 = MeiElement("note")
        n2 = MeiElement("note")
        n3 = MeiElement("note")

        doc = MeiDocument()

        mei.addChild(mus)

        doc.root = mei

        mus.addChild(body)
        body.addChild(staff)
        body.addChild(staff2)
        staff.addChild(n1)
        staff.addChild(n2)
        staff2.addChild(n3)

        doc.lookBack(n2, "mei")
        self.assertEqual(8, len(doc.getFlattenedTree()))

        staff.removeChild(n2)
        self.assertEqual(7, len(doc.getFlattenedTree()))

        self.assertEqual(staff2, doc.getFlattenedTree()[5])

        staff.removeChildrenWithName("note")
        self.assertEqual(6, len(doc.getFlattenedTree()))

        body.deleteAllChildren()
        self.assertEqual(3, len(doc.getFlattenedTree()))

        children = MeiElementList()
        staff3 = MeiElement("staff")
        staff4 = MeiElement("staff")
        children.append(staff3)
        children.append(staff4)

        body.children = children

        self.assertEqual(5, len(doc.getFlattenedTree()))

        elements = [mei, mus, body, staff3, staff4]

        for i,el in enumerate(doc.getFlattenedTree()):
            self.assertEqual(elements[i], doc.getFlattenedTree()[i])
Beispiel #44
0
    def write_mei(self, notes, audio_path, output_path=None):
        from pymei import MeiDocument, MeiElement, XmlExport
        
        # combine features with the same timestamps
        note_events = []
        for n in notes:
            ts = n.timestamp.toSeconds()
            note_num = int(n.values[0]) + 1          # it looks like everything is transposed a semitone down ... transposing up
            # if the last timestamp is equal to this timestamp, combine into a chord
            if len(note_events) > 0 and note_events[-1][0] == ts:
                note_events[-1][1].append(note_num)
            else:
                note_events.append([ts, [note_num]])

        # sort by timestamp in ascending order
        note_events = sorted(note_events, key=lambda n: n[0])

        # begin constructing mei document
        meidoc = MeiDocument()
        mei = MeiElement('mei')
        meidoc.setRootElement(mei)

        music = MeiElement('music')
        timeline = MeiElement('timeline')
        timeline.addAttribute('avref', str(audio_path))
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')

        # assume 4/4 time signature
        meter_count = 4
        meter_unit = 4
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))
        
        staff_def = MeiElement('staffDef')
        staff_def.addAttribute('n', '1')
        staff_def.addAttribute('label.full', 'Electric Guitar')
        staff_def.addAttribute('clef.shape', 'TAB')

        instr_def = MeiElement('instrDef')
        instr_def.addAttribute('n', 'Electric_Guitar')
        instr_def.addAttribute('midi.channel', '1')
        instr_def.addAttribute('midi.instrnum', '28')

        mei.addChild(music)
        music.addChild(timeline)
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(staff_def)
        staff_def.addChild(instr_def)

        section = MeiElement('section')
        score.addChild(section)
        # another score def
        score_def = MeiElement('scoreDef')
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))
        section.addChild(score_def)
        
        # start writing pitches to file
        note_container = None
        for i, note_event in enumerate(note_events):
            if i % meter_count == 0:
                measure = MeiElement('measure')
                measure.addAttribute('n', str(int(i/meter_count + 1)))
                staff = MeiElement('staff')
                staff.addAttribute('n', '1')
                layer = MeiElement('layer')
                layer.addAttribute('n', '1')
                section.addChild(measure)
                measure.addChild(staff)
                staff.addChild(layer)
                note_container = layer

            ts = note_event[0]
            when = MeiElement('when')
            if i == 0:
                timeline.addAttribute('origin', when.getId())
            when.addAttribute('absolute', str(ts))
            timeline.addChild(when)

            notes = note_event[1]
            if len(notes) > 1:
                chord = MeiElement('chord')
                chord.addAttribute('when', when.getId())
                for n in notes:
                    note = MeiElement('note')
                    note_info = PolyTrans.midi_map[n]
                    pname = note_info[0]
                    oct = note_info[1]
                    note.addAttribute('pname', pname[0])
                    note.addAttribute('oct', str(oct))
                    if len(pname) > 1 and pname[-1] == '#':
                        # there is an accidental
                        note.addAttribute('accid.ges', 's')
                    note.addAttribute('dur', str(meter_unit))
                    chord.addChild(note)
                note_container.addChild(chord)
            else:
                n = notes[0]
                note = MeiElement('note')
                note.addAttribute('when', when.getId())
                note_info = PolyTrans.midi_map[n]
                pname = note_info[0]
                oct = note_info[1]
                note.addAttribute('pname', pname[0])
                note.addAttribute('oct', str(oct))
                if len(pname) > 1 and pname[-1] == '#':
                    # there is an accidental
                    note.addAttribute('accid.ges', 's')
                note.addAttribute('dur', str(meter_unit))
                note_container.addChild(note)

        if output_path is not None:
            XmlExport.meiDocumentToFile(meidoc, output_path)
        else:
            return XmlExport.meiDocumentToText(meidoc)
Beispiel #45
0
    def bardata_to_mei(self, sg_hint, image_path, image_width, image_height, image_dpi):
        '''
        Perform the data conversion to mei
        '''

        self.meidoc = MeiDocument()
        mei = MeiElement('mei')
        self.meidoc.setRootElement(mei)

        ###########################
        #         MetaData        #
        ###########################
        mei_head = self._create_header()
        mei.addChild(mei_head)

        ###########################
        #           Body          #
        ###########################
        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')
        section = MeiElement('section')

        # physical location data
        facsimile = MeiElement('facsimile')
        surface = MeiElement('surface')

        graphic = self._create_graphic(image_path, image_width, image_height)
        surface.addChild(graphic)

        # parse staff group hint to generate staff group
        sg_hint = sg_hint.split(" ")
        systems = []
        for s in sg_hint:
            parser = nestedExpr()
            sg_list = parser.parseString(s).asList()[0]
            staff_grp, n = self._create_staff_group(sg_list, MeiElement('staffGrp'), 0)

            # parse repeating staff groups (systems)
            num_sb = 1
            match = re.search('(?<=x)(\d+)$', s)
            if match is not None:
                # there are multiple systems of this staff grouping
                num_sb = int(match.group(0))
            
            for i in range(num_sb):
                systems.append(staff_grp)

            if self.verbose:
                print "number of staves in system: %d x %d system(s)" % (n, num_sb)

        # there may be hidden staves in a system
        # make the encoded staff group the largest number of staves in a system
        final_staff_grp = max(systems, key=lambda x: len(x.getDescendantsByName('staffDef')))

        mei.addChild(music)
        music.addChild(facsimile)
        facsimile.addChild(surface)
        
        # list of staff bounding boxes within a system
        staves = []
        for staff_bb in self.staff_bb:
            # get bounding box of the staff
            # parse bounding box integers
            #staff_bb = [int(x) for x in staff_bb]
            staves.append(staff_bb[1:])
        
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(final_staff_grp)
        score.addChild(section)

        # parse barline data file [staffnum][barlinenum_ulx]
        barlines = []
        for i, bar in enumerate(self.bar_bb):
            staff_num = int(bar[0])
            ulx = bar[1]
            try:
                barlines[staff_num-1].append(ulx)
            except IndexError:
                barlines.append([ulx])

        staff_offset = 0
        n_measure = 1
        for s_ind, s in enumerate(systems):
            # measures in a system
            s_measures = []
            staff_defs = s.getDescendantsByName('staffDef')
            # for each staff in the system
            for i in range(len(staff_defs)):
                staff_num = staff_offset + i
                s_bb = staves[staff_num]
                # bounding box of the staff
                s_ulx = s_bb[0]
                s_uly = s_bb[1]
                s_lrx = s_bb[2]
                s_lry = s_bb[3]

                # for each barline on this staff
                try:
                    staff_bars = barlines[staff_num]
                except IndexError:
                    # a staff was found, but no bar candidates have been found on the staff
                    continue

                # for each barline on this staff
                for n, b in enumerate(staff_bars[:-1]):
                    # calculate bounding box of the measure
                    m_uly = s_uly
                    m_lry = s_lry
                    m_ulx = b
                    m_lrx = staff_bars[n+1]

                    zone = self._create_zone(m_ulx, m_uly, m_lrx, m_lry)
                    surface.addChild(zone)
                    if len(sg_hint) == 1 or len(staff_defs) == len(final_staff_grp.getDescendantsByName('staffDef')):
                        staff_n = str(i+1)    
                    else:
                        # take into consideration hidden staves
                        staff_n = i + self._calc_staff_num(len(staff_defs), [final_staff_grp]) + 1
                    
                    staff = self._create_staff(staff_n, zone)
                    #print '  ', staff_n, m_ulx, m_uly, m_lrx, m_lry
                    try:
                        s_measures[n].addChild(staff)
                    except IndexError:
                        # create a new measure
                        measure = self._create_measure(str(n_measure))
                        s_measures.append(measure)
                        section.addChild(measure)
                        measure.addChild(staff)
                        n_measure += 1

            # calculate min/max of measure/staff bounding boxes to get measure zone
            self._calc_measure_zone(s_measures)

            staff_offset += len(staff_defs)

            # add a system break, if necessary
            if s_ind+1 < len(systems):
                sb = MeiElement('sb')
                section.addChild(sb)
class GroundTruthBarlineDataConverter:
    '''
    Convert the stored measures of the Ground Truth System to MEI.
    TODO: Only considers barpanels, not staffpanels
    '''

    def __init__(self, staffbb, barbb, verbose=False):
        '''
        Constructor of converter.
        staffbb are the boxes bouding the staves (or systems)
        barbb are the boxes bounding the measures (or bars)
        These are passed in as lists of Rects defined in gtruth-rect
        '''

        # Print errors / messages
        self.verbose = verbose

        # The coordinates of the staves stored in the format:
        # [index, top-corner x, top-corner y, bottom-corner x, bottom-corner y]
        # (note this is a python list)
        # To get an idea of what the staves are, image a piano score where each
        # system consists (usually) of a treble staff and bass staff. This
        # system is divided into measures and you can divide the measure into
        # two parts: the box encompassing the top staff within the measure and
        # the box encompassing the bottom staff within the measure. These two
        # boxes are what is meant by staff bounding boxes.
        self.staffbb = staffbb
        if self.verbose:
            sys.stderr.write("Staff bounding boxes" + repr(self.staffbb))

        # The coordinates of the bars stored in the format:
        # (index, top-corner x, top-corner y, bottom-corner x, bottom-corner y)
        # (note this is a python tuple)
        # The differentiation is for compatibility with meicreate.py
        # Bars are the measures of the system. That means for an orchestral
        # score the bars can be very tall and thin.
        self.barbb = barbb
        if self.verbose:
            sys.stderr.write("Bar bounding boxes" + repr(self.barbb))

        self.meidoc = None;

    def bardata_to_mei(self, imagepath, imagewidth, imageheight, imagedpi=72):
        '''
        Perform the data conversion to MEI
        '''

        self.meidoc = MeiDocument()
        mei = MeiElement('mei')
        self.meidoc.setRootElement(mei)

        ###########################
        #         MetaData        #
        ###########################
        mei_head = self._create_header()
        mei.addChild(mei_head)

        ###########################
        #           Body          #
        ###########################
        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')
        section = MeiElement('section')

        # physical location data
        facsimile = MeiElement('facsimile')
        surface = MeiElement('surface')

        graphic = self._create_graphic(imagepath, imagewidth, imageheight,\
                imagedpi)
        surface.addChild(graphic)

        mei.addChild(music)
        music.addChild(facsimile)
        facsimile.addChild(surface)
        
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score.addChild(section)

        barmeasdict = dict()

        # Only add the bar bounding boxes
        for bar in self.barbb:
            # Zone is the coordinates where the measure is found in the image
            zone = self._create_zone(\
                    int(bar.pos[0]),int(bar.pos[1]),\
                    int(bar.pos[0])+int(bar.size[0]),\
                    int(bar.pos[1])+int(bar.size[1]));
            # Zone is a child element of the surface
            surface.addChild(zone)
            # The measure is found in the zone
            measure = self._create_measure(bar.number,zone);
            section.addChild(measure);
            # store which measure this bar corresponds to so we can add it as a
            # child to the staff bounding boxes later TODO: We don't do this
            # right now
            barmeasdict[bar] = measure

        # Add the staff bounding boxes
        # We don't do this but when we do, the staff needs to look up its
        # children in barmeasdict

    def _create_header(self, rodan_version='0.1'):
        '''
        Create a meiHead element
        '''

        mei_head = MeiElement('meiHead')
        today = datetime.date.today().isoformat()

        app_name = 'gtruth_write_mei'

        # file description
        file_desc = MeiElement('fileDesc')

        title_stmt = MeiElement('titleStmt')
        title = MeiElement('title')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        title_stmt.addChild(title)
        title_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        
        pub_stmt = MeiElement('pubStmt')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        pub_stmt.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)

        mei_head.addChild(file_desc)
        file_desc.addChild(title_stmt)
        file_desc.addChild(pub_stmt)

        # encoding description
        encoding_desc = MeiElement('encodingDesc')
        app_info = MeiElement('appInfo')
        application = MeiElement('application')
        application.addAttribute('version', rodan_version)
        name = MeiElement('name')
        name.setValue(app_name)
        ptr = MeiElement('ptr')
        ptr.addAttribute('target', 'https://github.com/DDMAL/barlineFinder')

        mei_head.addChild(encoding_desc)
        encoding_desc.addChild(app_info)
        app_info.addChild(application)
        application.addChild(name)
        application.addChild(ptr)

        # revision description
        revision_desc = MeiElement('revisionDesc')
        change = MeiElement('change')
        change.addAttribute('n', '1')
        resp_stmt = MeiElement('respStmt')
        corp_name = MeiElement('corpName')
        corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)')
        change_desc = MeiElement('changeDesc')
        ref = MeiElement('ref')
        ref.addAttribute('target', '#'+application.getId())
        ref.setValue(app_name)
        ref.setTail('.')
        p = MeiElement('p')
        p.addChild(ref)
        p.setValue('Encoded using ')
        date = MeiElement('date')
        date.setValue(today)
        
        mei_head.addChild(revision_desc)
        revision_desc.addChild(change)
        change.addChild(resp_stmt)
        resp_stmt.addChild(corp_name)
        change.addChild(change_desc)
        change_desc.addChild(p)
        change.addChild(date)

        return mei_head

    def _create_graphic(self, image_path, image_width, image_height, image_dpi):
        '''
        Create a graphic element.
        '''

        graphic = MeiElement('graphic')
        graphic.addAttribute('height', str(image_height))
        graphic.addAttribute('width', str(image_width))
        graphic.addAttribute('target', image_path)
        graphic.addAttribute('resolution', str(image_dpi))
        graphic.addAttribute('unit', 'px')

        return graphic

    def _create_measure(self, n, zone = None):
        '''
        Create a measure element and attach a zone reference to it.
        The zone element is optional, since the zone of the measure is
        calculated once all of the staves within a measure have been added
        to the MEI.
        '''

        measure = MeiElement('measure')
        measure.addAttribute('n', str(n))

        if zone is not None:
            measure.addAttribute('facs', '#'+zone.getId())

        return measure

    def _create_zone(self, ulx, uly, lrx, lry):
        '''
        Create a zone element
        '''

        zone = MeiElement('zone')
        zone.addAttribute('ulx', str(ulx))
        zone.addAttribute('uly', str(uly))
        zone.addAttribute('lrx', str(lrx))
        zone.addAttribute('lry', str(lry))

        return zone

    def output_mei(self, output_path):
        '''
        Write the generated mei to disk
        '''

        # output mei file
        if self.meidoc == None:
            raise Warning('The MEI document has not yet been created');
            return

        XmlExport.meiDocumentToFile(self.meidoc, output_path)
Beispiel #47
0
    def __init__(self, incoming_data, original_image, page_number=None):
        self._recognition_results = incoming_data
        # self.mei = mod.mei_()
        self.mei = MeiElement("mei")
        self.staff = None

        # Hack: I'm not sure what staff_num is. In any case it's strange to set it to None.
        # I therefore set it to 0 if page_number is None.
        if page_number is not None:
            self.staff_num = int(page_number)
        else:
            self.staff_num = 0
        self.glyph = None

        self._note_elements = None
        self._neume_pitches = []

        # set up a basic MEI document structure

        # header
        # self.meihead = mod.meiHead_()
        self.meihead = MeiElement("meiHead")
        # self.filedesc = mod.fileDesc_()
        self.filedesc = MeiElement("fileDesc")
        # self.titlestmt = mod.titleStmt_()
        self.titlestmt = MeiElement("titleStmt")
        # self.title = mod.title_()
        self.title = MeiElement("title")
        # self.pubstmt = mod.pubStmt_()
        self.pubstmt = MeiElement("pubStmt")

        self.titlestmt.addChild(self.title)

        self.filedesc.addChild(self.titlestmt)
        self.filedesc.addChild(self.pubstmt)

        self.meihead.addChild(self.filedesc)
        self.mei.addChild(self.meihead)

        # music
        # self.music = mod.music_()
        self.music = MeiElement("music")
        self.facsimile = self._create_facsimile_element()
        self.surface = self._create_surface_element()
        self.graphic = self._create_graphic_element(original_image)
        lg.debug("SELF GRAPHIC:{0}".format(
            XmlExport.meiElementToText(self.graphic)))

        self.surface.addChild(self.graphic)
        self.facsimile.addChild(self.surface)
        self.music.addChild(self.facsimile)

        self.layout = self._create_layout_element()
        self.pg = self._create_page_element()
        if page_number:
            # self.pg.attributes = {"n": page_number}
            self.pg.addAttribute("n", page_number)

        self.layout.addChild(self.pg)
        self.music.addChild(self.layout)

        # self.body = mod.body_()
        self.body = MeiElement("body")
        self.music.addChild(self.body)

        self.mdiv = MeiElement("mdiv")
        # self.mdiv = mod.mdiv_()
        self.mdiv.addAttribute("type", "solesmes")
        self.body.addChild(self.mdiv)

        # self.score = mod.score_()
        self.score = MeiElement("score")
        self.mdiv.addChild(self.score)

        # self.scoredef = mod.scoreDef_()
        self.scoredef = MeiElement("scoreDef")
        self.score.addChild(self.scoredef)

        # self.section = mod.section_()
        self.section = MeiElement("section")
        self.pagebreak = self._create_pb_element()
        # self.pagebreak.attributes = {"pageref": self.pg.id}
        self.pagebreak.addAttribute("pageref", self.pg.id)

        self.section.addChild(self.pagebreak)
        self.score.addChild(self.section)

        self.staffgrp = self._create_staffgrp_element()
        self.staffdef = self._create_staffdef_element()
        self.staffdef.addAttribute("n", str(self.staff_num))  # trouble

        self.staffgrp.addChild(self.staffdef)
        self.scoredef.addChild(self.staffgrp)

        self.layer = self._create_layer_element()
        self.layer.addAttribute("n", "1")

        self.staffel = self._create_staff_element()
        self.staffel.addAttribute("n", str(self.staff_num))  # trouble
        self.section.addChild(self.staffel)
        self.staffel.addChild(self.layer)

        for sysnum in sorted(self._recognition_results.keys()):
            syst = self._recognition_results[sysnum]
            lg.debug("sysnum:{0}".format(sysnum))
            self.system = syst
            self.systembreak = self._parse_system(sysnum, syst)
            # z = mod.zone_()
            z = MeiElement("zone")
            # z.id = self._idgen()
            # z.attributes = {'ulx': self.system['coord'][0], 'uly': self.system['coord'][1], \
            #                     'lrx': self.system['coord'][2], 'lry': self.system['coord'][3]}
            z.addAttribute("ulx", str(self.system['coord'][0]))
            z.addAttribute("uly", str(self.system['coord'][1]))
            z.addAttribute("lrx", str(self.system['coord'][2]))
            z.addAttribute("lry", str(self.system['coord'][3]))
            self.surface.addChild(z)
            # self.system.facs = z.id
            s = self._create_system_element()
            s.facs = z.id
            s.addAttribute("facs", s.facs)
            self.pg.addChild(s)
            self.systembreak.addAttribute("systemref", s.id)

        self.mei.addChild(self.music)

        # if not self.staffel.descendants_by_name('neume'):
        if not self.staffel.getDescendantsByName("neume"):
            self.staffgrp.removeChild(self.staffdef)
            self.section.removeChild(self.staffel)

        # self.md = MeiDocument.MeiDocument()
        # self.md.addelement(self.mei)
        self.md = MeiDocument()
        self.md.setRootElement(self.mei)
        print XmlExport.meiElementToText(
            self.md.getElementById(self.graphic.getId()))
    def bardata_to_mei(self, imagepath, imagewidth, imageheight, imagedpi=72):
        '''
        Perform the data conversion to MEI
        '''

        self.meidoc = MeiDocument()
        mei = MeiElement('mei')
        self.meidoc.setRootElement(mei)

        ###########################
        #         MetaData        #
        ###########################
        mei_head = self._create_header()
        mei.addChild(mei_head)

        ###########################
        #           Body          #
        ###########################
        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')
        section = MeiElement('section')

        # physical location data
        facsimile = MeiElement('facsimile')
        surface = MeiElement('surface')

        graphic = self._create_graphic(imagepath, imagewidth, imageheight,\
                imagedpi)
        surface.addChild(graphic)

        mei.addChild(music)
        music.addChild(facsimile)
        facsimile.addChild(surface)
        
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score.addChild(section)

        barmeasdict = dict()

        # Only add the bar bounding boxes
        for bar in self.barbb:
            # Zone is the coordinates where the measure is found in the image
            zone = self._create_zone(\
                    int(bar.pos[0]),int(bar.pos[1]),\
                    int(bar.pos[0])+int(bar.size[0]),\
                    int(bar.pos[1])+int(bar.size[1]));
            # Zone is a child element of the surface
            surface.addChild(zone)
            # The measure is found in the zone
            measure = self._create_measure(bar.number,zone);
            section.addChild(measure);
            # store which measure this bar corresponds to so we can add it as a
            # child to the staff bounding boxes later TODO: We don't do this
            # right now
            barmeasdict[bar] = measure
    def write_mei(self, notes, output_path=None):
        # begin constructing mei document
        meidoc = MeiDocument()
        mei = MeiElement('mei')
        meidoc.setRootElement(mei)
        mei_head = MeiElement('meiHead')
        mei.addChild(mei_head)

        music = MeiElement('music')
        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        score = MeiElement('score')
        score_def = MeiElement('scoreDef')

        # assume 4/4 time signature
        meter_count = 4
        meter_unit = 4
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))

        staff_def = MeiElement('staffDef')
        staff_def.addAttribute('n', '1')
        staff_def.addAttribute('label.full', 'Electric Guitar')
        staff_def.addAttribute('clef.shape', 'TAB')

        instr_def = MeiElement('instrDef')
        instr_def.addAttribute('n', 'Electric_Guitar')
        instr_def.addAttribute('midi.channel', '1')
        instr_def.addAttribute('midi.instrnum', '28')

        mei.addChild(music)
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(score)
        score.addChild(score_def)
        score_def.addChild(staff_def)
        staff_def.addChild(instr_def)

        section = MeiElement('section')
        score.addChild(section)
        # another score def
        score_def = MeiElement('scoreDef')
        score_def.addAttribute('meter.count', str(meter_count))
        score_def.addAttribute('meter.unit', str(meter_unit))
        section.addChild(score_def)

        # start writing pitches to file
        note_container = None
        for i, frame_n in enumerate(notes):
            if i % meter_count == 0:
                measure = MeiElement('measure')
                measure.addAttribute('n', str(int(i / meter_count + 1)))
                staff = MeiElement('staff')
                staff.addAttribute('n', '1')
                layer = MeiElement('layer')
                layer.addAttribute('n', '1')
                section.addChild(measure)
                measure.addChild(staff)
                staff.addChild(layer)
                note_container = layer

            if len(frame_n) > 1:
                chord = MeiElement('chord')
                for n in frame_n:
                    note = MeiElement('note')
                    pname = n['pname'][0].upper()
                    note.addAttribute('pname', pname)
                    note.addAttribute('oct', str(n['oct']))
                    if len(n['pname']) > 1 and n['pname'][1] == '#':
                        # there is an accidental
                        note.addAttribute('accid.ges', 's')
                    note.addAttribute('dur', str(meter_unit))
                    chord.addChild(note)
                note_container.addChild(chord)
            else:
                n = frame_n[0]
                note = MeiElement('note')
                pname = n['pname'][0].upper()
                note.addAttribute('pname', pname)
                note.addAttribute('oct', str(n['oct']))
                if len(n['pname']) > 1 and n['pname'][1] == '#':
                    # there is an accidental
                    note.addAttribute('accid.ges', 's')
                note.addAttribute('dur', str(meter_unit))
                note_container.addChild(note)

        if output_path is not None:
            XmlExport.meiDocumentToFile(meidoc, output_path)
        else:
            return XmlExport.meiDocumentToText(meidoc)
Beispiel #50
0
    def test_documentrootnotset(self):
        doc = MeiDocument()
        with self.assertRaises(DocumentRootNotSetException) as cm:
            ret = documentToText(doc)

        self.assertTrue(isinstance(cm.exception, DocumentRootNotSetException))
Beispiel #51
0
        def __init__(self):
            """
            Setup some connecting apps.
            Connecting apps are:
              1. they are in subsequent measures,
              2. they are on the same staff,
              3. there isn't any notes or rests are in between them and
              4. their rdgs represent the exact same set of sources
            Apps need to have xml:id. Only apps lower than <layer> level
            will be linked together.
            """
            music = MeiElement('music')
            body = MeiElement('body')
            mdiv = MeiElement('mdiv')
            score = MeiElement('score')
            section = MeiElement('section')
            m1 = MeiElement('measure')
            m2 = MeiElement('measure')
            s1 = MeiElement('staff')
            s2 = MeiElement('staff')
            l1 = MeiElement('layer')
            l2 = MeiElement('layer')

            app1 = MeiElement('app')
            app2 = MeiElement('app')
            app3 = MeiElement('app')
            lem1 = MeiElement('lem')
            lem2 = MeiElement('lem')
            lem3 = MeiElement('lem')
            rdg1_A = MeiElement('rdg')
            rdg1_B = MeiElement('rdg')
            rdg2_A = MeiElement('rdg')
            rdg2_B = MeiElement('rdg')
            rdg1_A.addAttribute('source', "SRC-A")
            rdg1_B.addAttribute('source', "SRC-B")
            rdg2_A.addAttribute('source', "SRC-A")
            rdg2_B.addAttribute('source', "SRC-B")

            music.addChild(body)
            body.addChild(mdiv)
            mdiv.addChild(score)
            score.addChild(section)
            section.addChild(m1)
            m1.addChild(s1)
            s1.addChild(l1)
            section.addChild(m2)
            m2.addChild(s2)
            s2.addChild(l2)

            """
            app1 and app2 are connecting apps in m1 and m2
            """
            l1.addChild(app1)
            app1.addChild(lem1)
            app1.addChild(rdg1_A)
            app1.addChild(rdg1_B)
        
            l2.addChild(app2)
            app2.addChild(lem2)
            app2.addChild(rdg2_A)
            app2.addChild(rdg2_B)
            
            self.music =  music
            self.app1 = app1
            self.app2 = app2
        
            doc = MeiDocument()
            doc.setRootElement(music)
Beispiel #52
0
    def _initMEI(self):
        """Initialize a new MEI document

        Sets the attributes meiDoc, surface, and initLayer
        """

        self.meiDoc = MeiDocument()

        root = MeiElement("mei")
        root.id = generate_MEI_ID()
        self.meiDoc.root = root

        #needs meiHead here
        meiHead = MeiElement('meiHead')
        fileDesc = MeiElement('fileDesc')
        titleStmt = MeiElement('titleStmt')
        title = MeiElement('title')
        pubStmt = MeiElement('pubStmt')
        date = MeiElement('date')
        encodingDesc = MeiElement('encodingDesc')
        projectDesc = MeiElement('projectDesc')
        p = MeiElement('p')

        music = MeiElement('music')
        facsimile = MeiElement('facsimile')

        self.surface = MeiElement('surface')

        # Label the surface with the name of the input file, which could help
        # identify the original image
        label = os.path.basename(os.path.splitext(self.xmlFile)[0])
        self.surface.addAttribute(MeiAttribute('label', label))

        #systems get added to page
        #neumes get added to systems

        body = MeiElement('body')
        mdiv = MeiElement('mdiv')
        pages = MeiElement('pages')
        page = MeiElement('page')
        page.id = generate_MEI_ID()

        initSystem = MeiElement('system')
        initSystem.id = generate_MEI_ID()

        initStaff = MeiElement('staff')
        initStaff.id = generate_MEI_ID()

        self.initLayer = MeiElement('layer')
        self.initLayer.id = generate_MEI_ID()

        root.addChild(meiHead)
        meiHead.addChild(fileDesc)
        fileDesc.addChild(titleStmt)
        titleStmt.addChild(title)
        fileDesc.addChild(pubStmt)
        pubStmt.addChild(date)
        meiHead.addChild(encodingDesc)
        encodingDesc.addChild(projectDesc)
        projectDesc.addChild(p)

        root.addChild(music)
        music.addChild(facsimile)
        facsimile.addChild(self.surface)
        music.addChild(body)
        body.addChild(mdiv)
        mdiv.addChild(pages)
        pages.addChild(page)
        page.addChild(initSystem)
        initSystem.addChild(initStaff)
        initStaff.addChild(self.initLayer)