def test_object_equality(self): el1 = MeiElement("note") el2 = MeiElement("accid") el1.addChild(el2) self.assertEqual(el1, el2.parent)
def move_recon_staves(recon_staves, al): """Move reconstructed staves to their proper place within the <app> element created inplace of the original (placeholder) staff. """ def orig(staff_n, alternates_list): """Return the number of staff that the given staff is a reconstruction of. """ for i in alternates_list: if i[0] == staff_n: return i[2] def resp(staff_n, alternates_list): for i in alternates_list: if i[0] == staff_n: return i[3] for staff in recon_staves: staff_n = staff.getAttribute('n').getValue() parent_measure = staff.getParent() sibling_apps = parent_measure.getChildrenByName('app') for app in sibling_apps: # If it's the right <app> element -- that is, # the number matches with the original staff # for this reconstruction if orig(staff_n, al) == app.getAttribute('n').getValue(): new_rdg = MeiElement('rdg') # Number <rdg> with old staff number new_rdg.addAttribute('n', staff_n) # Add responsibility to new reading element new_rdg.addAttribute('resp', '#' + resp(staff_n, al)) app.addChild(new_rdg) new_rdg.addChild(staff) parent_measure.removeChild(staff)
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 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_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 _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_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_getnextmeasure(self): section = MeiElement('section') m1 = MeiElement('measure') sb = MeiElement('sb') m2 = MeiElement('measure') section.addChild(m1) section.addChild(sb) section.addChild(m2) self.assertEqual(utilities.get_next_measure(m1), m2) self.assertEqual(utilities.get_next_measure(m2), None)
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 change_arranger_element(MEI_tree): """Changes all occurrence of the <arranger> tag to <editor>""" all_arranger = MEI_tree.getDescendantsByName('arranger') for arranger in all_arranger: parent = arranger.getParent() editor = MeiElement('editor') arranger_children = arranger.getChildren() arranger_value = arranger.getValue() for child in arranger_children: editor.addChild(child) editor.setValue(arranger_value) parent.addChild(editor) parent.removeChild(arranger)
def test_peers(self): 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 m1.addChild(b1) b1.addChild(s1) s1.addChild(n1) s1.addChild(n2) s1.addChild(n3) s1.addChild(n4) res = n2.getPeers() self.assertEqual(4, len(res)) self.assertEqual(noteid, res[0].id) self.assertEqual(note4id, res[3].id)
def test_get_descendants(self): measure = MeiElement('measure') layer = MeiElement('layer') note1 = MeiElement('note') note2 = MeiElement('note') note3 = MeiElement('note') rest1 = MeiElement('rest') rest2 = MeiElement('rest') note1.addAttribute('pname', 'c') note1.addAttribute('oct', '4') note1.addAttribute('dur', 'breve') note2.addAttribute('pname', 'd') note2.addAttribute('dur', '1') note3.addAttribute('pname', 'd') note3.addAttribute('dur', '2') rest1.addAttribute('dur', '1') rest2.addAttribute('dur', '2') layer.addChild(note1) layer.addChild(note2) layer.addChild(note3) layer.addChild(rest1) layer.addChild(rest2) measure.addChild(layer) self.assertEqual(3, len(utilities.get_descendants(measure, 'note'))) self.assertEqual(5, len(utilities.get_descendants(measure, 'note rest'))) self.assertEqual(1, len(utilities.get_descendants(measure, 'note[dur=1]'))) self.assertEqual(1, len(utilities.get_descendants(measure, 'note[pname=d,dur=1]'))) self.assertEqual(4, len(utilities.get_descendants(measure, 'note[pname=d,dur=1] note[pname=c,oct=4,dur=breve] rest[dur=2] layer')))
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_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 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 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_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.removeChildrenWithName("note") self.assertEqual(1, len(p.children)) # check that el1 was not actually deleted self.assertTrue(el1)
def ungroup(self, ids, bboxes): ''' Ungroup a neume with the provided ids into puncta. Create bounding box information for each punctum. ''' newids = [] for id, bbox in zip(ids, bboxes): ref_neume = self.mei.getElementById(id) parent = ref_neume.getParent() # get underlying notes notes = ref_neume.getDescendantsByName("note") nids = [] for n, bb in zip(notes, bbox): 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 self.update_or_add_zone(punctum, str(bb["ulx"]), str(bb["uly"]), str(bb["lrx"]), str(bb["lry"])) # insert the punctum before the reference neume parent.addChildBefore(ref_neume, punctum) newids.append(nids) # delete the old neume neume = self.mei.getElementById(id) if neume: # remove bounding box information self.remove_zone(neume) # now remove the neume neume.getParent().removeChild(neume) result = {"nids": newids} return result
def move_supplied_staves(supplied_staves, al): """Move supplied staves to their proper place within the <app> element created in place of the original (placeholder) staff. """ def orig(staff_n, alternates_list): """Return the number of staff that the given staff is substituting for. """ for i in alternates_list: if i[0] == staff_n: return i[2] def staff_type(staff_n, alternates_list): """Return the type of alternate a given staff belongs to.""" for i in alternates_list: if i[0] == staff_n: return i[1] def resp(staff_n, alternates_list): for i in alternates_list: if i[0] == staff_n: return i[3] for staff in supplied_staves: staff_n = staff.getAttribute('n').getValue() parent_measure = staff.getParent() sibling_apps = parent_measure.getChildrenByName('app') for app in sibling_apps: # If it's the right <app> element -- that is, # the number matches with the original staff # for this supplied staff if orig(staff_n, al) == app.getAttribute('n').getValue(): new_rdg = MeiElement('rdg') # Number <rdg> with old staff number new_rdg.addAttribute('n', staff_n) # Add responsibility to new reading element if staff_type(staff_n, al) == RECONSTRUCTION: new_rdg.addAttribute('resp', '#' + resp(staff_n, al)) elif staff_type(staff_n, al) == CONCORDANCE: new_rdg.addAttribute('source', '#' + resp(staff_n, al)) new_rdg.addAttribute('type', staff_type(staff_n, al)) app.addChild(new_rdg) new_rdg.addChild(staff) parent_measure.removeChild(staff)
def create_new_neume(self, neumeids, neume_name): ''' Make a new neume with notes from the neumes with ID's from neumeids and return the MEI object ''' neume = MeiElement("neume") neume.addAttribute("name", neume_name) nc = MeiElement("nc") for i in neumeids: ref_neume = self.mei.getElementById(str(i)) if ref_neume: # get underlying notes notes = ref_neume.getDescendantsByName("note") for n in notes: nc.addChild(n) neume.addChild(nc) return neume
def test_addchildbefore(self): p = MeiElement("note") el1 = MeiElement("accid") el2 = MeiElement("accid") el3 = MeiElement("accid") el4 = MeiElement("accid") p.addChild(el1) p.addChild(el2) self.assertEqual(2, len(p.children)) p.addChildBefore(el2, el3) self.assertEqual(3, len(p.children)) p.addChildBefore(el1, el4) self.assertEqual(4, len(p.children)) self.assertEqual(el4, p.children[0])
def mark_accid_as_editorial(note): """If the note given has an accidental, mark that accidental as editorial and display it above the note. """ # There should be zero or one accid elements in the list, # but it's easier and maybe safer to get a list of "all" # the accidental elements contained within the note. note_accidentals = note.getDescendantsByName('accid') for accid in note_accidentals: supplied_element = MeiElement('supplied') supplied_element.addAttribute('reason', 'edit') note.addChild(supplied_element) accid.addAttribute('func', 'edit') accid.addAttribute('place', 'above') # The accidental SHOULD be the child of <note>, but # just in case we'll get its parent. accid_parent = accid.getParent() accid_parent.removeChild(accid) # Then add the <accid> element to <supplied> supplied_element.addChild(accid)
def test_exportnamespace2(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") music = MeiElement("music") music.id = "musid" music.addAttribute(attr) music.value = "mus!" root.addChild(music) 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\" meiversion=\"2013\">\n <music \ xml:id=\"musid\" xlink:title=\"my awesome thing\">mus!</music>\n</mei>\n" ret = XmlExport.meiDocumentToText(doc) self.assertEqual(expected, ret)
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 wrap_whole_measure(staff, ALT_TYPE): """Enclose the entire contents of a staff in a measure inside the <app> element. Will be done if variants overlap in illegal ways. """ rich_wrapper_name = 'app' rich_default_name = 'lem' if ALT_TYPE == EMENDATION: rich_wrapper_name = 'choice' rich_default_name = 'sic' old_layers = staff.getChildrenByName('layer') notelist = [] if len(old_layers) > 0: old_layer = staff.getChildrenByName('layer')[0] notelist.extend(get_descendants(old_layer, 'note rest space mRest')) staff.removeChild(old_layer) new_layer = MeiElement('layer') rich_wrapper = MeiElement(rich_wrapper_name) rich_default_elem = MeiElement(rich_default_name) for note in notelist: rich_default_elem.addChild(note) rich_wrapper.addChild(rich_default_elem) new_layer.addChild(rich_wrapper) staff.addChild(new_layer) return rich_wrapper
def test_get_children_with_attribute_value(self): meiHead = MeiElement('meiHead') titleStmt = MeiElement('titleStmt') title = MeiElement('tite') respStmt = MeiElement('respStmt') titleStmt.addChild(title) titleStmt.addChild(respStmt) meiHead.addChild(titleStmt) persName = MeiElement('persName') persName.addAttribute('role', 'composer') respStmt.addChild(persName) self.assertEqual(len(utilities.get_children_with_attribute_value(respStmt, 'persName', 'role', 'composer')), 1)
def test_setchildren(self): p = MeiElement("note") el1 = MeiElement("accid") el2 = MeiElement("dot") el3 = MeiElement("artic") p.addChild(el1) self.assertEqual(1, len(p.children)) children = MeiElementList() children.append(el2) children.append(el3) p.children = children # setting the children will REPLACE any previously # set children!!! self.assertEqual(2, len(p.children)) # can't affect children by changing the initial list children.append(MeiElement("accid")) self.assertEqual(2, len(p.children))
def test_get_children(self): meiHead = MeiElement('meiHead') titleStmt = MeiElement('titleStmt') title = MeiElement('tite') respStmt = MeiElement('respStmt') titleStmt.addChild(title) titleStmt.addChild(respStmt) meiHead.addChild(titleStmt) persName = MeiElement('persName') persName.addAttribute('role', 'composer') respStmt.addChild(persName) composers = utilities.get_children_by_expr(respStmt, 'persName[role=composer]') self.assertEqual(len(composers), 1) self.assertEqual(composers[0].getAttribute('role').value, 'composer')
def move_elements(self, layer, before): # get staff parent element staff = layer.getParent() section_parent = staff.getParent() # create new staff and layer new_staff = MeiElement("staff") new_layer = MeiElement("layer") new_layer.addAttribute("n", "1") # get elements after "before element" to move element_peers = before.getPeers() e_ind = list(element_peers).index(before) for e in element_peers[e_ind:]: # add element to the new staff/layer new_layer.addChild(e) # remove element from the current staff/layer layer.removeChild(e) new_staff.addChild(new_layer) # insert new staff into the document staves = section_parent.getChildrenByName("staff") s_ind = list(staves).index(staff) before_staff = None if s_ind + 1 < len(staves): before_staff = staves[s_ind + 1] # insert and update staff definitions self.insert_staff_def(s_ind + 1, len(staves)) # update staff numbers of subsequent staves for i, s in enumerate(staves[s_ind + 1:]): s.addAttribute("n", str(s_ind + i + 3)) new_staff.addAttribute("n", str(s_ind + 2)) self.insert_staff(section_parent, new_staff, before_staff)
def move_elements(self, layer, before): # get staff parent element staff = layer.getParent() section_parent = staff.getParent() # create new staff and layer new_staff = MeiElement("staff") new_layer = MeiElement("layer") new_layer.addAttribute("n", "1") # get elements after "before element" to move element_peers = before.getPeers() e_ind = list(element_peers).index(before) for e in element_peers[e_ind:]: # add element to the new staff/layer new_layer.addChild(e) # remove element from the current staff/layer layer.removeChild(e) new_staff.addChild(new_layer) # insert new staff into the document staves = section_parent.getChildrenByName("staff") s_ind = list(staves).index(staff) before_staff = None if s_ind+1 < len(staves): before_staff = staves[s_ind+1] # insert and update staff definitions self.insert_staff_def(s_ind+1, len(staves)) # update staff numbers of subsequent staves for i, s in enumerate(staves[s_ind+1:]): s.addAttribute("n", str(s_ind+i+3)) new_staff.addAttribute("n", str(s_ind+2)) self.insert_staff(section_parent, new_staff, before_staff)
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))
def test_ancestor(self): m1 = MeiElement("music") musicid = m1.id b1 = MeiElement("body") bodyid = b1.id s1 = MeiElement("staff") n1 = MeiElement("note") a1 = MeiElement("accid") m1.addChild(b1) b1.addChild(s1) s1.addChild(n1) n1.addChild(a1) self.assertEqual(bodyid, a1.getAncestor("body").id) self.assertEqual(musicid, a1.getAncestor("music").id) self.assertEqual(None, a1.getAncestor("mei"))
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()
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_new_punctum(self, pname, oct, dot_form): ''' Make a new punctum with the given pitch name and octave and return the MEI element ''' punctum = MeiElement("neume") punctum.addAttribute("name", "punctum") nc = MeiElement("nc") note = MeiElement("note") note.addAttribute("pname", pname) note.addAttribute("oct", oct) if dot_form is not None: dot = MeiElement("dot") dot.addAttribute("form", str(dot_form)) note.addChild(dot) punctum.addChild(nc) nc.addChild(note) return punctum
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))
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 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)
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_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))
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