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_grp.addChild(staff_def) n += n_staff_defs return self._create_staff_group(sg_list[1:], staff_grp, n)
def insert_puncta(self, nid, bboxes): ''' Insert a punctum for each note in the reference neume before the reference neume in the MEI document. ''' ref_neume = self.mei.getElementById(nid) parent = ref_neume.getParent() # get underlying notes notes = ref_neume.getDescendantsByName("note") nids = [] for n, bb in zip(notes, bboxes): punctum = MeiElement("neume") punctum.addAttribute("name", "punctum") nc = MeiElement("nc") nc.addChild(n) punctum.addChild(nc) # add generated punctum id to return to client nids.append(punctum.getId()) # add facs data for the punctum zone = self.get_new_zone(bb["ulx"], bb["uly"], bb["lrx"], bb["lry"]) self.add_zone(punctum, zone) # insert the punctum before the reference neume parent.addChildBefore(ref_neume, punctum) return nids
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))
def test_object_equality(self): el1 = MeiElement("note") el2 = MeiElement("accid") el1.addChild(el2) self.assertEqual(el1, el2.parent)
def _redistribute(self): ''' Redistribute notes in the measures to match the 4/4 time signature ''' layers = self.mei_doc.getElementsByName('layer') note_events = [] for l in layers: note_events.extend(l.getChildren()) # remove all measures for m in self.mei_doc.getElementsByName('measure'): m.getParent().removeChild(m) section = self.mei_doc.getElementsByName('section')[0] score_def = self.mei_doc.getElementsByName('scoreDef')[0] meter_count = int(score_def.getAttribute('meter.count').value) # insert the note events again 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 note_container.addChild(note_event)
def test_parent(self): el1 = MeiElement("mei") el2 = MeiElement("meiHead") el3 = MeiElement("music") el2.parent = el1 el3.parent = el1 self.assertEqual("mei", el2.parent.name) self.assertEqual("mei", el3.parent.name)
def test_removechild(self): p = MeiElement("layer") el1 = MeiElement("note") el2 = MeiElement("note") p.addChild(el1) p.addChild(el2) self.assertEqual(2, len(p.children)) p.removeChild(el1) self.assertEqual(1, len(p.children))
def test_children(self): el1 = MeiElement("mei") el2 = MeiElement("meiHead") el3 = MeiElement("music") self.assertEqual(0, len(el1.children)) el1.addChild(el2) el1.addChild(el3) self.assertEqual("mei", el2.parent.name) self.assertTrue(el1.hasChildren("music"))
def test_deleteallchildren(self): p = MeiElement("layer") el1 = MeiElement("note") el2 = MeiElement("note") el3 = MeiElement("chord") p.addChild(el1) p.addChild(el2) p.addChild(el3) self.assertEqual(3, len(p.children)) p.deleteAllChildren() self.assertEqual(0, len(p.children))
def getMEIContent(self, dumpVisualization=False): """Extract zones and neumes from the source file""" neumeElements = [] zones = [] for elem in etree.parse( self.xmlFile).xpath('/gamera-database/glyphs/glyph'): # Get the relevant attributes from the glyph element startX = int(elem.get('ulx')) endX = startX + int(elem.get('ncols')) startY = int(elem.get('uly')) endY = startY + int(elem.get('nrows')) curNeumeName = elem.xpath('string(./ids/id/@name)') # Create the MEI neume element newNeumeElement = MeiElement('neume') neumeElements.append(newNeumeElement) newNeumeElement.id = generate_MEI_ID() splitName = curNeumeName[curNeumeName.find(".") + 1:] if (splitName in self.neumeNames): newNeumeElement.addAttribute( MeiAttribute('name', self.neumeNames[splitName])) elif len(splitName) < 3: newNeumeElement.addAttribute( MeiAttribute('name', "Letter " + splitName.upper())) else: newNeumeElement.addAttribute(MeiAttribute('name', splitName)) zoneID = generate_MEI_ID() newNeumeElement.addAttribute(MeiAttribute('facs', zoneID)) zones.append(Zone(zoneID, startX, startY, endX, endY)) zoneElements = [] for zone in self._sortZones(zones, dumpVisualization=dumpVisualization): newZoneElement = MeiElement('zone') zoneElements.append(newZoneElement) newZoneElement.id = zone.id newZoneElement.addAttribute(MeiAttribute('ulx', str(zone.startX))) newZoneElement.addAttribute(MeiAttribute('uly', str(zone.startY))) newZoneElement.addAttribute(MeiAttribute('lrx', str(zone.endX))) newZoneElement.addAttribute(MeiAttribute('lry', str(zone.endY))) return zoneElements, neumeElements
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 test_changechildvalue(self): """ Check if we can replace an attribute value in-place""" p = MeiElement("layer") el1 = MeiElement("note") el2 = MeiElement("note") p.addChild(el1) p.addChild(el2) el1.addAttribute("pname", "c") self.assertEqual("c", p.children[0].getAttribute("pname").value) el1.getAttribute("pname").value = "d" self.assertEqual("d", p.children[0].getAttribute("pname").value)
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())
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)
def test_getchildrenbyname(self): p = MeiElement("note") el1 = MeiElement("accid") el2 = MeiElement("accid") el3 = MeiElement("dot") children = MeiElementList() children.append(el1) children.append(el2) children.append(el3) p.children = children # this should return a new list accid_children = p.getChildrenByName("accid") self.assertEqual(2, len(accid_children))
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)
def mei_append_metamusic(self): ''' Append meta data for the musical work to the mei document ''' mei_path = self.get_abs_path() mei_doc = XmlImport.documentFromFile(mei_path) mei = mei_doc.getRootElement() mei_head = MeiElement('meiHead') music = mei.getChildrenByName('music')[0] file_desc = MeiElement('fileDesc') # title title_stmt = MeiElement('titleStmt') title = MeiElement('title') title.setValue(str(self.fk_mid.title)) # contributers resp_stmt = MeiElement('respStmt') pers_name_artist = MeiElement('persName') pers_name_artist.addAttribute('role', 'artist') pers_name_artist.setValue(str(self.fk_mid.artist)) pers_name_tabber = MeiElement('persName') pers_name_tabber.addAttribute('role', 'tabber') pers_name_tabber.setValue(str(self.fk_mid.copyright)) # encoding information encoding_desc = MeiElement('encodingDesc') app_info = MeiElement('appInfo') application = MeiElement('application') application.setValue('Robotaba') mei_head.addChild(file_desc) file_desc.addChild(title_stmt) title_stmt.addChild(title) title_stmt.addChild(resp_stmt) resp_stmt.addChild(pers_name_artist) resp_stmt.addChild(pers_name_tabber) title_stmt.addChild(encoding_desc) encoding_desc.addChild(app_info) app_info.addChild(application) # attach mei metadata to the document mei.addChildBefore(music, mei_head) XmlExport.meiDocumentToFile(mei_doc, mei_path)
def post(self, file): ''' Add a dot ornament to a given element. ''' neumeid = str(self.get_argument("id", "")) dot_form = str(self.get_argument("dotform", "")) # Bounding box ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) punctum = self.mei.getElementById(neumeid) # check that a punctum element was provided if punctum.getName() == "neume" and punctum.getAttribute( "name").getValue() == "punctum": note = punctum.getDescendantsByName("note") if len(note): # if a dot does not already exist on the note if len(note[0].getChildrenByName("dot")) == 0: dot = MeiElement("dot") dot.addAttribute("form", dot_form) note[0].addChild(dot) self.update_or_add_zone(punctum, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry): ''' Insert a custos. Also add a bounding box for this element. ''' # create custos custos = MeiElement("custos") if pname and oct: custos.addAttribute("pname", pname) custos.addAttribute("oct", oct) # insert the custos if before_id is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(custos) else: before = self.mei.getElementById(str(before_id)) parent = before.getParent() if parent and before: parent.addChildBefore(before, custos) # update the bounding box self.update_or_add_zone(custos, ulx, uly, lrx, lry) result = {"id": custos.getId()} return result
def insert_clef(self, line, shape, pitch_info, before_id, ulx, uly, lrx, lry): ''' Insert a doh or fah clef, with a given bounding box. Must also update pitched elements on the staff that affected by this clef being inserted. ''' clef = MeiElement("clef") clef.addAttribute("shape", shape) clef.addAttribute("line", line) # perform clef insertion if before_id is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(clef) else: before = self.mei.getElementById(str(before_id)) parent = before.getParent() if parent and before: parent.addChildBefore(before, clef) self.update_or_add_zone(clef, ulx, uly, lrx, lry) if pitch_info: self.update_pitched_elements(pitch_info) result = {"id": clef.getId()} return result
def getOrAddChild(mei_elem, child_name): print("Adding ", child_name) children = mei_elem.getChildrenByName(child_name) if children: return children mei_elem.addChild(MeiElement(child_name)) return mei_elem.getChildrenByName(child_name)
def test_removechildrenbyname(self): p = MeiElement("layer") el1 = MeiElement("note") el2 = MeiElement("note") el3 = MeiElement("chord") p.addChild(el1) p.addChild(el2) p.addChild(el3) self.assertEqual(3, len(p.children)) p.removeChildrenByName("note") self.assertEqual(1, len(p.children)) # check that el1 was not actually deleted self.assertTrue(el1)
def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry): ''' Insert a custos. Also add a bounding box for this element. ''' # create custos custos = MeiElement("custos") custos.addAttribute("pname", pname) custos.addAttribute("oct", oct) # insert the custos before = self.mei.getElementById(before_id) # get layer element parent = before.getParent() if parent and before: parent.addChildBefore(before, custos) # update the bounding box self.update_or_add_zone(custos, ulx, uly, lrx, lry) result = {"id": custos.getId()} return result
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 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)
def test_removeattr(self): el = MeiElement("mei") el.addAttribute("meiversion", "2012") self.assertTrue(el.hasAttribute("meiversion")) el.removeAttribute("meiversion") self.assertFalse(el.hasAttribute("meiversion"))
def insert_punctum(self, before_id, pname, oct, dot_form, ulx, uly, lrx, lry): ''' Insert a punctum before the given element. There is one case where there is no element to insert before, when there is no subsequent staff. In this case, the element is inserted at the end of the last system. Also sets the bounding box information of the new punctum. ''' # create the punctum punctum = MeiElement("neume") punctum.addAttribute("name", "punctum") nc = MeiElement("nc") note = MeiElement("note") note.addAttribute("pname", pname) note.addAttribute("oct", oct) # add ornamentation if dot_form is not None: dot = MeiElement("dot") dot.addAttribute("form", str(dot_form)) note.addChild(dot) punctum.addChild(nc) nc.addChild(note) # create bounding box self.update_or_add_zone(punctum, ulx, uly, lrx, lry) # perform the insertion if before_id is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(punctum) else: before = self.mei.getElementById(before_id) # get layer element parent = before.getParent() if parent and before: parent.addChildBefore(before, punctum) # get the generated ID for the client result = {"id": punctum.getId()} return result
def create_zone(self, ulx, uly, lrx, lry): zone = MeiElement("zone") zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry) return zone
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)
def test_descendants(self): m1 = MeiElement("music") b1 = MeiElement("body") s1 = MeiElement("staff") n1 = MeiElement("note") a1 = MeiElement("accid") m1.addChild(b1) b1.addChild(s1) s1.addChild(n1) n1.addChild(a1) desc = m1.getDescendants() self.assertEqual(4, len(desc)) desc2 = a1.getDescendants() self.assertEqual(0, len(desc2))