def post(self, file): ''' Remove a dot ornament to a given element. ''' neumeid = str(self.get_argument("id", "")) # 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): dot = note[0].getChildrenByName("dot") # if a dot exists if len(dot) == 1: note[0].removeChild(dot[0]) self.update_or_add_zone(punctum, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Move a division before the given element. 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 division placement. ''' division_id = str(self.get_argument("id", "")) before_id = str(self.get_argument("beforeid", None)) # 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) division = self.mei.getElementById(division_id) self.update_zone(division, ulx, uly, lrx, lry) self.reposition_division(division, before_id) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Move a clef on a staff (must not change staff). Updates the bounding box information of the clef and updates the pitch information (pitch name and octave) of all pitched elements on the affected staff. ''' data = json.loads(self.get_argument("data", "")) clef_id = str(data["id"]) # bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) clef = self.mei.getElementById(clef_id) # update staff line the clef is on clef.addAttribute("line", str(data["line"])) self.update_or_add_zone(clef, ulx, uly, lrx, lry) self.update_pitched_elements(data["pitchInfo"]) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): data = json.loads(self.get_argument("data", "")) nid = str(data["id"]) beforeid = str(data["beforeid"]) # Bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) pitch_info = data["pitchInfo"] mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) neume = self.mei.getElementById(nid) if pitch_info is not None: self.neume_pitch_shift(neume, pitch_info) self.reposition_neume(neume, beforeid) self.update_or_add_zone(neume, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def test_readmethod_unicode(self): fn = unicode(os.path.join("test", "testdocs", "beethoven.mei")) doc = XmlImport.read(fn) self.assertNotEqual(None, doc) el = doc.getElementById("d1e41") self.assertEqual("c", el.getAttribute("pname").value) self.assertEqual("4", el.getAttribute("oct").value)
def post(self, file): ''' Insert a custos. Also add a bounding box for this element. ''' pname = str(self.get_argument("pname", "")) oct = str(self.get_argument("oct", "")) before_id = str(self.get_argument("beforeid", None)) # 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) custos = self.create_custos(pname, oct) self.insert_custos(custos, before_id) self.add_zone(custos, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) result = {"id": custos.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Move the given custos element. Also update the bounding box information. ''' custos_id = str(self.get_argument("id", "")) pname = self.get_argument("pname", None) oct = self.get_argument("oct", None) # 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) custos = self.mei.getElementById(custos_id) if pname is not None and oct is not None: custos.addAttribute("pname", str(pname)) custos.addAttribute("oct", str(oct)) self.update_or_add_zone(custos, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Ungroup a neume with the provided ID into puncta. Create bounding box information for each punctum. ''' data = json.loads(self.get_argument("data", "")) nids = str(data["nids"]).split(",") bboxes = data["bbs"] mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) newids = [] for nid, bb in zip(nids, bboxes): newids.append(self.insert_puncta(nid, bb)) self.delete_old_neume(nid) XmlExport.write(self.mei, fname) result = {"nids": newids} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Insert a division 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. ''' div_type = str(self.get_argument("type", "")) beforeid = str(self.get_argument("beforeid", None)) # bounding box lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) zone = self.create_zone(ulx, uly, lrx, lry) division = self.create_new_division(div_type) self.add_zone(division, zone) self.insert_division(division, beforeid) XmlExport.write(self.mei, fname) result = {"id": division.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' 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. ''' data = json.loads(self.get_argument("data", "")) shape = str(data["shape"]).upper() line = str(data["line"]) before_id = str(data["beforeid"]) # bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) clef = self.create_clef(shape, line) self.insert_clef(clef, before_id) self.create_zone(ulx, uly, lrx, lry, clef) self.update_pitched_elements(data["pitchInfo"]) XmlExport.write(self.mei, fname) result = {"id": clef.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Neumify a group of neumes (with provided ids) and give it the given neume name. Also update bounding box information. ''' nids = str(self.get_argument("nids", "")).split(",") neume_name = str(self.get_argument("name", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) neume = self.create_new_neume(nids, neume_name) self.insert_neume(neume, nids[0]) self.delete_old_neumes(nids) # Bounding box lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) if lrx and lry and ulx and uly: zone = self.get_new_zone(ulx, uly, lrx, lry) self.add_zone(neume, zone) XmlExport.write(self.mei, fname) result = {"nid": neume.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Change the shape of a given clef. Must also update bounding box data since the glyphs for c and f clefs are different. Must also update pitched elements on the affected staff to correspond with the new clef shape. ''' data = json.loads(self.get_argument("data", "")) clef_id = str(data["id"]) # bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) clef = self.mei.getElementById(clef_id) # update clef shape clef.addAttribute("shape", str(data["shape"]).upper()) self.update_or_add_zone(clef, ulx, uly, lrx, lry) self.update_pitched_elements(data["pitchInfo"]) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Remove a dot ornament to a given element. ''' neumeid = str(self.get_argument("id", "")) # 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): dot = note[0].getChildrenByName("dot") # if a dot exists if len(dot) == 1: note[0].removeChild(dot[0]) self.update_or_add_zone(punctum, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self): mei = self.request.files.get("mei", []) mei_img = self.request.files.get("mei_img", []) document_type = self.get_argument("document_type") mei_root_directory = os.path.abspath(conf.MEI_DIRECTORY) mei_directory = os.path.join(mei_root_directory, document_type) mei_directory_backup = os.path.join(mei_directory, "backup") errors = "" mei_fn = "" if len(mei): mei_fn = mei[0]["filename"] contents = mei[0]["body"] try: mei = XmlImport.documentFromText(contents) if os.path.exists(os.path.join(mei_directory, mei_fn)): errors = "mei file already exists" else: # write to working directory and backup fp = open(os.path.join(mei_directory, mei_fn), "w") fp.write(contents) fp.close() fp = open(os.path.join(mei_directory_backup, mei_fn), "w") fp.write(contents) fp.close() except Exception, e: errors = "invalid mei file"
def append_guitar_data(self, tuning, capo): ''' Append meta data about the guitar the transcriber is using ''' mei_path = self.get_abs_path() mei_doc = XmlImport.documentFromFile(mei_path) staff_def = mei_doc.getElementsByName('staffDef')[0] g = Guitar(tuning=str(tuning), capo=capo) sounding_pitches = g.strings # From the MEI guidelines: # "this is given using the written pitch, not the sounding pitch. # For example, the Western 6-string guitar, in standard tuning, sounds an octave below written pitch." written_pitches = [s.pname + str(s.oct + 1) for s in sounding_pitches] staff_def.addAttribute('lines', str(len(sounding_pitches))) staff_def.addAttribute('tab.strings', " ".join(written_pitches)) # Capo could be implicitly encoded by setting the pitches of the open strings # but I really don't like this solution. Instructions are lost about how to tune # and perform the piece on the guitar. # TODO: this attribute doesn't exist in MEI, make a custom build if capo > 0: staff_def.addAttribute('tab.capo', str(capo)) XmlExport.meiDocumentToFile(mei_doc, mei_path)
def append_guitar_data(self, tuning, capo): ''' Append meta data about the guitar the transcriber is using ''' mei_path = self.get_abs_path() mei_doc = XmlImport.documentFromFile(mei_path) staff_def = mei_doc.getElementsByName('staffDef')[0] g = Guitar(tuning=str(tuning), capo=capo) sounding_pitches = g.strings # From the MEI guidelines: # "this is given using the written pitch, not the sounding pitch. # For example, the Western 6-string guitar, in standard tuning, sounds an octave below written pitch." written_pitches = [s.pname + str(s.oct+1) for s in sounding_pitches] staff_def.addAttribute('lines', str(len(sounding_pitches))) staff_def.addAttribute('tab.strings', " ".join(written_pitches)) # Capo could be implicitly encoded by setting the pitches of the open strings # but I really don't like this solution. Instructions are lost about how to tune # and perform the piece on the guitar. # TODO: this attribute doesn't exist in MEI, make a custom build if capo > 0: staff_def.addAttribute('tab.capo', str(capo)) XmlExport.meiDocumentToFile(mei_doc, mei_path)
def post(self, request): mei = self.request.files.get("mei", []) mei_img = self.request.files.get("mei_img", []) document_type = "squarenote" mei_root_directory = os.path.abspath(conf.MEI_DIRECTORY) mei_directory = os.path.join(mei_root_directory, document_type) mei_directory_backup = os.path.join(mei_root_directory, "backup") errors = "" mei_fn = "" if len(mei): mei_fn = mei[0]["filename"] mei_fn_split = os.path.splitext(mei_fn) mei_zero, mei_ext = mei_fn_split contents = mei[0]["body"] # TODO: Figure out how to validate MEI files properly using pymei try: mei = XmlImport.documentFromText(contents) # if not mei_fn.endswith('.mei'): # errors = "not in mei file format" if os.path.exists(os.path.join(mei_directory, mei_fn)): errors = "mei file already exists" else: # write to working directory and backup fp = open(os.path.join(mei_directory, mei_fn), "w") fp.write(contents) fp.close() fp = open(os.path.join(mei_directory_backup, mei_fn), "w") fp.write(contents) fp.close() except Exception, e: errors = "invalid mei file"
def _get_symbol_widths(self, pages): ''' Calculate the average pixel width of each symbol from a set of pages. PARAMETERS ---------- pages (list): a list of pages ''' # TODO: make this a global var, since it is used in more than one function now symbol_types = ['clef', 'neume', 'custos', 'division'] # dict of symbol_name -> [cumulative_width_sum, num_occurences] symbol_widths = {} for p in pages: meidoc = XmlImport.documentFromFile(p['mei']) num_systems = len(meidoc.getElementsByName('system')) flat_tree = meidoc.getFlattenedTree() sbs = meidoc.getElementsByName('sb') # for each system # important: need to iterate system by system because the class labels depend on the acting clef for staff_index in range(num_systems): try: labels = self._get_symbol_labels(staff_index, meidoc) except IndexError: continue # retrieve list of MeiElements that correspond to glyphs between system breaks start_sb_pos = meidoc.getPositionInDocument(sbs[staff_index]) if staff_index+1 < len(sbs): end_sb_pos = meidoc.getPositionInDocument(sbs[staff_index+1]) else: end_sb_pos = len(flat_tree) symbols = [s for s in flat_tree[start_sb_pos+1:end_sb_pos] if s.getName() in symbol_types] # get bounding box information for each symbol belonging this system symbol_zones = [meidoc.getElementById(s.getAttribute('facs').value) for s in symbols if s.hasAttribute('facs')] for l, z in zip(labels, symbol_zones): ulx = int(z.getAttribute('ulx').value) lrx = int(z.getAttribute('lrx').value) if l in symbol_widths: symbol_widths[l][0] += (lrx - ulx) symbol_widths[l][1] += 1 else: symbol_widths[l] = [lrx - ulx, 1] # calculate average symbol widths across all training pages # rounding to the nearest pixel for s in symbol_widths: symbol_widths[s] = int(round(symbol_widths[s][0] / symbol_widths[s][1])) return symbol_widths
def sanitize_mei_str(self, mei_str, output_mei_path=None, prune=True): self.mei_doc = XmlImport.documentFromText(mei_str) self._sanitize_mei(prune) if output_mei_path: XmlExport.meiDocumentToFile(self.mei_doc, str(output_mei_path)) else: return XmlExport.meiDocumentToText(self.mei_doc)
def parse_file(self, mei_path): ''' Read an mei file and fill the score model ''' from pymei import XmlImport self.doc = XmlImport.documentFromFile(str(mei_path)) self.parse_input()
def parse_str(self, mei_str): ''' Read an mei file from string and fill the score model ''' from pymei import XmlImport self.doc = XmlImport.documentFromText(mei_str) self.parse_input()
def processMeiFile(ffile, solr_server, shortest_gram, longest_gram, page_number, project_id): solrconn = solr.SolrConnection(solr_server) print '\nProcessing ' + str(ffile) + '...' try: meifile = XmlImport.documentFromFile(str(ffile)) except Exception, e: print "E: ",e lg.debug("Could not process file {0}. Threw exception: {1}".format(ffile, e)) print "Whoops!"
def processMeiFile(ffile, solr_server, shortest_gram, longest_gram, page_number, project_id): solrconn = solr.SolrConnection(solr_server) print '\nProcessing ' + str(ffile) + '...' try: meifile = XmlImport.documentFromFile(str(ffile)) except Exception, e: print "E: ", e lg.debug("Could not process file {0}. Threw exception: {1}".format( ffile, e)) print "Whoops!"
def __init__(self, image_path, mei_path): ''' Creates a GlyphGen object. PARAMETERS ---------- image_path: path to the image to generate glyphs for. mei_path: path to the mei file containing glyph bounding box information. ''' self.page_image = Image.open(image_path) self.meidoc = XmlImport.documentFromFile(mei_path)
def __init__(self, input_mei_paths, output_mei_path): ''' PARAMETERS ---------- input_mei_paths {list}: list of mei paths to combine output_mei_path {String}: output file path of type .mei ''' self._input_mei_paths = input_mei_paths self._output_mei_path = output_mei_path if len(self._input_mei_paths): self._meidoc = XmlImport.documentFromFile(self._input_mei_paths[0]) else: self._meidoc = None
def analyze(MEI_filename): MEI_doc = XmlImport.documentFromFile(MEI_filename) MEI_tree = MEI_doc.getRootElement() has_editor_element_ = editorial.has_editor_element(MEI_tree) has_arranger_element_ = editorial.has_arranger_element(MEI_tree) editor_name_ = editorial.editor_name(MEI_tree) staff_list_ = staves.staff_list(MEI_tree) alternates_list_ = staves.alternates_list(staff_list_) return AnalyzeData(has_editor_element_, has_arranger_element_, editor_name_, staff_list_, alternates_list_, )
def massage_mei(in_file, out_file): try: analysis = make_analysis(in_file) MEI_instructions = TransformData( arranger_to_editor=True, obliterate_incipit=analysis.first_measure_empty, replace_longa=True, editorial_resp=analysis.has_arranger_element, alternates_list=analysis.alternates_list) old_MEI_doc = XmlImport.documentFromFile(in_file) new_MEI_doc = transform_mei(old_MEI_doc, MEI_instructions) XmlExport.meiDocumentToFile(new_MEI_doc, out_file) except Exception as ex: logging.critical(ex) logging.critical("Error during massaging " + in_file)
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): ''' Delete a given custos from the document. Also remove the element's bounding box information. ''' custos_id = str(self.get_argument("id", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) self.delete_custos(custos_id) XmlExport.write(self.mei, fname) self.set_status(200)
def OnLoadRects(self, event): ''' Loads rectangles from an mei file. Only loads bar boxes and not staff boxes yet. ''' fdlg = wx.FileDialog(self) if fdlg.ShowModal() == wx.ID_OK: print "File loaded: " + fdlg.GetPath() meidoc = XmlImport.documentFromFile(str(fdlg.GetPath())) # get all the measure elements measures = meidoc.getElementsByName('measure') # the measures have their coordinates stored in zones zones = meidoc.getElementsByName('zone') for m in measures: # the id of the zone that has the coordinates is stored in 'facs' facs = m.getAttribute('facs') print facs.getName(), facs.getValue() # there's a # sign preceding the id stored in the facs # attribute, remove it zone = meidoc.getElementById(facs.getValue()[1:]) # the coordinates stored in zone ulx = int(zone.getAttribute('ulx').getValue()) uly = int(zone.getAttribute('uly').getValue()) lrx = int(zone.getAttribute('lrx').getValue()) lry = int(zone.getAttribute('lry').getValue()) print ulx, uly, lrx, lry # make a new panel # Rect is looking for top (x,y) coordinates and length and # height, so we need to subtract the two corners self.scrolledwin.barpanels.append(\ Rect(ulx, uly, lrx - ulx, lry - uly)) self.scrolledwin.Refresh()
def Run(self): old_filename = self.mei_file if (len(old_filename) < EXT_LENGTH or old_filename[-EXT_LENGTH:] not in EXT): logging.info("No file extension provided; " + EXT[0] + " used.") old_filename += EXT[0] old_MEI_doc = XmlImport.documentFromFile(old_filename) logging.info('running test case ' + self.name + ' Input: ' + old_filename) new_MEI_doc = transform(old_MEI_doc, self.transform_data) new_filename = (old_filename[:-EXT_LENGTH] + self.outsuffix + '_' + old_filename[-EXT_LENGTH:]) status = XmlExport.meiDocumentToFile(new_MEI_doc, new_filename) if status: logging.info("Done. Transformed file saved as " + new_filename) pass else: logging.error("Transformation failed") return new_MEI_doc
def post(self, file): ''' Delete a division from the MEI document. Special consideration is taken when deleting divisions of form "final" ''' division_ids = str(self.get_argument("ids", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) for id in division_ids.split(","): division = self.mei.getElementById(id) self.delete_division(division) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' 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. ''' beforeid = str(self.get_argument("beforeid", None)) pname = str(self.get_argument("pname", "")) oct = str(self.get_argument("oct", "")) dot_form = self.get_argument("dotform", None) # Bounding box lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) punctum = self.create_new_punctum(pname, oct, dot_form) zone = self.get_new_zone(ulx, uly, lrx, lry) self.add_zone(punctum, zone) if beforeid is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(punctum) else: self.insert_punctum(punctum, beforeid) XmlExport.write(self.mei, fname) result = {"nid": punctum.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): """ Delete one or more <note> or <neume> elements. Pass in an argument called 'id' with a comma separated list of ids of note elements to delete. If the note's surrounding <nc> element is empty after this, remove it. If the nc's surrounding <neume> element is empty, remove it. Remove any <zone> elements whose ids are referenced by removed <neume>s. Does not reduce the size of the bounding box on a <zone> or change the neume type if it now has a different number of <note> elements. """ todelete = self.get_argument("ids", "") mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) self.do_delete(todelete) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Delete a doh or fah clef. Must also update pitched elements on the staff that are affected by the deletion of this clef element. ''' clefs_to_delete = json.loads(self.get_argument("data", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) for c in clefs_to_delete: clef = self.mei.getElementById(str(c["id"])) self.delete_clef(clef) self.update_pitched_elements(c["pitchInfo"]) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self): mei = self.request.files.get("mei", []) mei_img = self.request.files.get("mei_img", []) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) mei_directory_backup = os.path.abspath(conf.MEI_DIRECTORY_BACKUP) errors = "" mei_fn = "" if len(mei): mei_fn = mei[0]["filename"] contents = mei[0]["body"] try: mei = XmlImport.documentFromText(contents) if os.path.exists(os.path.join(mei_directory, mei_fn)): errors = "mei file already exists" else: # write to working directory and backup fp = open(os.path.join(mei_directory, mei_fn), "w") fp.write(contents) fp.close() fp = open(os.path.join(mei_directory_backup, mei_fn), "w") fp.write(contents) fp.close() except Exception, e: errors = "invalid mei file"
from pymei import XmlImport from gamera.core import * import PIL, os init_gamera() import pdb from optparse import OptionParser if __name__ == "__main__": usage = "usage: %prog [options] input_mei_file input_image_file output_folder" opts = OptionParser(usage) (options, args) = opts.parse_args() input_file = args[0] output_folder = args[2] mdoc = XmlImport.documentFromFile(input_file) neumes = mdoc.getElementsByName('neume') clefs = mdoc.getElementsByName('clef') divisions = mdoc.getElementsByName('division') custos = mdoc.getElementsByName('custos') systems = mdoc.getElementsByName('system') img = load_image(args[1]) if img.pixel_type_name != "OneBit": img = img.to_onebit() rgb = Image(img, RGB) neumecolour = RGBPixel(255, 0, 0)
def meitoalphatex(mei_path): alphatex = '' # read in the mei document meidoc = XmlImport.read(mei_path) mei = meidoc.getRootElement() ########################### # MetaData # ########################### title = mei.getDescendantsByName('title') if len(title): tex_title = "\\title \"%s\"\n" % title[0].getValue() alphatex += tex_title pers_name = mei.getDescendantsByName('persName') if len(pers_name): for p in pers_name: role = p.getAttribute('role').value if role == 'artist': tex_artist = "\\artist \"%s\"\n" % p.getValue() alphatex += tex_artist elif role == 'tabber': tex_copywrite = "\\copyright \"%s\"\n" % p.getValue() alphatex += tex_copywrite elif role == 'lyricist': tex_words = "\\words \"%s\"\n" % p.getValue() alphatex += tex_words staff_def = mei.getDescendantsByName('staffDef') if len(staff_def): # capo position if staff_def[0].hasAttribute('tab.capo'): capo = staff_def[0].getAttribute('tab.capo').value if int(capo) > 0: alphatex += '\\capo %s\n' % capo # this doesn't display alphatex += '\\words %s\n' % capo # hack this to display # guitar tuning pnames = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] if staff_def[0].hasAttribute('tab.strings'): strings = staff_def[0].getAttribute('tab.strings').value.split(' ') if len(strings) != 6: raise ValueError('Invalid number of strings: should be 6') # convert pitch names to those used in alphatab (flats vs. sharps) for i in range(len(strings)): pattern = re.compile('^([a-zA-z][#s])') match = pattern.match(strings[i]) if match: mei_pname = match.group() alpha_pname = pnames[pnames.index(mei_pname[0]) + 1 % len(pnames)] + 'b' oct = strings[i][-1] # replace string strings[i] = alpha_pname + oct alphatex += '\\tuning %s\n' % ' '.join(strings) # set midi instrument to play the tab with # 27 is Electric Guitar Clean alphatex += '\\instrument 27\n' # in alphatex the metadata and body are separated by a period character alphatex += '.\n' ########################### # Body # ########################### measures = mei.getDescendantsByName('measure') alpha_measures = [] for m in measures: measure_events = [] # only parse first staff (instrument), the instrument display staff = m.getChildrenByName('staff')[0] # only parse first layer (assume only one voice) layer = staff.getChildrenByName('layer')[0] score_events = layer.getChildren() for e in score_events: if e.getName() == 'chord': # get notes in this chord notes = e.getChildrenByName('note') alpha_notes = [ n.getAttribute('tab.fret').value + '.' + n.getAttribute('tab.string').value for n in notes ] alpha_chord = '(' + ' '.join(alpha_notes) + ')' measure_events.append(alpha_chord) elif e.getName() == 'note': alpha_note = e.getAttribute( 'tab.fret').value + '.' + e.getAttribute( 'tab.string').value measure_events.append(alpha_note) alpha_measures.append(' '.join(measure_events)) alphatex += ' |\n'.join(alpha_measures) return alphatex
def __init__(self, filename): self.mei = XmlImport.read(filename) self.filename = filename