def manuscript_full_json (passage_or_id, hs_hsnr_id): """Endpoint. Serve information about a manuscript. :param string hs_hsnr_id: The hs, hsnr or id of the manuscript. """ auth () hs_hsnr_id = request.args.get ('ms_id') or hs_hsnr_id chapter = request.args.get ('range') or 'All' 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) json = ms.to_json () json['length'] = ms.get_length (passage, chapter) # Get the attestation(s) of the manuscript (may be uncertain eg. a/b/c) res = execute (conn, """ SELECT labez, clique, labez_clique FROM apparatus_view_agg WHERE ms_id = :ms_id AND pass_id = :pass_id """, dict (parameters, ms_id = ms.ms_id, pass_id = passage.pass_id)) json['labez'], json['clique'], json['labez_clique'] = res.fetchone () # Get the affinity of the manuscript to all manuscripts res = execute (conn, """ SELECT avg (a.affinity) as aa, percentile_cont(0.5) WITHIN GROUP (ORDER BY a.affinity) as ma FROM affinity a WHERE a.ms_id1 = :ms_id1 AND a.rg_id = :rg_id """, dict (parameters, ms_id1 = ms.ms_id, rg_id = rg_id)) json['aa'], json['ma'] = res.fetchone () # Get the affinity of the manuscript to MT # # For a description of mt and mtp see the comment in # ActsMsListValPh3.pl and # http://intf.uni-muenster.de/cbgm/actsPh3/guide_en.html#Ancestors json['mt'], json['mtp'] = 0.0, 0.0 res = execute (conn, """ SELECT a.affinity as mt, a.equal::float / c.length as mtp FROM affinity a JOIN ms_ranges c ON (a.ms_id1, a.rg_id) = (c.ms_id, c.rg_id) WHERE a.ms_id1 = :ms_id1 AND a.ms_id2 = 2 AND a.rg_id = :rg_id """, dict (parameters, ms_id1 = ms.ms_id, rg_id = rg_id)) if res.rowcount > 0: json['mt'], json['mtp'] = res.fetchone () return make_json_response (json)
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)))