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_emendations_02(self): name = 'TC_Emendations.02 - Emendations across barlines' mei_file = 'dat/TC.Emendations.02.mei' transform_data = TransformData() transform_data.editorial_resp = 'ZK' transform_data.alternates_list = [ ('1', VARIANT, '1', ''), ('2', EMENDATION, '1', 'Editor1'), ('3', EMENDATION, '1', 'Editor2'), ] transformed_mei_doc = TransformTestCase(name, mei_file, transform_data).Run() MEI_tree = transformed_mei_doc.getRootElement() annots = utilities.get_descendants(MEI_tree, 'annot') self.assertEqual(len(annots), 2) choices = get_descendants(MEI_tree, 'choice') self.assertEqual(len(choices), 8) idtokens = get_attribute_val(annots[0], 'plist').split(' ') self.assertEqual(len(idtokens), 2) self.assertEqual(idtokens[0], '#' + choices[0].getId()) self.assertEqual(idtokens[1], '#' + choices[1].getId()) idtokens = get_attribute_val(annots[1], 'plist').split(' ') self.assertEqual(len(idtokens), 2) self.assertEqual(idtokens[0], '#' + choices[2].getId()) self.assertEqual(idtokens[1], '#' + choices[3].getId())
def renumber_measures(MEI_tree, difference=1): all_measures = get_descendants(MEI_tree, 'measure') for measure in all_measures: # Get measure number attribute measure_n_attr = measure.getAttribute('n') # Get its value, as a number measure_number = eval(measure_n_attr.getValue()) # Reduce number by one measure_n_attr.setValue(str(measure_number - difference))
def process_tune(args, filename, music_group, index): logging.info("Processing file: " + filename) doc = pymei.XmlImport.documentFromFile(filename) music = doc.getElementsByName('music')[0] fileDesc = doc.getElementsByName('fileDesc')[0] subtitles = get_descendants(fileDesc, 'title[type=subtitle]') title = get_descendants(fileDesc, 'title')[0] if (music): music_copy = pymei.MeiElement(music) music_copy.addAttribute('n', 'tune-' + str(index)) music_copy.addAttribute('label', title.getValue()) music_group.addChild(music_copy) mdiv = get_descendants(music_copy, 'mdiv')[0] if (len(subtitles)>0): mdiv.addAttribute('label', subtitles[0].getValue()) filename_tokens = string.split(os.path.basename(filename), '.') if filename_tokens != None and len(filename_tokens)>0: mdiv.addAttribute('label', filename_tokens[0]) return music_group
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_variants_continuous(self): name = 'TC_Variants.04 - Continuos variant' mei_file = 'dat/TC.Variants.04.mei' transform_data = TransformData() transform_data.editorial_resp = 'ZK' transform_data.alternates_list = [ ('1', VARIANT, '1', ''), ('2', VARIANT, '1', 'SourceA 1552/01'), ] transformed_mei_doc = TransformTestCase(name, mei_file, transform_data).Run() MEI_tree = transformed_mei_doc.getRootElement() annots = utilities.get_descendants(MEI_tree, 'annot') self.assertEqual(len(annots), 1) self.assertEqual(len(get_attribute_val(annots[0], 'plist').split(' ')), 4)
def number_of_incipit_measures(MEI_tree): """Calculate the number of incipit measures by finding the first measure with a `label` attribute and comparing that attribute with its logical number. The difference between the two numbers is the number of measures we will need to remove and also the value by which we will need to renumber. """ all_measures = get_descendants(MEI_tree, 'measure') for measure in all_measures: if measure.getAttribute('label'): label_number = eval(measure.getAttribute('label').getValue()) measure_number = eval(measure.getAttribute('n').getValue()) if label_number != measure_number: return measure_number - label_number # If no measure with 'label' exists, there may not be any incipit measures. return 0
facsimile = pymei.MeiElement(pages_doc.getElementsByName('facsimile')[0]) music_group = pymei.MeiElement(tunes_doc.getElementsByName('group')[0]) music = pymei.MeiElement("music") music.addChild(facsimile) music.addChild(music_group) book_doc = pymei.MeiDocument() mei = pymei.MeiElement('mei') book_doc.root = mei mei.addChild(music) logging.info('merging mdivs...') mdivs = get_descendants(music_group, 'mdiv') for mdiv in mdivs: label = mdiv.getAttribute('label') if (label): target = label.value + '.jpg' logging.debug('linking ' + target) graphics = get_descendants(facsimile, 'graphic[target=' + target + ']') if len(graphics) > 0: graphic = graphics[0] mdiv.addAttribute('facs', '#' + graphic.id) else: logging.warning('graphic with @target=\'' + target + '\' not found') else: logging.warning('missing label attribute at mdiv#' + mdiv.id) if args.out: logging.info('writing output...')
def orig_clefs(MEI_tree, alternates_list): def is_placeholder(staff_n, alternates_list): """A staff is PLACEHOLDER if there's at least one other staff that is a reconstruction or concordance of it. """ for a in alternates_list: # if a is reconstruction of alt_list_item: if a[2] == staff_n and a[1] in (RECONSTRUCTION, CONCORDANCE): return True return False def staff_role(staff_n, alternates_list): for a in alternates_list: if a[0] == staff_n: return a[1] def mergeClefAttributes(staffDef, clef): # merge the following attributes: # * shape # * line # * oct # * dis # * dis.place def mergeAttr(attr_name): if (clef.hasAttribute(attr_name)): staffDef.addAttribute('clef.' + attr_name, clef.getAttribute(attr_name).getValue() ) mergeAttr('shape') mergeAttr('line') mergeAttr('oct') mergeAttr('dis') mergeAttr('dis.place') def mergeScoreDefAttributes(scoreDef1, scoreDef2): # merge the following attributes: # * meter.count # * meter.unit # * meter.sym # * clef.line # * clef.shape # * clef.oct # * clef.dis # * clef.dis.place # * key.sig # * key.pname # * key.accid # * key.mode # * key.sig.mixed def mergeAttr(attr_name): if (scoreDef2.hasAttribute(attr_name)): scoreDef1.addAttribute(attr_name, scoreDef2.getAttribute(attr_name).getValue()) mergeAttr('meter.count') mergeAttr('meter.unit') mergeAttr('meter.sym') mergeAttr('clef.line') mergeAttr('clef.oct') mergeAttr('clef.dis') mergeAttr('clef.dis.place') mergeAttr('key.sig') mergeAttr('key.pname') mergeAttr('key.accid') mergeAttr('key.mode') mergeAttr('key.sig.mixed') # copy initial scoreDef to meiHead/workDesc/work/incip/score/ scoreDefs = get_descendants(MEI_tree, 'scoreDef') # make a copy of the main scoreDef mainScoreDef = MeiElement(scoreDefs[0]) # remove unwanted staves: # - Reconstructed (placeholder) staves # - Reconstruction (actual reconstruction) staves # - Emendation staves staffDefs = get_descendants(mainScoreDef, 'staffDef') for staffDef in staffDefs: staff_n = staffDef.getAttribute('n').getValue() if (is_placeholder(staff_n, alternates_list) or staff_role(staff_n, alternates_list) in (RECONSTRUCTION, EMENDATION, CONCORDANCE)): staffDef.parent.removeChild(staffDef) meiHead = get_descendants(MEI_tree, 'meiHead')[0] head_score = chain_elems(meiHead, ['workDesc', 'work', 'incip', 'score']) head_score.addChild(mainScoreDef) # remove the milestone scoreDef and update the # main scoreDef accordingly, and: # 1. find <clef> elements (they should be in the first measure: # assert this, and signal warning if it's not the case) # 2. update main scoreDef according to <clef>s music = get_descendants(MEI_tree, 'music')[0] section = music.getDescendantsByName('section')[0] mainScoreDef = music.getDescendantsByName('scoreDef')[0] i = 0 for scoreDef in music.getDescendantsByName('scoreDef'): # Choosing 3 as a convenient value for a measure early # in the piece, hence unlikely to give false positives, # with a little wiggle room if i > 0 and measures_before_element(scoreDef) < 3: mergeScoreDefAttributes(mainScoreDef, scoreDef) scoreDef.getParent().removeChild(scoreDef) i += 1 clefs = section.getDescendantsByName('clef') for clef in clefs: clef_in_measure = False clef_in_staff = False if clef.hasAncestor('measure'): measure = clef.getAncestor('measure') if (measure.hasAttribute('n') and measure.getAttribute('n').getValue() == '1'): clef_in_measure = True if clef.hasAncestor('staff'): staff = clef.getAncestor('staff') clef_in_staff = True if not clef_in_measure: logging.warning("<clef> is only valid under the first <measure>.") # continue if not clef_in_staff: logging.warning("<clef> is only valid under a <staff>.") # continue if staff.hasAttribute('n'): clef_staff_n = staff.getAttribute('n').getValue() else: clef_staff_n = '1' staffDefs = music.getDescendantsByName('staffDef') for staffDef in staffDefs: staff_n = staffDef.getAttribute('n').getValue() if (staff_n == clef_staff_n): mergeClefAttributes(staffDef, clef)
def obliterate_incipit(MEI_tree, iterations=1): all_measures = get_descendants(MEI_tree, 'measure') for i in range(iterations): measure_to_remove = all_measures[i] measure_to_remove.getParent().removeChild(measure_to_remove)