def __post_init__(self): stream = music21.converter.parse(self.data) self.xml = stream_to_xml(stream) self.notes = [ Note(n.offset, n.offset + n.duration.quarterLength, n.pitch.ps, i) for i, n in enumerate(indexers.NotePointSet(stream)) ] self.windows = list(generate_normalized_windows(stream, WINDOW))
def __post_init__(self): self.music21_xml = symbolic_data_to_m21_xml(self.data) stream = music21.converter.parse(self.music21_xml) self.notes = [ piece.Note(n.offset, n.offset + n.duration.quarterLength, n.pitch.ps, i) for i, n in enumerate(indexers.NotePointSet(stream)) ]
def __post_init__(self): stream = music21.converter.parse(base64.b64decode(self.data)) stream.makeNotation(inPlace=True) xml = m21_score_to_xml_write(stream) self.data = xml self.notes = [ Note(n.offset, n.offset + n.duration.quarterLength, n.pitch.ps, i) for i, n in enumerate(indexers.NotePointSet(stream)) ]
def generate_normalized_windows(stream, window_size): notes = [ Note(n.offset, n.offset + n.duration.quarterLength, n.pitch.ps, i) for i, n in enumerate(indexers.NotePointSet(stream)) ] for i in range(min(len(notes) - window_size + 1, len(notes))): window = notes[i:i + window_size] bases = [(window[0], window[i]) for i in range(1, len(window))] for u, v in ((u, v) for u, v in bases if u.onset != v.onset): yield (u, v), normalize(window, (u, v))
def search(): db_conn = connect_to_psql() for arg in (x.name for x in fields(QueryArgs)): missing = [] if not request.args.get(arg): missing.append(arg) if missing: return Response(f"Missing GET parameter(s): {missing}", status=400) try: page = int(request.args.get("page")) rpp = int(request.args.get("rpp")) tnps = request.args.get("tnps").split(",") tnps_ints = list(map(int, tnps)) tnps_ints[1] += 1 # increase range to include end intervening = request.args.get("intervening").split(",") intervening_ints = tuple(map(int, intervening)) inexact = request.args.get("inexact").split(",") inexact_ints = tuple(map(int, inexact)) collection = int(request.args.get("collection")) query_str = request.args.get("query") qargs = QueryArgs(rpp, page, tnps, intervening, inexact, collection, query_str) except ValueError as e: return Response( f"Failed to parse parameter(s) to integer, got exception {str(e)}", status=400) query_str = request.args.get("query") query_stream = indexers.parse(query_str) query_nps = indexers.NotePointSet(query_stream) query_notes = [(n.offset, n.pitch.ps) for n in query_nps] query_pb_notes = [ piece.Note(n[0], None, n[1], i).to_pb() for i, n in enumerate(query_notes) ] resp = requests.get(POSTGREST_URI + "/rpc/search", params=('query=' + qstring(query_pb_notes))).json() occurrences = [occurrence.occ_to_occpb(occ) for occ in resp] occfilters = OccurrenceFilters(transpositions=range(*tnps_ints), intervening=intervening_ints, inexact=inexact_ints) search_response = build_response( db_conn, filter_occurrences(occurrences, query_pb_notes, occfilters), qargs) if request.content_type == "application/json": return jsonify(search_response) else: return render_template("search.html", searchResponse=search_response)
def query(stream): m = [] query_length = len(indexers.NotePointSet(stream)) for (u, v), window in generate_normalized_windows(stream, query_length): print(window) matches = {} for n in window: postings = BINS.get(n.__hash__(), ()) for (u, v), j in postings: key = (u, v) matches[key] = matches.get(key, (u, )) + ((j, n.index), ) m.append(matches) return set((c[key]) for c in m for key in c if len(c[key]) >= query_length)
def pointset(filename, outname): """ Converts a musicxml file to its point set image representation """ st = music21.converter.parse(filename) nps = indexers.NotePointSet(st) offsets = np.array([n.offset for n in nps]) pitches = np.array([n.pitch.ps for n in nps]) pointset_plot = plt.scatter(offsets, pitches) plt.xlabel("Quarter-length offset") plt.ylabel("Chromatic pitch") plt.savefig(outname)
def query_postgres(stream): conn = psycopg2.connect("") matches = {} query_length = len(indexers.NotePointSet(stream)) (u, v), window = next(generate_normalized_windows(stream, query_length)) with conn, conn.cursor() as cur: for n in window: cur.execute( f"SELECT * FROM Posting WHERE n ~= '{(n.onset, n.pitch)}'") postings = cur.fetchall() for _, _, pid, u, v, j in postings: key = (pid, u, v) matches[key] = matches.get(key, (u, )) + ((j, n.index), ) return set(v for v in matches.values() if len(v) >= query_length)
def pointsets(filenames, outname): fig, ax = plt.subplots() colours = cycle(('#a50000', '#00a500', '#0000a5')) for label, filename, colour in zip(filenames[::2], filenames[1::2], colours): st = music21.converter.parse(filename) nps = indexers.NotePointSet(st) offsets = np.array([n.offset for n in nps]) pitches = np.array([n.pitch.ps for n in nps]) ax.scatter(offsets, pitches, c=colour, label=label) ax.legend() ax.grid(True) plt.xlabel("Quarter-length offset") plt.ylabel("Chromatic pitch") fig.savefig(outname)