def optimal_substemma_csv (): """Do an exhaustive search for the combination among a given set of ancestors that best explains a given manuscript. """ if current_app.config.val is None: current_app.config.val = init (current_app.config.dba) val = current_app.config.val with current_app.config.dba.engine.begin () as conn: # the manuscript to explain ms = Manuscript (conn, request.args.get ('ms')) # get the selected set of ancestors and build all combinations of that set selected = [ Manuscript (conn, anc_id) for anc_id in (request.args.get ('selection') or '').split () ] combinations = [] i = 0 for l in range (len (selected)): for c in itertools.combinations (selected, l + 1): combinations.append (Combination (c, i)) i += 1 explain_matrix = build_explain_matrix (conn, val, ms.ms_id) _optimal_substemma (ms.ms_id, explain_matrix, combinations, mode = 'search') res = [c.to_csv () for c in combinations] return csvify (_OptimalSubstemmaRow._fields, list (map (_OptimalSubstemmaRow._make, res)))
def attesting_csv (passage_or_id, labez): """ Serve all relatives of all mss. attesting labez at passage. """ auth () with current_app.config.dba.engine.begin () as conn: passage = Passage (conn, passage_or_id) res = execute (conn, """ SELECT ms_id, hs, hsnr FROM apparatus_view WHERE pass_id = :pass_id AND labez = :labez ORDER BY hsnr """, dict (parameters, pass_id = passage.pass_id, labez = labez)) Attesting = collections.namedtuple ('Attesting', 'ms_id hs hsnr') return csvify (Attesting._fields, list (map (Attesting._make, res)))
def optimal_substemma_detail_csv(): """Report details about one combination of ancestors. """ if current_app.config.val is None: current_app.config.val = init(current_app.config.dba) val = current_app.config.val with current_app.config.dba.engine.begin() as conn: # the manuscript to explain ms = Manuscript(conn, request.args.get('ms')) # get the selected set of ancestors selected = [ Manuscript(conn, anc_id) for anc_id in (request.args.get('selection') or '').split() ] combinations = [Combination(selected, 0)] explain_matrix = build_explain_matrix(conn, val, ms.ms_id) _optimal_substemma(ms.ms_id, explain_matrix, combinations, mode='detail') res = execute( conn, """ SELECT 'unknown' as type, p.pass_id, p.begadr, p.endadr, v.labez_clique, v.lesart FROM passages p JOIN apparatus_cliques_view v USING (pass_id) WHERE v.ms_id = :ms_id AND pass_id IN :unknown_pass_ids UNION SELECT 'open' as type, p.pass_id, p.begadr, p.endadr, v.labez_clique, v.lesart FROM passages p JOIN apparatus_cliques_view v USING (pass_id) WHERE v.ms_id = :ms_id AND pass_id IN :open_pass_ids """, dict(ms_id=ms.ms_id, unknown_pass_ids=combinations[0].unknown_indices or (-1, ), open_pass_ids=combinations[0].open_indices or (-1, ))) return csvify( _OptimalSubstemmaDetailRowCalcFields._fields, list(map(_OptimalSubstemmaDetailRowCalcFields._make, res)))
def attesting_csv(passage_or_id, labez): """ Serve all relatives of all mss. attesting labez at passage. """ auth() with current_app.config.dba.engine.begin() as conn: passage = Passage(conn, passage_or_id) res = execute( conn, """ SELECT ms_id, hs, hsnr FROM apparatus_view WHERE pass_id = :pass_id AND labez = :labez ORDER BY hsnr """, dict(parameters, pass_id=passage.pass_id, labez=labez)) Attesting = collections.namedtuple('Attesting', 'ms_id hs hsnr') return csvify(Attesting._fields, list(map(Attesting._make, res)))
def optimal_substemma_detail_csv (): """Report details about one combination of ancestors. """ if current_app.config.val is None: current_app.config.val = init (current_app.config.dba) val = current_app.config.val with current_app.config.dba.engine.begin () as conn: # the manuscript to explain ms = Manuscript (conn, request.args.get ('ms')) # get the selected set of ancestors selected = [ Manuscript (conn, anc_id) for anc_id in (request.args.get ('selection') or '').split () ] combinations = [Combination (selected, 0)] explain_matrix = build_explain_matrix (conn, val, ms.ms_id) _optimal_substemma (ms.ms_id, explain_matrix, combinations, mode = 'detail') res = execute (conn, """ SELECT 'unknown' as type, p.pass_id, p.begadr, p.endadr, v.labez_clique, v.lesart FROM passages p JOIN apparatus_cliques_view v USING (pass_id) WHERE v.ms_id = :ms_id AND pass_id IN :unknown_pass_ids UNION SELECT 'open' as type, p.pass_id, p.begadr, p.endadr, v.labez_clique, v.lesart FROM passages p JOIN apparatus_cliques_view v USING (pass_id) WHERE v.ms_id = :ms_id AND pass_id IN :open_pass_ids """, dict ( ms_id = ms.ms_id, unknown_pass_ids = combinations[0].unknown_indices, open_pass_ids = combinations[0].open_indices )) return csvify (_OptimalSubstemmaDetailRowCalcFields._fields, list (map (_OptimalSubstemmaDetailRowCalcFields._make, res)))
def optimal_substemma_csv(): """Do an exhaustive search for the combination among a given set of ancestors that best explains a given manuscript. """ if current_app.config.val is None: current_app.config.val = init(current_app.config.dba) val = current_app.config.val with current_app.config.dba.engine.begin() as conn: # the manuscript to explain ms = Manuscript(conn, request.args.get('ms')) # get the selected set of ancestors and build all combinations of that set selected = [ Manuscript(conn, anc_id) for anc_id in (request.args.get('selection') or '').split() ] combinations = [] i = 0 for l in range(len(selected)): for c in itertools.combinations(selected, l + 1): combinations.append(Combination(c, i)) i += 1 explain_matrix = build_explain_matrix(conn, val, ms.ms_id) _optimal_substemma(ms.ms_id, explain_matrix, combinations, mode='search') res = [c.to_csv() for c in combinations] return csvify(_OptimalSubstemmaRow._fields, list(map(_OptimalSubstemmaRow._make, res)))
def relatives_csv (passage_or_id, hs_hsnr_id): """Output a table of the nearest relatives of a manuscript. Output a table of the nearest relatives/ancestors/descendants of a manuscript and what they attest. """ auth () type_ = request.args.get ('type') or 'rel' chapter = request.args.get ('range') or 'All' limit = int (request.args.get ('limit') or 0) labez = request.args.get ('labez') or 'all' mode = request.args.get ('mode') or 'sim' include = request.args.getlist ('include[]') or [] fragments = request.args.getlist ('fragments[]') or [] view = 'affinity_view' if mode == 'rec' else 'affinity_p_view' where = '' if type_ == 'anc': where = ' AND older < newer' if type_ == 'des': where = ' AND older >= newer' if labez == 'all': where += " AND labez !~ '^z'" elif labez == 'all+lac': pass else: where += " AND labez = '%s'" % labez if 'fragments' in fragments: frag_where = '' else: frag_where = 'AND aff.common > aff.ms1_length / 2' limit = '' if limit == 0 else ' LIMIT %d' % limit with current_app.config.dba.engine.begin () as conn: passage = Passage (conn, passage_or_id) ms = Manuscript (conn, hs_hsnr_id) rg_id = passage.range_id (chapter) exclude = get_excluded_ms_ids (conn, include) # Get the X most similar manuscripts and their attestations res = execute (conn, """ /* get the LIMIT closest ancestors for this node */ WITH ranks AS ( SELECT ms_id1, ms_id2, rank () OVER (ORDER BY affinity DESC, common, older, newer DESC, ms_id2) AS rank, affinity FROM {view} aff WHERE ms_id1 = :ms_id1 AND aff.rg_id = :rg_id AND ms_id2 NOT IN :exclude AND newer > older {frag_where} ORDER BY affinity DESC ) SELECT r.rank, aff.ms_id2 as ms_id, ms.hs, ms.hsnr, aff.ms2_length, aff.common, aff.equal, aff.older, aff.newer, aff.unclear, aff.common - aff.equal - aff.older - aff.newer - aff.unclear as norel, CASE WHEN aff.newer < aff.older THEN '' WHEN aff.newer = aff.older THEN '-' ELSE '>' END as direction, aff.affinity, a.labez FROM {view} aff JOIN apparatus_view_agg a ON aff.ms_id2 = a.ms_id JOIN manuscripts ms ON aff.ms_id2 = ms.ms_id LEFT JOIN ranks r ON r.ms_id2 = aff.ms_id2 WHERE aff.ms_id2 NOT IN :exclude AND aff.ms_id1 = :ms_id1 AND aff.rg_id = :rg_id AND aff.common > 0 AND a.pass_id = :pass_id {where} {frag_where} ORDER BY affinity DESC, r.rank, newer DESC, older DESC, hsnr {limit} """, dict (parameters, where = where, frag_where = frag_where, ms_id1 = ms.ms_id, hsnr = ms.hsnr, pass_id = passage.pass_id, rg_id = rg_id, limit = limit, view = view, exclude = exclude)) Relatives = collections.namedtuple ( 'Relatives', 'rank ms_id hs hsnr length common equal older newer unclear norel direction affinity labez' ) return csvify (Relatives._fields, list (map (Relatives._make, res)))
def relatives_csv(passage_or_id, hs_hsnr_id): """Output a table of the nearest relatives of a manuscript. Output a table of the nearest relatives/ancestors/descendants of a manuscript and what they attest. """ auth() type_ = request.args.get('type') or 'rel' limit = int(request.args.get('limit') or 0) labez = request.args.get('labez') or 'all' mode = request.args.get('mode') or 'sim' include = request.args.getlist('include[]') or [] fragments = request.args.getlist('fragments[]') or [] view = 'affinity_view' if mode == 'rec' else 'affinity_p_view' where = '' if type_ == 'anc': where = ' AND older < newer' if type_ == 'des': where = ' AND older >= newer' if labez == 'all': where += " AND labez !~ '^z'" elif labez == 'all+lac': pass else: where += " AND labez = '%s'" % labez if 'fragments' in fragments: frag_where = '' else: frag_where = 'AND aff.common > aff.ms1_length / 2' limit = '' if limit == 0 else ' LIMIT %d' % limit with current_app.config.dba.engine.begin() as conn: passage = Passage(conn, passage_or_id) ms = Manuscript(conn, hs_hsnr_id) rg_id = passage.request_rg_id(request) exclude = get_excluded_ms_ids(conn, include) # Get the X most similar manuscripts and their attestations res = execute( conn, """ /* get the LIMIT closest ancestors for this node */ WITH ranks AS ( SELECT ms_id1, ms_id2, rank () OVER (ORDER BY affinity DESC, common, older, newer DESC, ms_id2) AS rank, affinity FROM {view} aff WHERE ms_id1 = :ms_id1 AND aff.rg_id = :rg_id AND ms_id2 NOT IN :exclude AND newer > older {frag_where} ORDER BY affinity DESC ) SELECT r.rank, aff.ms_id2 as ms_id, ms.hs, ms.hsnr, aff.ms2_length, aff.common, aff.equal, aff.older, aff.newer, aff.unclear, aff.common - aff.equal - aff.older - aff.newer - aff.unclear as norel, CASE WHEN aff.newer < aff.older THEN '' WHEN aff.newer = aff.older THEN '-' ELSE '>' END as direction, aff.affinity, a.labez, a.certainty FROM {view} aff JOIN apparatus_view_agg a ON aff.ms_id2 = a.ms_id JOIN manuscripts ms ON aff.ms_id2 = ms.ms_id LEFT JOIN ranks r ON r.ms_id2 = aff.ms_id2 WHERE aff.ms_id2 NOT IN :exclude AND aff.ms_id1 = :ms_id1 AND aff.rg_id = :rg_id AND aff.common > 0 AND a.pass_id = :pass_id {where} {frag_where} ORDER BY affinity DESC, r.rank, newer DESC, older DESC, hsnr {limit} """, dict(parameters, where=where, frag_where=frag_where, ms_id1=ms.ms_id, hsnr=ms.hsnr, pass_id=passage.pass_id, rg_id=rg_id, limit=limit, view=view, exclude=exclude)) Relatives = collections.namedtuple( 'Relatives', 'rank ms_id hs hsnr length common equal older newer unclear norel direction affinity labez certainty' ) return csvify(Relatives._fields, list(map(Relatives._make, res)))
def comparison_detail_csv (): """Endpoint. Serve a CSV table. (see also :func:`comparison_detail`)""" auth () return csvify (_ComparisonDetailRowCalcFields._fields, comparison_detail ())
def comparison_summary_csv (): """Endpoint. Serve a CSV table. (see also :func:`comparison_summary`)""" auth () return csvify (_ComparisonRowCalcFields._fields, comparison_summary ())