def sources_and_editors(MEI_tree, alternates_data): """add the sourceDesc element, the source elements, and the editor elements to the mei header """ 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 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) for adi in alternates_data: if adi[1] == RECONSTRUCTION: add_editor(chain_elems(MEI_tree, ['meiHead', 'fileDesc', 'titleStmt']), adi) elif adi[1] == EMENDATION: add_editor(chain_elems(MEI_tree, ['meiHead', 'fileDesc', 'titleStmt']), adi) elif adi[1] == CONCORDANCE: add_source(chain_elems(MEI_tree, ['meiHead', 'fileDesc', 'sourceDesc']), adi) elif adi[0] != adi[2] and adi[1] == VARIANT: add_source(chain_elems(MEI_tree, ['meiHead', 'fileDesc', 'sourceDesc']), adi) else: pass
def sources_and_editors(MEI_tree, alternates_data): """add the sourceDesc element, the source elements, and the editor elements to the mei header """ def add_source(sourceDesc, adi): existing = sourceDesc.getDocument().getElementById(adi[3]) if not existing: source = MeiElement('source') source.id = adi[3] sourceDesc.addChild(source) def add_editor(titleStmt, ali): existing = titleStmt.getDocument().getElementById(adi[3]) if not existing: editor = MeiElement('editor') editor.id = ali[3] titleStmt.addChild(editor) for adi in alternates_data: if adi[1] == RECONSTRUCTION or adi[1] == EMENDATION: add_editor(chain_elems(MEI_tree, ['meiHead', 'fileDesc', 'titleStmt']), adi) if adi[0] != adi[2] and adi[1] == VARIANT: add_source(chain_elems(MEI_tree, ['meiHead', 'fileDesc', 'sourceDesc']), adi)
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)