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 parse_token(token): def parse_attrs(token): def parse_attrs_str(attrs_str): res = [] attr_pairs = attrs_str.split(",") for attr_pair in attr_pairs: if attr_pair == '': continue name_val = attr_pair.split("=") if len(name_val) > 1: attr = MeiAttribute(name_val[0], name_val[1]) res.append(attr) else: logging.warning("get_descendants(): invalid attribute specifier in expression: " + expr) return res m = re.search("\[(.*)\]", token) attrs_str = "" if m is not None: attrs_str = m.group(1) return parse_attrs_str(attrs_str) m = re.search("^([^\[]+)", token) elem = MeiElement(m.group(1)) attrs = parse_attrs(token) for attr in attrs: elem.addAttribute(attr) return elem
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_getattributeval(self): measure = MeiElement("measure") staff = MeiElement("staff") measure.addAttribute("n", "2") self.assertEqual(utilities.get_attribute_val(measure, "n"), "2") self.assertEqual(utilities.get_attribute_val(staff, "n", "1"), "1")
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 test_removeattr(self): el = MeiElement("mei") el.addAttribute("meiversion", "2012") self.assertTrue(el.hasAttribute("meiversion")) el.removeAttribute("meiversion") self.assertFalse(el.hasAttribute("meiversion"))
def test_getattributeval(self): measure = MeiElement('measure') staff = MeiElement('staff') measure.addAttribute('n', '2') self.assertEqual(utilities.get_attribute_val(measure, 'n'), '2') self.assertEqual(utilities.get_attribute_val(staff, 'n', '1'), '1')
def add_source(sourceDesc, adi): existing = sourceDesc.getDocument().getElementById(adi[3]) if not existing: source = MeiElement('source') source.id = adi[3] source.addAttribute('type', adi[1]) sourceDesc.addChild(source)
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 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 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 make_invisible_space(MEI_tree, handle_mRest=False): """Turns all invisible notes, rests and mRests into <space> elements. """ all_note_rest = MEI_tree.getDescendantsByName('note rest') all_mRest = MEI_tree.getDescendantsByName('mRest') # Replace notes and rests with spaces for item in all_note_rest: try: if item.getAttribute('visible').getValue() == 'false': space = MeiElement('space') attributes = item.getAttributes() for attr in attributes: # Don't add octave or pitch attributes to space if attr.getName() not in ['oct', 'pname']: space.addAttribute(attr) # If mRest, calculate duration here? parent = item.getParent() parent.addChildBefore(item, space) parent.removeChild(item) except: # doesn't have attribute `visible` pass # Replace mRests with nothing -- just remove them # Not currently supported by MEItoVexFlow if handle_mRest: for item in all_mRest: try: if item.getAttribute('visible').getValue() == 'false': item.getParent().removeChild(item) except: # doesn't have attribute `visible` pass
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 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 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 get_new_zone(self, ulx, uly, lrx, lry): 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 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 add_editor(titleStmt, ali): existing = titleStmt.getDocument().getElementById(adi[3]) if not existing: editor = MeiElement('editor') editor.id = ali[3] # Using 'replace' simply to have more natural name for a person editor.addAttribute('type', adi[1].replace('ction', 'ctor')) titleStmt.addChild(editor)
def test_changeattr(self): el = MeiElement("mei") el.addAttribute("meiversion", "2011-05") self.assertTrue(el.hasAttribute("meiversion")) self.assertEqual("2011-05", el.getAttribute("meiversion").value) at = el.getAttribute("meiversion") at.value = "2012" self.assertEqual("2012", el.getAttribute("meiversion").value)
def create_new_division(self, type): ''' Make a new division and return the MEI element. Attach the facs data to the division element ''' division = MeiElement("division") division.addAttribute("form", type) return division
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_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 test_popfromattributes(self): m = MeiElement('mei') m.addAttribute('foo', '1') m.addAttribute('bar', '2') m.addAttribute('baz', '3') attrs = m.getAttributes() foo = attrs.pop() self.assertEqual('3', foo.value) self.assertEqual(2, len(attrs))
def add_zone(self, custos, ulx, uly, lrx, lry): zone = MeiElement("zone") zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry) custos.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone)
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_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 _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_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 test_pushtoattributes(self): m = MeiElement('mei') m.addAttribute('foo', '1') m.addAttribute('bar', '2') m.addAttribute('baz', '3') attrs = m.getAttributes() new = MeiAttribute('hi', 'there') attrs.push(new) self.assertEqual('there', attrs[0].value) self.assertEqual(4, len(attrs))
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 _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 update_or_add_zone(self, punctum, ulx, uly, lrx, lry): facsid = punctum.getAttribute("facs").getValue() if facsid: # the zone exists already zone = self.mei.getElementById(facsid) else: # create a new zone zone = MeiElement("zone") # update bounding box data zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry)
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 _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 update_zone(self, division, ulx, uly, lrx, lry): facs_id = division.getAttribute("facs").getValue() if facs_id: zone = self.mei.getElementById(facs_id) else: zone = MeiElement("zone") division.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone) zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry)
def update_or_add_zone(self, clef, ulx, uly, lrx, lry): facsid = clef.getAttribute("facs").value if facsid: zone = self.mei.getElementById(facsid) else: zone = MeiElement("zone") clef.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone) zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry)
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 test_copy_constructor(self): note = MeiElement("note") note2 = note # check that regular pointer referencing in Python works on MeiElements self.assertEqual(note2, note) note.addAttribute('pname', 'c') note3 = MeiElement(note) # check that they have been properly copied self.assertNotEqual(note3, note) # check that the attributes copied are not the same self.assertNotEqual(note3.getAttribute('pname'), note.getAttribute('pname')) # check that the attribute values copied are the same self.assertEqual(note3.getAttribute('pname').value, note.getAttribute('pname').value)
def add_dot(self, id, form, ulx, uly, lrx, lry): ''' Add a dot ornament to a given element. ''' punctum = self.mei.getElementById(id) # check that a neume with one note is given notes = punctum.getDescendantsByName("note") if punctum.getName() == "neume" and len(notes) == 1: if len(notes): # if a dot does not already exist on the note if len(notes[0].getChildrenByName("dot")) == 0: dot = MeiElement("dot") dot.addAttribute("form", form) notes[0].addChild(dot) self.update_or_add_zone(punctum, ulx, uly, lrx, lry)
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 update_or_add_zone(self, element, ulx, uly, lrx, lry): ''' Update the bounding box information attached to an element ''' facsid = element.getAttribute("facs") if facsid: zone = self.mei.getElementById(facsid.getValue()) else: zone = MeiElement("zone") element.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone) zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry)