Esempio n. 1
0
def favourite():
    if re.search(r'^\d+$', request.form['vf_id']):
        vf_id = request.form['vf_id']
        if vf_id is None:
            flash('Cannot mark a variant without id! Please contact us.', 'w3-pale-red')
            return 'notok'
        # print(vf_id)
        # g.user['id']
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        if request.form['marker'] == 'mark':
            curs.execute(
                "INSERT INTO mobiuser_favourite (mobiuser_id, feature_id) VALUES (%s, %s)",
                (g.user['id'], vf_id)
            )
        else:
            curs.execute(
                "DELETE FROM mobiuser_favourite WHERE mobiuser_id = %s AND feature_id = %s",
                (g.user['id'], vf_id)
            )
        db.commit()
        close_db()
        return 'ok'
    else:
        flash('Cannot mark a variant without id! Please contact us.', 'w3-pale-red')
        return 'notok'
Esempio n. 2
0
def index():
    # print(app.config['RUN_MODE'])
    # check vv
    md_api_url = '{0}{1}'.format(request.host_url[:-1],
                                 url_for('api.check_vv_instance'))
    vv_instance = json.loads(
        http.request('GET', md_api_url).data.decode('utf-8'))
    # count genes
    db = get_db()
    curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
    curs.execute("""
        SELECT COUNT(DISTINCT(gene_symbol)) AS gene, COUNT(refseq) AS transcript
        FROM gene
        WHERE variant_creation = 'ok'
        """)
    res = curs.fetchone()
    if res is None:
        close_db()
        error = 'There is a problem with the number of genes.'
        flash(error, 'w3-pale-red')
        md_utilities.send_error_email(
            md_utilities.prepare_email_html(
                'MobiDetails PostGreSQL error',
                '<p>There is a problem with the number of genes.\
<br /> in {}</p>'.format(os.path.basename(__file__))),
            '[MobiDetails - PostGreSQL Error]')
    else:
        close_db()
        return render_template('md/index.html',
                               run_mode=md_utilities.get_running_mode(),
                               nb_genes=res['gene'],
                               nb_isoforms=res['transcript'],
                               vv_instance=vv_instance)
Esempio n. 3
0
def variant_list(list_name):
    if len(list_name) < 31 and \
            re.search(r'^[\w]+$', list_name):
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        curs.execute(
            """
            SELECT a.variant_ids, b.username, a.creation_date, a.list_name
            FROM variants_groups a, mobiuser b
            WHERE a.mobiuser_id = b.id AND list_name = %s
            """, (list_name, ))
        res = curs.fetchone()
        # we've got an ARRAY of variants_ids and want to query on them...
        if res:
            res_ids_string = "("
            for id in res['variant_ids']:
                res_ids_string += "{}, ".format(id)
            res_ids_string = res_ids_string[:-2]
            res_ids_string += ")"
            # print(res_ids_string)
            curs.execute("""
                SELECT a.id, a.c_name, a.p_name, a.gene_symbol, a.refseq, a.creation_user, a.creation_date, b.username
                FROM variant_feature a, mobiuser b
                WHERE  a.creation_user = b.id AND a.id IN {0}
                """.format(res_ids_string))
            variants = curs.fetchall()
            close_db()
            return render_template('md/variant_multiple.html',
                                   variants=variants,
                                   unique_url_info=res)
        else:
            close_db()
            return render_template('errors/404.html'), 404
    else:
        return render_template('errors/404.html'), 404
Esempio n. 4
0
def load_logged_in_user():
    user_id = session.get('user_id')

    if user_id is None:
        g.user = None
    else:
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        curs.execute("SELECT * FROM mobiuser WHERE id = %s", (user_id, ))
        g.user = curs.fetchone()
    close_db()
Esempio n. 5
0
def forgot_pass():
    if (md_utilities.get_running_mode() == 'maintenance'):
        return render_template('md/index.html',
                               run_mode=md_utilities.get_running_mode())
    if request.method == 'GET':
        return render_template('auth/forgot_pass.html')
    elif request.method == 'POST':
        error = None
        email = request.form['email']
        if not re.search(r'^[a-zA-Z0-9\._%\+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
                         email):
            error = 'The email address does not look valid.'
            flash(error, 'w3-pale-red')
            return render_template('auth/forgot_pass.html')
        else:
            db = get_db()
            curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            curs.execute("SELECT * FROM mobiuser WHERE email = %s", (email, ))
            user = curs.fetchone()
            if user is None:
                close_db()
                error = """
                Your email address {} seems to be unknown by the system.
                """.format(email)
                flash(error, 'w3-pale-red')
                return render_template('auth/forgot_pass.html')
            # message, mail_object, receiver
            md_utilities.send_email(
                md_utilities.prepare_email_html(
                    'MobiDetails - Reset your password', """
                    Dear {0},
                    <p>please follow the link below to reset your MobiDetails password:</p>
                    <p><a href="{1}{2}" title="Reset your MD password">
                    Reset your MD password</a></p>
                    <p>If you do not know why you receive this email,
                    do not follow the link and please alert
                    [email protected].</p><br />
                    """.format(
                        user['username'], request.host_url.rstrip('/'),
                        url_for('auth.reset_password',
                                mobiuser_id=user['id'],
                                api_key=user['api_key'],
                                ts=datetime.timestamp(datetime.now()))),
                    False), '[MobiDetails - Password reset]', [email])
            flash(
                """
                Please check your e-mail inbox.
                You should have received a message with a link
                to reset your password
                """, 'w3-pale-green')
            close_db()
            return render_template('auth/forgot_pass.html')
    return render_template('md/unknown.html')
Esempio n. 6
0
def genes():
    db = get_db()
    curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
    curs.execute("""
        SELECT DISTINCT(gene_symbol)
        FROM gene
        ORDER BY gene_symbol
        """)
    genes = curs.fetchall()
    close_db()
    if genes:
        return render_template('md/genes.html',
                               run_mode=md_utilities.get_running_mode(),
                               genes=genes)
    else:
        return render_template('md/unknown.html',
                               run_mode=md_utilities.get_running_mode())
Esempio n. 7
0
def defgen():
    genome_regexp = md_utilities.regexp['genome']
    if re.search(r'^\d+$', request.form['vfid']) and \
            re.search(rf'^{genome_regexp}$', request.form['genome']):
        variant_id = request.form['vfid']
        genome = request.form['genome']
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        # get all variant_features and gene info
        curs.execute(
            "SELECT * FROM variant_feature a, variant b, gene c WHERE \
            a.id = b.feature_id AND a.gene_name = c.name AND a.id = '{0}'\
            AND b.genome_version = '{1}'".format(variant_id, genome)
        )
        vf = curs.fetchone()
        file_content = "GENE;VARIANT;A_ENREGISTRER;ETAT;RESULTAT;VARIANT_P;VARIANT_C;ENST;NM;POSITION_GENOMIQUE;CLASSESUR5;CLASSESUR3;COSMIC;RS;REFERENCES;CONSEQUENCES;COMMENTAIRE;CHROMOSOME;GENOME_REFERENCE;NOMENCLATURE_HGVS;LOCALISATION;SEQUENCE_REF;LOCUS;ALLELE1;ALLELE2\r\n"

        file_content += "{0};{1}.{2}:c.{3};;;;p.{4};c.{3};{5};{1}.{2};{6};;;;rs{7};;{8};;chr{9};{10};chr{9}:g.{11};{12} {13};;;;\r\n".format(
            vf['gene_name'][0], vf['gene_name'][1], vf['nm_version'], vf['c_name'], vf['p_name'], vf['enst'], vf['pos'],
            vf['dbsnp_id'], vf['prot_type'], vf['chr'], genome, vf['g_name'], vf['start_segment_type'], vf['start_segment_number']
        )
        # print(file_content)
        app_path = os.path.dirname(os.path.realpath(__file__))
        file_loc = "defgen/{0}-{1}-{2}{3}-{4}.csv".format(genome, vf['chr'], vf['pos'], vf['pos_ref'], vf['pos_alt'])
        defgen_file = open("{0}/static/{1}".format(app_path, file_loc), "w")
        defgen_file.write(file_content)
        close_db()
        return render_template('ajax/defgen.html', variant="{0}.{1}:c.{2}".format(
            vf['gene_name'][1], vf['nm_version'], vf['c_name']), defgen_file=file_loc, genome=genome)
    else:
        # close_db()
        md_utilities.send_error_email(
            md_utilities.prepare_email_html(
                'MobiDetails Ajax error',
                '<p>DefGen file generation failed in {} (no variant_id)</p>'.format(
                    os.path.basename(__file__)
                )
            ),
            '[MobiDetails - Ajax Error]'
        )
        return '<div class="w3-blue w3-ripple w3-padding-16 w3-large w3-center" style="width:100%">Impossible to create DEFGEN file</div>'
Esempio n. 8
0
def activate(mobiuser_id, api_key):
    if (md_utilities.get_running_mode() == 'maintenance'):
        return render_template('md/index.html',
                               run_mode=md_utilities.get_running_mode())
    if isinstance(mobiuser_id, int) and \
            isinstance(api_key, str):
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        curs.execute(
            """
            SELECT id, api_key, activated
            FROM mobiuser WHERE id = %s AND api_key = %s
            """, (mobiuser_id, api_key))
        user = curs.fetchone()
        if user is None:
            message_body = """
            <p>Account activation exception</p><p>Recived API key: {0} and mobiuser_id: {1} from {2}
            """.format(api_key, mobiuser_id, request.remote_addr)
            md_utilities.send_error_email(
                md_utilities.prepare_email_html('MobiDetails error',
                                                message_body),
                '[MobiDetails - Activation Error]')
            flash(
                'API key and user id do not seem to fit. An admin has been warned',
                'w3-pale-red')
            close_db()
            return render_template('md/index.html')
        else:
            if user['activated'] is False and \
                    user['api_key'] == api_key and \
                    user['id'] == mobiuser_id:
                curs.execute(
                    "UPDATE mobiuser SET activated = 't' WHERE \
                    id = %s AND api_key = %s", (user['id'], user['api_key']))
                db.commit()
                flash(
                    'Your account has been activated, you may now log in using your email address.',
                    'w3-pale-green')
                close_db()
                return render_template('auth/login.html')
    return render_template('md/unknown.html')
Esempio n. 9
0
def api_variant_create_rs(rs_id=None, caller=None, api_key=None):
     # get params
    if request.args.get('rs_id') and \
            request.args.get('caller') and \
            request.args.get('api_key'):
        rs_id = request.args.get('rs_id', type=str)
        caller = request.args.get('caller', type=str)
        api_key = request.args.get('api_key', type=str)
    elif 'rs_id' in request.form and \
            'caller' in request.form and \
            'api_key' in request.form:
        rs_id = request.form['rs_id']
        caller = request.form['caller']
        api_key = request.form['api_key']
    else:
        if caller == 'cli':
            return jsonify(mobidetails_error='I cannot fetch the right parameters')
        else:
            flash('I cannot fetch the right parameters for MD API.', 'w3-pale-red')
            return redirect(url_for('md.index'))
    db = get_db()
    curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
    # check api key
    res_check_api_key = md_utilities.check_api_key(db, api_key)
    if 'mobidetails_error' in res_check_api_key:
        if caller == 'cli':
            return jsonify(res_check_api_key)
        else:
            flash(res_check_api_key['mobidetails_error'], 'w3-pale-red')
            return redirect(url_for('md.index'))
    else:
        g.user = res_check_api_key['mobiuser']
    # check caller
    if md_utilities.check_caller(caller) == 'Invalid caller submitted':
        if caller == 'cli':
            return jsonify(mobidetails_error='Invalid caller submitted')
        else:
            flash('Invalid caller submitted to the API.', 'w3-pale-red')
            return redirect(url_for('md.index'))
    # check rs_id
    trunc_rs_id = None
    match_obj = re.search(r'^rs(\d+)$', rs_id)
    if match_obj:
        trunc_rs_id = match_obj.group(1)
        # check if rsid exists
        curs.execute(
            "SELECT a.c_name, a.id, b.name[2] as nm, b.nm_version FROM variant_feature a, gene b WHERE a.gene_name = b.name AND a.dbsnp_id = %s",
            (trunc_rs_id,)
        )
        res_rs = curs.fetchall()
        if res_rs:
            vars_rs = {}
            for var in res_rs:
                current_var = '{0}.{1}:c.{2}'.format(var['nm'], var['nm_version'], var['c_name'])
                vars_rs[current_var] = {
                    'mobidetails_id': var['id'],
                    'url': '{0}{1}'.format(
                        request.host_url[:-1],
                        url_for('md.variant', variant_id=var['id'])
                    )
                }
            if caller == 'cli':
                    return jsonify(vars_rs)
            else:
                if len(res_rs) == 1:
                    return redirect(url_for('md.variant', variant_id=res_rs['id']))
                else:                  
                    return redirect(url_for('md.variant_multiple', vars_rs=vars_rs))
        # use putalyzer to get HGVS noemclatures
        http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
        mutalyzer_url = "{0}getdbSNPDescriptions?rs_id={1}".format(
            md_utilities.urls['mutalyzer_api_json'], rs_id
        )
        # returns sthg like
        # ["NC_000011.10:g.112088901C>T", "NC_000011.9:g.111959625C>T", "NG_012337.3:g.7055C>T", "NM_003002.4:c.204C>T", "NM_003002.3:c.204C>T", "NM_001276506.2:c.204C>T", "NM_001276506.1:c.204C>T", "NR_077060.2:n.239C>T", "NR_077060.1:n.288C>T", "NM_001276504.2:c.87C>T", "NM_001276504.1:c.87C>T", "NG_033145.1:g.2898G>A"]
        try:
            mutalyzer_data = json.loads(http.request('GET', mutalyzer_url).data.decode('utf-8'))
        except Exception:
            close_db()
            if caller == 'cli':
                return jsonify(mobidetails_error='Mutalyzer did not return any value for the variant {}.'.format(rs_id))
            else:
                flash('Mutalyzer did not return any value for the variant {}'.format(rs_id), 'w3-pale-red')
                return redirect(url_for('md.index'))
        # print(mutalyzer_data)
        md_response = {}
        # md_nm = list of NM recorded in MD, to be sure not to consider unexisting NM acc no
        # md_nm = []
        hgvs_nc = []
        gene_names = []
        # can_nm = None
        for hgvs in mutalyzer_data:  # works for exonic variants because mutalyzer returns no NM for intronic variants
            variant_regexp = md_utilities.regexp['variant']
            # match_nm = re.search(rf'^(NM_\d+)\.\d+:c\.({variant_regexp})$', hgvs)
            # if match_nm:
            #     current_nm = match_nm.group(1)
            #     # get list of NM recorded in MD
            #     if not md_nm:
            #         curs.execute(
            #             "SELECT name[2] as nm FROM gene WHERE name[1] = (SELECT name[1] FROM gene WHERE name[2] = %s)",
            #             (current_nm,)
            #         )
            #         res_nm_all = curs.fetchall()
            #         if res_nm_all:
            #             for nm in res_nm_all:
            #                 md_nm.append(nm[0])
            #     if current_nm in md_nm:
            #         # check if variant with same name already recorded => at least we do not query multiple times for these
            #         curs.execute(
            #             "SELECT id FROM variant_feature WHERE dbsnp_id = %s AND c_name = %s",
            #             (trunc_rs_id, match_nm.group(2),)
            #         )
            #         res_known = curs.fetchall()
            #         if not res_known:
            #             # get gene and MD current NM version
            #             curs.execute(
            #                 "SELECT nm_version FROM gene WHERE name[2] = %s",
            #                 (current_nm,)
            #             )
            #             res_nm = curs.fetchone()
            #             if res_nm:
            #                 md_api_url = '{0}{1}'.format(request.host_url[:-1], url_for('api.api_variant_create'))
            #                 variant_chgvs = '{0}.{1}:c.{2}'.format(current_nm, res_nm['nm_version'], match_nm.group(2))
            #                 data = {
            #                     'variant_chgvs': urllib.parse.quote(variant_chgvs),
            #                     'caller': 'cli',
            #                     'api_key': api_key
            #                 }
            #                 try:
            #                     md_response[variant_chgvs] = json.loads(http.request('POST', md_api_url, headers=md_utilities.api_agent, fields=data).data.decode('utf-8'))
            #                 except Exception:
            #                     md_response[variant_chgvs] = {'mobidetails_error': 'MobiDetails returned an unexpected error for your request {0}: {1}'.format(rs_id, variant_chgvs)}
            #             else:
            #                 continue
            #         else:
            #             continue
            #     else:
            #         continue
            # intronic variant?
            # we need HGVS genomic to launch the API but also the gene - got from NG
            # f-strings usage https://stackoverflow.com/questions/6930982/how-to-use-a-variable-inside-a-regular-expression
            # https://www.python.org/dev/peps/pep-0498/
            match_nc = re.search(rf'^(NC_0000\d{{2}}\.\d{{1,2}}):g\.({variant_regexp})$', hgvs)
            if match_nc and \
                    not md_response:
                # if hg38, we keep it in a variable that can be useful later
                curs.execute(
                    "SELECT name, genome_version FROM chromosomes WHERE ncbi_name = %s",
                    (match_nc.group(1),)
                )
                res_chr = curs.fetchone()
                if res_chr and \
                        res_chr['genome_version'] == 'hg38':
                    hgvs_nc.append(hgvs)
                    # look for gene name
                    positions = md_utilities.compute_start_end_pos(match_nc.group(2))
                    # print("SELECT a.name[1] as hgnc FROM gene a, segment b WHERE a.name = b.gene_name AND a.chr = {0} AND {1} BETWEEN SYMMETRIC # b.segment_start AND b.segment_end".format(res_chr['name'], positions[0]))
                    if not gene_names:
                        curs.execute(
                            "SELECT DISTINCT(a.name[1]) as hgnc FROM gene a, segment b WHERE a.name = b.gene_name AND a.chr = %s AND %s BETWEEN SYMMETRIC b.segment_start AND b.segment_end",
                            (res_chr['name'], positions[0])
                        )
                        res_gene = curs.fetchall()
                        if res_gene:
                            for hgnc_name in res_gene:
                                gene_names.append(hgnc_name[0])
            # match_ng = re.search(rf'^(NG_\d+)\.\d+:g\.{variant_regexp}$', hgvs)
            # if match_ng and \
            #         not gene_name and \
            #         not md_response:
            #     # we need to get the gene name that can be useful later
            #     curs.execute(
            #         "SELECT name[1] as hgnc FROM gene WHERE ng LIKE %s AND canonical = 't'",
            #         ('{}%'.format(match_ng.group(1)),)
            #     )
            #     res_gene = curs.fetchone()
            #     if res_gene:
            #         gene_name = res_gene['hgnc']
            else:
                continue
        # do we have an intronic variant?
        if hgvs_nc and \
                gene_names:  # and \
                # not md_response:
            md_api_url = '{0}{1}'.format(request.host_url[:-1], url_for('api.api_variant_g_create'))
            for var_hgvs_nc in hgvs_nc:
                for gene_hgnc in gene_names:
                    data = {
                        'variant_ghgvs': urllib.parse.quote(var_hgvs_nc),
                        'gene_hgnc': gene_hgnc,
                        'caller': 'cli',
                        'api_key': api_key
                    }
                    try:
                        # print('{0}-{1}'.format(var_hgvs_nc, gene_hgnc))
                        md_response[var_hgvs_nc] = json.loads(http.request('POST', md_api_url, headers=md_utilities.api_agent, fields=data).data.decode('utf-8'))
                    except Exception as e:
                        md_response[var_hgvs_nc] = {'mobidetails_error': 'MobiDetails returned an unexpected error for your request {0}: {1}'.format(rs_id, var_hgvs_nc)}
                        md_utilities.send_error_email(
                            md_utilities.prepare_email_html(
                                'MobiDetails API error',
                                '<p>Error with MDAPI file writing for {0} ({1})<br /> - from {2} with args: {3}</p>'.format(
                                    rs_id,
                                    var_hgvs_nc,
                                    os.path.basename(__file__),
                                    e.args
                                )
                            ),
                            '[MobiDetails - MDAPI Error]'
                        )
        if md_response:
            if caller == 'cli':
                return jsonify(md_response)
            else:
                if len(md_response) == 1:
                    for var in md_response:
                        if 'mobidetails_error' in md_response[var]:
                            flash(md_response[var]['mobidetails_error'], 'w3-pale-red')
                            return redirect(url_for('md.index'))
                        return redirect(url_for('md.variant', variant_id=md_response[var]['mobidetails_id']))
                else:
                    
                    return render_template('md/variant_multiple.html', vars_rs=md_response)

        # md_utilities.api_end_according_to_caller(
        #     caller=caller,
        #     message='Using Mutalyzer, we did not find any suitable variant corresponding to your request {}'.format(rs_id),
        #     url=url_for('md.index')
        # )
        if caller == 'cli':
            return jsonify(mobidetails_error='Using Mutalyzer, we did not find any suitable variant corresponding to your request {}'.format(rs_id))
        else:
            flash('Using <a href="https://www.mutalyzer.nl/snp-converter?rs_id={0}", target="_blank">Mutalyzer</a>, we did not find any suitable variant corresponding to your request {0}'.format(rs_id), 'w3-pale-red')
            return redirect(url_for('md.index'))
    else:
        if caller == 'cli':
            return jsonify(mobidetails_error='Invalid rs id provided')
        else:
            flash('Invalid rs id provided', 'w3-pale-red')
            return redirect(url_for('md.index'))
Esempio n. 10
0
def api_variant_g_create(variant_ghgvs=None, gene=None, caller=None, api_key=None):
    # get params
    if request.args.get('variant_ghgvs') and \
            request.args.get('gene_hgnc') and \
            request.args.get('caller') and \
            request.args.get('api_key'):
        variant_ghgvs = request.args.get('variant_ghgvs', type=str)
        gene = request.args.get('gene_hgnc', type=str)
        caller = request.args.get('caller', type=str)
        api_key = request.args.get('api_key', type=str)
    elif 'variant_ghgvs' in request.form and \
            'gene_hgnc' in request.form and \
            'caller' in request.form and \
            'api_key' in request.form:
        variant_ghgvs = request.form['variant_ghgvs']
        gene = request.form['gene_hgnc']
        caller = request.form['caller']
        api_key = request.form['api_key']
    else:
        if caller == 'cli':
            return jsonify(mobidetails_error='I cannot fetch the right parameters')
        else:
            flash('I cannot fetch the right parameters', 'w3-pale-red')
            return redirect(url_for('md.index'))
    if variant_ghgvs is not None and \
            gene is not None and \
            caller is not None and \
            api_key is not None:
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        # mobiuser_id = None
        res_check_api_key = md_utilities.check_api_key(db, api_key)
        if 'mobidetails_error' in res_check_api_key:
            if caller == 'cli':
                return jsonify(res_check_api_key)
            else:
                flash(res_check_api_key['mobidetails_error'], 'w3-pale-red')
                return redirect(url_for('md.index'))
        else:
            g.user = res_check_api_key['mobiuser']

        if md_utilities.check_caller(caller) == 'Invalid caller submitted':
            if caller == 'cli':
                return jsonify(mobidetails_error='Invalid caller submitted')
            else:
                flash('Invalid caller submitted to API.', 'w3-pale-red')
                return redirect(url_for('md.index'))

        # check gene exists
        curs.execute(
            "SELECT name, nm_version FROM gene WHERE name[1] = %s AND canonical = 't'",
            (gene,)
        )
        res_gene = curs.fetchone()
        if res_gene:
            variant_regexp = md_utilities.regexp['variant']
            match_object = re.search(rf'^([Nn][Cc]_0000\d{{2}}\.\d{{1,2}}):g\.({variant_regexp})', urllib.parse.unquote(variant_ghgvs))
            if match_object:
                ncbi_chr, g_var = match_object.group(1), match_object.group(2)
                # 1st check hg38
                curs.execute(
                    "SELECT * FROM chromosomes WHERE ncbi_name = %s",
                    (ncbi_chr,)
                )
                res = curs.fetchone()
                if res and \
                        res['genome_version'] == 'hg38':
                    genome_version, chrom = res['genome_version'], res['name']
                    # check if variant exists
                    curs.execute(
                        "SELECT feature_id FROM variant WHERE genome_version = %s AND g_name = %s AND chr = %s",
                        (genome_version, g_var, chrom)
                    )
                    res = curs.fetchone()
                    if res:
                        if caller == 'cli':                            
                            return jsonify(
                                mobidetails_id=res['feature_id'],
                                url='{0}{1}'.format(
                                    request.host_url[:-1],
                                    url_for('md.variant', variant_id=res['feature_id'])
                                )
                            )
                        else:
                            return redirect(url_for('md.variant', variant_id=res['feature_id']))
                    else:
                        # creation
                        vv_base_url = md_utilities.get_vv_api_url()
                        if not vv_base_url:
                            close_db()
                            if caller == 'cli':
                                return jsonify(mobidetails_error='Variant Validator looks down!.')
                            else:
                                flash('Variant Validator looks down!.', 'w3-pale-red')
                                return redirect(url_for('md.index'))
                        
                        vv_url = "{0}VariantValidator/variantvalidator/GRCh38/{1}/all?content-type=application/json".format(
                            vv_base_url, variant_ghgvs
                        )
                        # print(vv_url)
                        # vv_key_var = "{0}.{1}:c.{2}".format(acc_no, acc_version, new_variant)

                        try:
                            http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
                            vv_data = json.loads(http.request('GET', vv_url).data.decode('utf-8'))
                        except Exception:
                            close_db()
                            if caller == 'cli':
                                return jsonify(mobidetails_error='Variant Validator did not return any value for the variant {}.'.format(urllib.parse.unquote(variant_ghgvs)))
                            else:
                                try:
                                    flash('There has been a issue with the annotation of the variant via VariantValidator. \
                                          The error is the following: {}'.format(vv_data['validation_warning_1']['validation_warnings']), 'w3-pale-red')
                                except Exception:
                                    flash('There has been a issue with the annotation of the variant via VariantValidator. \
                                          Sorry for the inconvenience. You may want to try directly in MobiDetails.', 'w3-pale-red')
                                return redirect(url_for('md.index'))
                        # look for gene acc #
                        # print(vv_data)
                        new_variant = None
                        vv_key_var = None
                        res_gene_non_can_list = []
                        # we still need a list of non canonical NM for the gene of interest
                        curs.execute(
                            "SELECT name, nm_version FROM gene WHERE name[1] = %s AND canonical = 'f'",
                            (gene,)
                        )
                        res_gene_non_can = curs.fetchall()
                        for transcript in res_gene_non_can:
                            res_gene_non_can_list.append('{0}.{1}'.format(transcript['name'][1], transcript['nm_version']))
                        for key in vv_data.keys():
                            variant_regexp = md_utilities.regexp['variant']
                            match_obj = re.search(rf'^([Nn][Mm]_\d+)\.(\d{{1,2}}):c\.({variant_regexp})', key)
                            if match_obj:
                                new_variant = match_obj.group(3)
                                # print("{0}-{1}-{2}-{3}".format(match_obj.group(1), res_gene['name'][1], match_obj.group(2), res_gene['nm_version']))
                                if match_obj.group(1) == res_gene['name'][1] and \
                                        str(match_obj.group(2)) == str(res_gene['nm_version']):
                                    # treat canonical as priority
                                    vv_key_var = "{0}.{1}:c.{2}".format(match_obj.group(1), match_obj.group(2), match_obj.group(3))
                                    break
                                elif not vv_key_var:
                                    # take into account non canonical isoforms
                                    # print('{0}.{1}'.format(match_obj.group(1), match_obj.group(2)))
                                    # print(res_gene_non_can_list)
                                    if '{0}.{1}'.format(match_obj.group(1), match_obj.group(2)) in res_gene_non_can_list:
                                        vv_key_var = "{0}.{1}:c.{2}".format(match_obj.group(1), match_obj.group(2), match_obj.group(3))
                        if vv_key_var:
                            # print(vv_key_var)
                            creation_dict = md_utilities.create_var_vv(
                                vv_key_var, res_gene['name'][0], res_gene['name'][1],
                                'c.{}'.format(new_variant), new_variant,
                                res_gene['nm_version'], vv_data, 'api', db, g
                            )
                            if caller == 'cli':
                                return jsonify(creation_dict)
                            else:
                                return redirect(url_for('md.variant', variant_id=creation_dict['mobidetails_id']))
                        else:
                            if caller == 'cli':
                                return jsonify(mobidetails_error='Could not create variant {} (possibly considered as intergenic).'.format(urllib.parse.unquote(variant_ghgvs)), variant_validator_output=vv_data)
                            else:
                                try:
                                    flash('There has been a issue with the annotation of the variant via VariantValidator. \
                                          The error is the following: {}'.format(vv_data['validation_warning_1']['validation_warnings']), 'w3-pale-red')
                                except Exception:
                                    flash('There has been a issue with the annotation of the variant via VariantValidator. \
                                          Sorry for the inconvenience. You may want to try directly in MobiDetails.', 'w3-pale-red')
                                return redirect(url_for('md.index'))

                else:
                    if caller == 'cli':
                        return jsonify(mobidetails_error='Unknown chromosome {} submitted or bad genome version (hg38 only)'.format(ncbi_chr))
                    else:
                        flash('The submitted chromosome or genome version looks corrupted (hg38 only).', 'w3-pale-red')
                        return redirect(url_for('md.index'))
            else:
                if caller == 'cli':
                    return jsonify(mobidetails_error='Malformed query {}'.format(urllib.parse.unquote(variant_ghgvs)))
                else:
                    flash('The query seems to be malformed: {}.'.format(urllib.parse.unquote(variant_ghgvs)), 'w3-pale-red')
                    return redirect(url_for('md.index'))
        else:
            if caller == 'cli':
                return jsonify(mobidetails_error='Unknown gene {} submitted'.format(gene))
            else:
                flash('Unknown gene {} submitted'.format(gene), 'w3-pale-red')
                return redirect(url_for('md.index'))
    else:
        if caller == 'cli':
            return jsonify(mobidetails_error='Invalid parameters')
        else:
            flash('The submitted parameters looks invalid!!!', 'w3-pale-red')
            return redirect(url_for('md.index'))
Esempio n. 11
0
def file_upload():
    if request.method == 'POST':
        if request.files:
            uploaded_file = request.files['file']
            if uploaded_file.filename == "":
                flash('No filename.', 'w3-pale-red')
                return redirect(request.url)
            if allowed_file(uploaded_file.filename):
                # filename = secure_filename(uploaded_file.filename)
                lines = uploaded_file.read().decode().replace(
                    '\r\n', '\n').replace('\r', '\n').split('\n')
                # print(lines)
                # ok we've got the file
                # get user API key or use MD
                db = get_db()
                curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
                http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',
                                           ca_certs=certifi.where())
                # headers
                header = md_utilities.api_agent
                result = []
                api_key = md_utilities.get_api_key(g, curs)
                if api_key is None:
                    flash('There is an issue in obtaining an API key')
                    return redirect(request.url)
                # we need to check the format and send a proper query to the API
                for line in lines:
                    # print('-{}-'.format(line))
                    # cDNA format
                    md_response = []
                    if re.search(r'^#', line) or \
                            line == '':
                        continue
                    line = line.replace(' ', '')
                    variant_regexp = md_utilities.regexp['variant']
                    match_obj_c = re.search(
                        rf'^([Nn][Mm]_\d+)\.(\d+):(c\.{variant_regexp})$',
                        line)
                    if match_obj_c:
                        # check NM number and version
                        curs.execute(
                            "SELECT nm_version FROM gene WHERE name[2] = %s",
                            (match_obj_c.group(1), ))
                        res_nm = curs.fetchone()
                        if res_nm:
                            # send var to api
                            md_api_url = '{0}{1}'.format(
                                request.host_url[:-1],
                                url_for('api.api_variant_create'))
                            # md_api_url = '{0}/api/variant/create'.format(md_api_base_url)
                            # print(md_api_url)
                            data = {
                                'variant_chgvs':
                                urllib.parse.quote('{0}.{1}:{2}'.format(
                                    match_obj_c.group(1), match_obj_c.group(2),
                                    match_obj_c.group(3))),
                                'caller':
                                'cli',
                                'api_key':
                                api_key
                            }
                            try:
                                md_response = json.loads(
                                    http.request(
                                        'POST',
                                        md_api_url,
                                        headers=header,
                                        fields=data).data.decode('utf-8'))
                                # print(md_response)
                                result.append({
                                    'variant':
                                    line,
                                    'id':
                                    md_response['mobidetails_id'],
                                    'url':
                                    md_response['url']
                                })
                            except Exception:
                                if 'mobidetails_error' in md_response:
                                    result.append({
                                        'variant':
                                        line,
                                        'error':
                                        md_response['mobidetails_error']
                                    })
                                else:
                                    result.append({
                                        'variant': line,
                                        'error': 'MDAPI call failed'
                                    })
                        else:
                            result.append({
                                'variant':
                                line,
                                'error':
                                'Unknown NCBI NM accession number'
                            })
                        continue
                    # genomic format
                    match_obj_g = re.search(
                        rf'^([Nn][Cc]_\d+\.\d+:g\.{variant_regexp});([\w-]+)$',
                        line)
                    if match_obj_g:
                        # check NM number and version
                        curs.execute(
                            "SELECT nm_version FROM gene WHERE name[1] = %s",
                            (match_obj_g.group(2), ))
                        res_nm = curs.fetchone()
                        if res_nm:
                            # send var to api
                            md_api_url = '{0}{1}'.format(
                                request.host_url[:-1],
                                url_for('api.api_variant_g_create'))
                            # print(md_api_url)
                            data = {
                                'variant_ghgvs':
                                urllib.parse.quote(match_obj_g.group(1)),
                                'gene_hgnc':
                                match_obj_g.group(2),
                                'caller':
                                'cli',
                                'api_key':
                                api_key
                            }
                            try:
                                md_response = json.loads(
                                    http.request(
                                        'POST',
                                        md_api_url,
                                        headers=header,
                                        fields=data).data.decode('utf-8'))
                                # print(md_response)
                                result.append({
                                    'variant':
                                    line,
                                    'id':
                                    md_response['mobidetails_id']
                                })
                            except Exception:
                                if 'variant_validator_output' in md_response and \
                                        'validation_warning_1' in md_response['variant_validator_output'] and \
                                        'validation_warnings' in md_response['variant_validator_output']['validation_warning_1']:
                                    result.append({
                                        'variant':
                                        line,
                                        'error':
                                        md_response['variant_validator_output']
                                        ['validation_warning_1']
                                        ['validation_warnings'][0]
                                    })
                                elif 'mobidetails_error' in md_response:
                                    result.append({
                                        'variant':
                                        line,
                                        'error':
                                        md_response['mobidetails_error']
                                    })
                                    v
                                else:
                                    result.append({
                                        'variant': line,
                                        'error': 'MDAPI call failed'
                                    })
                        else:
                            result.append({
                                'variant': line,
                                'error': 'Unknown gene'
                            })
                        continue
                    if re.search(rf'^rs\d+$', line):
                        md_api_url = '{0}{1}'.format(
                            request.host_url[:-1],
                            url_for('api.api_variant_create_rs'))
                        # md_api_url = '{0}/api/variant/create'.format(md_api_base_url)
                        # print(md_api_url)
                        data = {
                            'rs_id': line,
                            'caller': 'cli',
                            'api_key': api_key
                        }
                        try:
                            md_response = json.loads(
                                http.request('POST',
                                             md_api_url,
                                             headers=header,
                                             fields=data).data.decode('utf-8'))
                            for var in md_response:
                                print(md_response[var])
                                if 'mobidetails_error' in md_response[var]:
                                    result.append({
                                        'variant':
                                        '{0} - {1}'.format(line, var),
                                        'error':
                                        md_response[var]['mobidetails_error']
                                    })
                                elif var == 'mobidetails_error':
                                    result.append({
                                        'variant': line,
                                        'error': md_response[var]
                                    })
                                else:
                                    result.append({
                                        'variant':
                                        '{0} - {1}'.format(line, var),
                                        'id':
                                        md_response[var]['mobidetails_id'],
                                        'url':
                                        md_response[var]['url']
                                    })

                        except Exception:
                            result.append({
                                'variant': line,
                                'error': 'MDAPI call failed'
                            })
                        continue
                    result.append({'variant': line, 'error': 'Bad format'})
                close_db()
                flash('File correctly uploaded', 'w3-pale-green')
                if g.user:
                    # send an email
                    # print(g.user)
                    result_list = ''
                    for resul in result:
                        result_list = '{0}<li>{1}'.format(
                            result_list, resul['variant'])
                        if 'error' in resul:
                            result_list = '{0} - {1}</li>'.format(
                                result_list, resul['error'])
                        else:
                            result_list = '{0} - <a href="{1}{2}">success</a></li>'.format(
                                result_list, request.host_url[:-1],
                                url_for('md.variant', variant_id=resul['id']))

                    message = 'Dear {0},<br /><p>Your batch job returned the following results:</p><ul>{1}</ul><p>You can have a direct acces to the successfully annotated variants at your <a href="{2}{3}">profile page</a>.'.format(
                        g.user['username'], result_list, request.host_url[:-1],
                        url_for('auth.profile', mobiuser_id=0))
                    md_utilities.send_email(
                        md_utilities.prepare_email_html(
                            'MobiDetails - Batch job', message, False),
                        '[MobiDetails - Batch job]', [g.user['email']])
                return render_template('md/variant_multiple.html',
                                       upload=result)
            else:
                flash('That file extension is not allowed', 'w3-pale-red')
                return redirect(request.url)

    return render_template("upload/upload_form.html")
Esempio n. 12
0
def gene(gene_symbol=None):
    if gene_symbol is None:
        return render_template('md/unknown.html', query='No gene provided')
    gene_match_obj = re.search(r'^([\w-]+)$', gene_symbol)
    if not gene_match_obj:
        return render_template('md/unknown.html', query=gene_symbol)
    gene_symbol = gene_match_obj.group(1)
    db = get_db()
    curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
    # main isoform? now canonical is stored in db
    curs.execute(
        """
        SELECT *
        FROM gene
        WHERE gene_symbol = %s
            AND canonical = 't'
        """, (gene_symbol, ))
    main = curs.fetchone()
    if main:
        curs.execute("""
            SELECT *
            FROM gene
            WHERE gene_symbol = %s
            ORDER BY number_of_exons DESC
            """, (gene_symbol, ))  # get all isoforms
        result_all = curs.fetchall()
        num_iso = len(result_all)
        # get metadome json?
        enst_ver = {}
        # if not json metadome file on filesystem, create it in
        # radboud server, then next time get it - it will then be
        # available for future requests
        # if we have the main => next step
        if not os.path.isfile('{0}{1}.json'.format(
                md_utilities.local_files['metadome']['abs_path'],
                main['enst'])):
            for gene in result_all:
                if not os.path.isfile('{0}{1}.json'.format(
                        md_utilities.local_files['metadome']['abs_path'],
                        gene['enst'])):
                    if gene['enst'] not in enst_ver:
                        # get enst versions in a dict
                        metad_ts = None
                        try:
                            metad_ts = json.loads(
                                http.request(
                                    'GET', '{0}get_transcripts/{1}'.format(
                                        md_utilities.urls['metadome_api'],
                                        gene['gene_symbol'])).data.decode(
                                            'utf-8'))
                            if metad_ts is not None and \
                                    'trancript_ids' in metad_ts:
                                for ts in metad_ts['trancript_ids']:
                                    if ts['has_protein_data']:
                                        match_obj = re.search(
                                            r'^(ENST\d+)\.\d',
                                            ts['gencode_id'])
                                        enst_ver[match_obj.group(
                                            1)] = ts['gencode_id']
                        except Exception as e:
                            md_utilities.send_error_email(
                                md_utilities.prepare_email_html(
                                    'MobiDetails API error', """
                                    <p>MetaDome first block code failed for gene {0} ({1})<br /> - from {2} with args: {3}</p>
                                    """.format(gene_symbol, gene['enst'],
                                               os.path.basename(__file__),
                                               e.args)),
                                '[MobiDetails - API Error]')
                    break

        # we check if data exist at metadome
        # we have a set of metadome transcripts
        for enst in enst_ver:
            # print('enst: {}'.format(enst_ver[enst]))
            # print('--{}--'.format(app.debug))
            # print(json.dumps({'transcript_id': enst_ver[enst]}))
            if not os.path.isfile('{0}{1}.json'.format(
                    md_utilities.local_files['metadome']['abs_path'], enst)):
                metad_data = None
                try:
                    metad_data = json.loads(
                        http.request(
                            'GET', '{0}status/{1}/'.format(
                                md_utilities.urls['metadome_api'],
                                enst_ver[enst])).data.decode('utf-8'))
                except Exception as e:
                    md_utilities.send_error_email(
                        md_utilities.prepare_email_html(
                            'MobiDetails API error', """
                            <p>MetaDome second block code failed for gene {0} ({1})<br /> - from {2} with args: {3}</p>
                            """.format(gene_symbol, enst,
                                       os.path.basename(__file__), e.args)),
                        '[MobiDetails - API Error]')
                if metad_data is not None:
                    if metad_data['status'] == 'PENDING':
                        # get transcript_ids ?? coz of the version number
                        # send request to build visualization to metadome
                        vis_request = None
                        # find out how to get app object
                        try:
                            # enst_metadome = {transcript_id: enst_ver[enst]}
                            header = md_utilities.api_agent
                            header['Content-Type'] = 'application/json'
                            vis_request = json.loads(
                                http.request(
                                    'POST',
                                    '{0}submit_visualization/'.format(
                                        md_utilities.urls['metadome_api']),
                                    # headers={'Content-Type': 'application/json'},
                                    headers=header,
                                    body=json.dumps({
                                        'transcript_id':
                                        enst_ver[enst]
                                    })).data.decode('utf-8'))
                            if not app.debug:
                                app.logger.info(
                                    '{} submitted to metadome'.format(
                                        vis_request['transcript_id']))
                            else:
                                print('{} submitted to metadome'.format(
                                    vis_request['transcript_id']))
                        except Exception as e:
                            md_utilities.send_error_email(
                                md_utilities.prepare_email_html(
                                    'MobiDetails API error', """
                                    <p>Error with metadome submission for {0} ({1})<br /> - from {2} with args: {3}</p>
                                    """.format(gene_symbol, enst,
                                               os.path.basename(__file__),
                                               e.args)),
                                '[MobiDetails - API Error]')
                            # print('Error with metadome
                            # submission for {}'.format(enst))
                    elif metad_data['status'] == 'SUCCESS':
                        # get_request = None
                        try:
                            get_request = json.loads(
                                http.request(
                                    'GET', '{0}result/{1}/'.format(
                                        md_utilities.urls['metadome_api'],
                                        enst_ver[enst])).data.decode('utf-8'))
                            # copy in file system
                            with open('{0}{1}.json'.format(
                                    md_utilities.local_files['metadome']
                                ['abs_path'], enst),
                                      "w",
                                      encoding='utf-8') as metad_file:
                                json.dump(get_request,
                                          metad_file,
                                          ensure_ascii=False,
                                          indent=4)
                            if not app.debug:
                                app.logger.info(
                                    'saving metadome {} into local file system'
                                    .format(enst_ver[enst]))
                            else:
                                print(
                                    'saving metadome {} into local file system'
                                    .format(enst_ver[enst]))
                        except Exception as e:
                            md_utilities.send_error_email(
                                md_utilities.prepare_email_html(
                                    'MobiDetails API error', """
                                    <p>Error with metadome file writing for {0} ({1})<br /> - from {2} with args: {3}</p>
                                    """.format(gene_symbol, enst,
                                               os.path.basename(__file__),
                                               e.args)),
                                '[MobiDetails - API Error]')
                            # print('error saving metadome json
                            # file for {}'.format(enst))
        if result_all is not None:
            # get annotations
            curs.execute(
                """
                SELECT *
                FROM gene_annotation
                WHERE gene_symbol = %s
                """, (gene_symbol, ))
            annot = curs.fetchone()
            if annot is None:
                annot = {'nognomad': 'No values in gnomAD'}
            curs.execute(
                """
                SELECT MAX(prot_size) AS size
                FROM gene
                WHERE gene_symbol = %s
                """, (gene_symbol, ))
            res_size = curs.fetchone()
            # get refseq select, mane, etc from vv json file
            no_vv_file = 0
            try:
                json_file = open(
                    '{0}{1}.json'.format(  # lgtm [py/path-injection]
                        md_utilities.local_files['variant_validator']
                        ['abs_path'], gene_symbol))
            except IOError:
                no_vv_file = 1
            if no_vv_file == 0:
                transcript_road_signs = {}
                vv_json = json.load(json_file)
                if 'error' in vv_json \
                    or ('message' in vv_json and
                        vv_json['message'] == 'Internal Server Error'):
                    no_vv_file = 1
                    curs.execute(
                        """
                        UPDATE gene
                        SET variant_creation = 'not_in_vv_json'
                        WHERE gene_symbol = %s
                            AND variant_creation <> 'not_in_vv_json'
                        """, (gene_symbol, ))
                    db.commit()
                    curs.execute("""
                        SELECT *
                        FROM gene
                        WHERE gene_symbol = %s
                        ORDER BY number_of_exons DESC
                        """, (gene_symbol, ))  # get all isoforms
                    result_all = curs.fetchall()
                    num_iso = len(result_all)
                if no_vv_file == 0:
                    for vv_transcript in vv_json['transcripts']:
                        for res in result_all:
                            # need to check vv isoforms against MD isoforms to keep only relevant ones
                            if vv_transcript['reference'] == res['refseq']:
                                if 'mane_select' in vv_transcript['annotations'] and \
                                        'mane_plus_clinical' in vv_transcript['annotations'] and \
                                        'refseq_select' in vv_transcript['annotations']:
                                    transcript_road_signs[res['refseq']] = {
                                        'mane_select':
                                        vv_transcript['annotations']
                                        ['mane_select'],
                                        'mane_plus_clinical':
                                        vv_transcript['annotations']
                                        ['mane_plus_clinical'],
                                        'refseq_select':
                                        vv_transcript['annotations']
                                        ['refseq_select']
                                    }
                # print(transcript_road_signs)
            close_db()
            clingen_criteria_specification_id = md_utilities.get_clingen_criteria_specification_id(
                gene_symbol)
            return render_template('md/gene.html',
                                   run_mode=md_utilities.get_running_mode(),
                                   urls=md_utilities.urls,
                                   gene_symbol=gene_symbol,
                                   num_iso=num_iso,
                                   main_iso=main,
                                   res=result_all,
                                   annotations=annot,
                                   max_prot_size=res_size['size'],
                                   clingen_criteria_specification_id=
                                   clingen_criteria_specification_id,
                                   transcript_road_signs=transcript_road_signs)
        else:
            close_db()
            return render_template('md/unknown.html',
                                   run_mode=md_utilities.get_running_mode(),
                                   query=gene_symbol)
    else:
        close_db()
        return render_template('md/unknown.html',
                               run_mode=md_utilities.get_running_mode(),
                               query=gene_symbol)
Esempio n. 13
0
def search_engine():
    # print("--{}--".format(request.form['search']))
    query_engine = request.form['search']
    # query_engine = query_engine.upper()
    error = None
    variant_regexp = md_utilities.regexp['variant']
    variant_regexp_flexible = md_utilities.regexp['variant_flexible']
    amino_acid_regexp = md_utilities.regexp['amino_acid']
    nochr_captured_regexp = md_utilities.regexp['nochr_captured']
    ncbi_transcript_regexp = md_utilities.regexp['ncbi_transcript']
    vcf_str_regexp = md_utilities.regexp['vcf_str']

    if query_engine is not None and \
            query_engine != '':
        pattern = ''
        query_type = ''
        sql_table = 'variant_feature'
        col_names = 'id, c_name, gene_symbol, refseq, p_name'
        semaph_query = 0
        query_engine = re.sub(r'\s', '', query_engine)
        query_engine = re.sub(r"'", '', query_engine)
        if re.search(r'^last$', query_engine):
            # get variant annotated the last 7 days
            if 'db' not in locals():
                db = get_db()
                curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
                curs.execute("""
                    SELECT a.id, a.c_name, a.p_name, a.gene_symbol, a.refseq, a.creation_user, a.creation_date, b.username
                    FROM variant_feature a, mobiuser b
                    WHERE a.creation_user = b.id
                        AND a.creation_date > CURRENT_DATE - 7
                    ORDER BY creation_date DESC
                    """)
                variants = curs.fetchall()
                close_db()
                return render_template('md/variant_multiple.html',
                                       variants=variants)
        match_object = re.search(
            rf'^([Gg]*[rR]*[hHcC][gGhH][13][978])[:_-]({vcf_str_regexp})$',
            query_engine)
        # match_object = re.search(rf'^{vcf_str_regexp}$', query_engine)
        if match_object:
            genome_version = md_utilities.translate_genome_version(
                match_object.group(1))
            if genome_version != 'wrong_genome_input':
                if 'db' not in locals():
                    db = get_db()
                    curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
                api_key = md_utilities.get_api_key(g, curs)
                if api_key is not None:
                    close_db()
                    return redirect(url_for('api.api_create_vcf_str',
                                            genome_version=genome_version,
                                            vcf_str=match_object.group(2),
                                            caller='browser',
                                            api_key=api_key),
                                    code=307)
            else:
                error = 'Your genome version looks suspicious ({}). Supported are hg19, hg38, GRCh37, GRCh38'.format(
                    match_object.group(1))
        else:
            match_object = re.search(rf'^{vcf_str_regexp}$', query_engine)
            if match_object:
                if 'db' not in locals():
                    db = get_db()
                    curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
                api_key = md_utilities.get_api_key(g, curs)
                if api_key is not None:
                    close_db()
                    return redirect(url_for('api.api_create_vcf_str',
                                            vcf_str=query_engine,
                                            caller='browser',
                                            api_key=api_key),
                                    code=307)
        match_object = re.search(
            rf'^([{amino_acid_regexp}]{{1}})(\d+)([{amino_acid_regexp}\*]{{1}})$',
            query_engine)  # e.g. R34X
        if match_object:
            confusing_genes = [
                'C1R', 'C8G', 'S100G', 'F11R', 'C1S', 'A2M', 'C1D', 'S100P',
                'F2R', 'C8A', 'C4A'
            ]
            # list of genes that look like the query
            if query_engine.upper() in confusing_genes:
                sql_table = 'gene'
                query_type = 'gene_symbol'
                col_names = 'gene_symbol'
                pattern = query_engine.upper()
            else:
                query_type = 'p_name'
                pattern = md_utilities.one2three_fct(query_engine)
        elif re.search(r'^rs\d+$', query_engine):
            query_type = 'dbsnp_id'
            match_object = re.search(r'^rs(\d+)$', query_engine)
            pattern = match_object.group(1)
        elif re.search(r'^p\..+', query_engine):
            query_type = 'p_name'
            var = md_utilities.clean_var_name(query_engine)
            match_object = re.search(r'^(\w{1})(\d+)([\w\*]{1})$',
                                     var)  # e.g. p.R34X
            match_object_inter = re.search(r'^(\w{1})(\d+)([d][ue][pl])',
                                           var)  # e.g. p.L34del
            match_object_long = re.search(r'^(\w{1})(\d+_)(\w{1})(\d+.+)$',
                                          var)  # e.g. p.R34_E68del
            if match_object or match_object_inter or match_object_long:
                pattern = md_utilities.one2three_fct(var)
            else:
                if re.search('X', var):
                    pattern = re.sub(r'X', 'Ter', var)
                elif re.search(r'\*', var):
                    pattern = re.sub(r'\*', 'Ter', var)
                else:
                    pattern = var
        elif re.search(rf'^{ncbi_transcript_regexp}:c\.{variant_regexp}$', query_engine) or \
                re.search(rf'^{ncbi_transcript_regexp}\([A-Za-z0-9-]+\):c\.{variant_regexp}$', query_engine):  # NM acc_no variant
            # f-strings usage https://stackoverflow.com/questions/6930982/how-to-use-a-variable-inside-a-regular-expression
            # API call
            if 'db' not in locals():
                db = get_db()
                curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            api_key = md_utilities.get_api_key(g, curs)
            match_obj = re.search(
                rf'^({ncbi_transcript_regexp})\(*[A-Za-z0-9-]*\)*(:c\.{variant_regexp})$',
                query_engine)
            if api_key is not None:
                close_db()
                return redirect(url_for('api.api_variant_create',
                                        variant_chgvs='{0}{1}'.format(
                                            match_obj.group(1),
                                            match_obj.group(2)),
                                        caller='browser',
                                        api_key=api_key),
                                code=307)
        elif re.search(r'^[Nn][Mm]_\d+', query_engine):  # NM acc_no
            sql_table = 'gene'
            query_type = 'refseq'
            col_names = 'gene_symbol'
            match_object = re.search(r'^(^[Nn][Mm]_\d+)', query_engine)
            if match_object:
                col_names = 'partial_name'
                pattern = match_object.group(1)
        elif re.search(
                rf'^[Nn][Cc]_0000\d{{2}}\.\d{{1,2}}:g\.{variant_regexp}$',
                query_engine):  # strict HGVS genomic
            sql_table = 'variant'
            query_type = 'g_name'
            col_names = 'feature_id'
            db = get_db()
            match_object = re.search(
                rf'^([Nn][Cc]_0000\d{{2}}\.\d{{1,2}}):g\.({variant_regexp})$',
                query_engine)
            # res_common = md_utilities.get_common_chr_name(db, match_object.group(1))
            chrom = md_utilities.get_common_chr_name(db,
                                                     match_object.group(1))[0]
            pattern = match_object.group(2)
            close_db()
            # res_common = md_utilities.get_common_chr_name(db, )
        elif re.search(
                rf'^[Nn][Cc]_0000\d{{2}}\.\d{{1,2}}:g\.{variant_regexp};[\w-]+$',
                query_engine):  # strict HGVS genomic + gene (API call)
            # API call
            if 'db' not in locals():
                db = get_db()
                curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            api_key = md_utilities.get_api_key(g, curs)
            match_obj = re.search(
                rf'^([Nn][Cc]_0000\d{{2}}\.\d{{1,2}}:g\.{variant_regexp});([\w-]+)$',
                query_engine)
            if api_key is not None:
                close_db()
                return redirect(url_for('api.api_variant_g_create',
                                        variant_ghgvs=match_obj.group(1),
                                        gene_hgnc=match_obj.group(2),
                                        caller='browser',
                                        api_key=api_key),
                                code=307)
        elif re.search(
                rf'^[Cc][Hh][Rr]({nochr_captured_regexp}):g\.{variant_regexp_flexible}$',
                query_engine):  # deal w/ genomic
            sql_table = 'variant'
            query_type = 'g_name'
            col_names = 'feature_id'
            match_object = re.search(
                rf'^[Cc][Hh][Rr]({nochr_captured_regexp}):g\.({variant_regexp_flexible})$',
                query_engine)
            chrom = match_object.group(1)
            pattern = match_object.group(2)
            # if re.search(r'>', pattern):
            #    pattern = pattern.upper()
        elif re.search(r'^g\..+', query_engine):  # g. ng dna vars
            query_type = 'ng_name'
            pattern = md_utilities.clean_var_name(query_engine)
        elif re.search(r'^c\..+', query_engine):  # c. dna vars
            query_type = 'c_name'
            pattern = md_utilities.clean_var_name(query_engine)
        elif re.search(
                r'^%\d+$', query_engine
        ):  # only numbers: get matching variants (exact position match) - specific query
            match_obj = re.search(r'^%(\d+)$', query_engine)
            pattern = match_obj.group(1)
            db = get_db()
            curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            curs.execute(r"""
                SELECT {0}
                FROM {1}
                WHERE c_name ~ '^{2}[^\d]'
                    OR c_name ~ '_{2}[^\d]'
                    OR p_name ~ '^{2}[^\d]'
                    OR p_name ~ '_{2}[^\d]'
                """.format(col_names, sql_table, pattern))
            semaph_query = 1
            close_db()
        elif re.search(
                r'^\d{2,}$', query_engine
        ):  # only numbers: get matching variants (partial match, at least 2 numbers) - specific query
            db = get_db()
            curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            curs.execute("""
                SELECT {0}
                FROM {1}
                WHERE c_name LIKE '%{2}%'
                    OR p_name LIKE '%{2}%'
                """.format(col_names, sql_table, query_engine))
            semaph_query = 1
            close_db()
        elif re.search(r'^[A-Za-z0-9-]+$', query_engine):  # genes
            sql_table = 'gene'
            query_type = 'gene_symbol'
            col_names = 'gene_symbol'
            pattern = query_engine
            if not re.search(r'[oO][rR][fF]', pattern):
                pattern = pattern.upper()
            else:
                # from experience the only low case in gene is 'orf'
                pattern = re.sub(r'O', 'o', pattern)
                pattern = re.sub(r'R', 'r', pattern)
                pattern = re.sub(r'F', 'f', pattern)
                pattern = pattern.capitalize()
        else:
            error = 'Sorry I did not understand this query ({}).'.format(
                query_engine)
            # return render_template('md/unknown.html', query=query_engine, transformed_query=pattern)
        if error is None:
            # print(semaph_query)
            if semaph_query == 0:
                if 'db' not in locals():
                    db = get_db()
                curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
                # sql_query = "SELECT {0} FROM {1} WHERE {2} = '{3}'".format(col_names, sql_table, query_type, pattern)
                # return render_template('md/search_engine.html', query=text)
                # a little bit of formatting
                if re.search('variant', sql_table) and \
                        re.search('>', pattern):
                    # upper for the end of the variant, lower for genomic chr
                    var_match = re.search(
                        r'^(.*)(\d+)([ACTGactg]>[ACTGactg])$', pattern)
                    if var_match:
                        pattern = var_match.group(1).lower() + var_match.group(
                            2) + var_match.group(3).upper()
                    else:
                        close_db()
                        error = 'You submitted a forbidden character in "{}".'.format(
                            pattern)
                        flash(error, 'w3-pale-red')
                        return render_template('md/unknown.html',
                                               run_mode=app.config['RUN_MODE'])
                    # print(pattern)
                if pattern == 'g_name':
                    curs.execute("""
                        SELECT {0}
                        FROM {1}
                        WHERE chr = {2}
                            AND {3} = '{4}'
                        """.format(col_names, sql_table, chrom, query_type,
                                   pattern))
                else:
                    if col_names == 'partial_name':
                        col_names = 'gene_symbol'
                        curs.execute("""
                            SELECT {0}
                            FROM {1}
                            WHERE {2} LIKE '{3}%'
                            """.format(col_names, sql_table, query_type,
                                       pattern))
                    else:
                        curs.execute("""
                            SELECT {0}
                            FROM {1}
                            WHERE {2} = '{3}'
                            """.format(col_names, sql_table, query_type,
                                       pattern))
                result = None
            if sql_table == 'gene':
                result = curs.fetchone()
                if result is None:
                    query_type = 'second_name'
                    # https://www.postgresql.org/docs/9.3/functions-matching.html#POSIX-ESCAPE-SEQUENCES
                    curs.execute(r"""
                        SELECT {0}
                        FROM {1}
                        WHERE {2} ~* '\m[;,]?{3}[;,]?\M'
                        """.format(col_names, sql_table, query_type, pattern))
                    result_second = curs.fetchone()
                    close_db()
                    if result_second is None:
                        error = """
                        Sorry the gene does not seem to exist yet in MD or cannot be annotated for some reason ({}).
                        """.format(query_engine)
                    else:
                        return redirect(
                            url_for('md.gene',
                                    gene_symbol=result_second[col_names]))
                else:
                    close_db()
                    return redirect(
                        url_for('md.gene', gene_symbol=result[col_names]))
            else:
                result = curs.fetchall()
                if not result:
                    if query_type == 'dbsnp_id':
                        # api call to create variant from rs id
                        api_key = md_utilities.get_api_key(g, curs)
                        if api_key is not None:
                            close_db()
                            return redirect(url_for(
                                'api.api_variant_create_rs',
                                rs_id='rs{}'.format(pattern),
                                caller='browser',
                                api_key=api_key),
                                            code=307)
                    error = """
                    Sorry the variant or gene does not seem to exist yet in MD or cannot be annotated for some reason ({}).<br />
                    You can annotate it directly at the corresponding gene page.
                    """.format(query_engine)
                else:
                    if len(result) == 1:
                        close_db()
                        return redirect(
                            url_for('api.variant',
                                    variant_id=result[0][0],
                                    caller='browser'))
                    else:
                        variants = result
                        if query_type == 'g_name':
                            # coming from a query type: NC_000001.11:g.216422237G>A
                            id_tuple = []
                            for feature_id in result:
                                id_tuple.append(feature_id['feature_id'])
                            curs.execute(
                                """
                                SELECT id, c_name, p_name, gene_symbol, refseq
                                FROM variant_feature
                                WHERE id IN %s
                                ORDER BY id
                                """, (tuple(id_tuple), ))
                            variants = curs.fetchall()
                        close_db()
                        return render_template(
                            'md/variant_multiple.html',
                            run_mode=md_utilities.get_running_mode(),
                            variants=variants)
            if 'db' in locals():
                close_db()
    else:
        error = 'Please type something for the search engine to work.'
    flash(error, 'w3-pale-red')
    return render_template('md/unknown.html',
                           run_mode=md_utilities.get_running_mode())
Esempio n. 14
0
def vars(gene_symbol=None):
    if gene_symbol is None:
        return render_template('md/unknown.html', query='No gene provided')
    elif re.search(r'[^\w-]', gene_symbol):
        return render_template('md/unknown.html', query=gene_symbol)
    gene_symbol = re.escape(gene_symbol)
    db = get_db()
    curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
    # error = None
    # main isoform?
    curs.execute(
        """
        SELECT *
        FROM gene
        WHERE gene_symbol = %s
            AND canonical = 't'
        """, (gene_symbol, ))
    main = curs.fetchone()
    if main is not None:
        curs.execute("""
            SELECT gene_symbol, refseq, variant_creation
            FROM gene
            WHERE gene_symbol = %s
            """, (gene_symbol, ))  # get all isoforms
        result_all = curs.fetchall()
        num_iso = len(result_all)
        # curs.execute(
        #     """
        #     SELECT d.variant_creation, d.refseq, b.pos, a.c_name, a.p_name, a.start_segment_type, a.start_segment_number, a.creation_date, c.username, a.prot_type, a.ivs_name, a.id as vf_id
        #     FROM variant_feature a, variant b, mobiuser c, gene d
        #     WHERE a.id = b.feature_id
        #         AND a.gene_symbol = d.gene_symbol
        #         AND a.refseq = d.refseq
        #         AND a.creation_user = c.id
        #         AND b.genome_version = 'hg38'
        #         AND a.gene_symbol = %s
        #     """,
        #     (gene_symbol,)
        # )
        curs.execute(
            """
            SELECT d.variant_creation, d.refseq, a.c_name, a.p_name, a.start_segment_type, a.start_segment_number, a.creation_date, c.username, a.prot_type, a.ivs_name, a.id as vf_id
            FROM variant_feature a, mobiuser c, gene d
            WHERE a.gene_symbol = d.gene_symbol
                AND a.refseq = d.refseq
                AND a.creation_user = c.id
                AND a.gene_symbol = %s
            """, (gene_symbol, ))
        variants = curs.fetchall()
        curs.execute(
            """
            SELECT MAX(prot_size) AS size
            FROM gene
            WHERE gene_symbol = %s
            """, (gene_symbol, ))
        res_size = curs.fetchone()
        # if vars_type is not None:
        close_db()
        clingen_criteria_specification_id = md_utilities.get_clingen_criteria_specification_id(
            gene_symbol)
        return render_template(
            'md/vars.html',
            run_mode=md_utilities.get_running_mode(),
            urls=md_utilities.urls,
            gene_symbol=gene_symbol,
            num_iso=num_iso,
            variants=variants,
            gene_info=main,
            res=result_all,
            max_prot_size=res_size['size'],
            clingen_criteria_specification_id=clingen_criteria_specification_id
        )
    else:
        close_db()
        return render_template('md/unknown.html',
                               run_mode=md_utilities.get_running_mode(),
                               query=gene_symbol)
Esempio n. 15
0
def register():
    if (md_utilities.get_running_mode() == 'maintenance'):
        return render_template('md/index.html',
                               run_mode=md_utilities.get_running_mode())
    if request.method == 'POST':
        # username = urllib.parse.unquote(request.form['username'])
        username = request.form['username']
        password = request.form['password']
        country = request.form['country']
        institute = request.form['institute']
        email = request.form['email']

        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        error = None

        if not username:
            error = 'Username is required.'
        elif len(username) < 5:
            error = 'Username should be at least 5 characters.'
        elif not password:
            error = 'Password is required.'
        elif len(password) < 8 or \
                not re.search(r'[a-z]', password) or \
                not re.search(r'[A-Z]', password) or \
                not re.search(r'[0-9]', password):
            error = """
            Password should be at least 8 characters and mix at least letters (upper and lower case) and numbers.
            """
        elif not country or re.match('--', country):
            error = 'Country is required.'
        elif not institute:
            error = 'Institute is required.'
        elif not email:
            error = 'Email is required.'
        elif not re.search(
                r'^[a-zA-Z0-9\._%\+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
            error = 'The email address does not look valid.'
        else:
            http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',
                                       ca_certs=certifi.where())
            # try:
            # read api key for mailboxvalidator
            apikey = configuration.mdconfig(section='email_check')['apikey']
            mv_url = 'https://api.mailboxvalidator.com/v1/validation/single?key={0}&format=json&email={1}'.format(
                apikey, email)
            try:
                mv_json = json.loads(
                    http.request('GET', mv_url).data.decode('utf-8'))
            except Exception:
                mv_json = None
            if mv_json is not None:
                try:
                    if mv_json['credits_available'] > 0:
                        if mv_json['status'] == "False":
                            if (mv_json['is_high_risk'] == "True"
                                    or mv_json['is_suppressed'] == "True"
                                    or mv_json['is_catchall'] == "True"):
                                error = """
                                The email address is reported as risky or suppressed.
                                If this is not the case, please send
                                us an email directly to
                                &#109;&#111;&#098;&#105;&#100;&#101;
                                &#116;&#097;&#105;&#108;&#115;
                                &#046;&#105;&#117;&#114;&#099;&#064;
                                &#103;&#109;&#097;&#105;&#108;&#046;
                                &#099;&#111;&#109;.
                                """
                            # else:valid adressese such as
                            # [email protected] are reported as False
                    else:
                        md_utilities.send_error_email(
                            md_utilities.prepare_email_html(
                                'MobiDetails email validation error',
                                '<p>mailboxvalidator credits == 0</p>'),
                            '[MobiDetails - Email Validation Error]')
                except Exception as e:
                    md_utilities.send_error_email(
                        md_utilities.prepare_email_html(
                            'MobiDetails email validation error', """
                            <p>mailboxvalidator validation failed: <br/> {0} <br /> - from {1} with args: {2}</p>
                            """.format(mv_json, os.path.basename(__file__),
                                       e.args)),
                        '[MobiDetails - Email Validation Error]')
            # 2nd check https://www.stopforumspam.com/
            # ex https://www.stopforumspam.com/api?ip=&email=&username=&f=json
            sfs_url = 'https://www.stopforumspam.com/api?ip={0}&email={1}&username={2}&f=json'.format(
                request.remote_addr, email, username)
            # print(sfs_url)
            try:
                sfs_json = json.loads(
                    http.request('GET', sfs_url).data.decode('utf-8'))
            except Exception:
                sfs_json = None
            if sfs_json is not None:
                try:
                    print(sfs_json)
                    if sfs_json['success'] == 1:
                        # sfs return a boolean for username, ip, email
                        # if email or ip = 1 => rejected
                        # username won't be rejected but a warning will be sent
                        if sfs_json['ip']['appears'] == 1 or \
                                sfs_json['email']['appears'] == 1:
                            error = """
                            Sorry, your input data is reported as risky.
                            If this is not the case, please send
                            us an email directly to
                            &#109;&#111;&#098;&#105;&#100;&#101;
                            &#116;&#097;&#105;&#108;&#115;
                            &#046;&#105;&#117;&#114;&#099;
                            &#064;&#103;&#109;&#097;&#105;&#108;
                            &#046;&#099;&#111;&#109;.
                            """
                        elif sfs_json['username']['appears'] == 1:
                            md_utilities.send_error_email(
                                md_utilities.prepare_email_html(
                                    'MobiDetails stop forum spam \
                                    username validation error', """
                                    <p>Stop forum spam username validation failed (user created but to follow):
                                    <br/> {0} <br /> - from {1} with url: {2}</p>
                                    """.format(sfs_json,
                                               os.path.basename(__file__),
                                               sfs_url)),
                                '[MobiDetails - Email Validation Error]')
                    else:
                        md_utilities.send_error_email(
                            md_utilities.prepare_email_html(
                                'MobiDetails stop forum spam validation error',
                                """
                                <p>Stop forum spam validation failed:<br/> {0}<br /> - from {1} with url: {2}</p>
                                """.format(sfs_json,
                                           os.path.basename(__file__),
                                           sfs_url)),
                            '[MobiDetails - Email Validation Error]')
                except Exception as e:
                    md_utilities.send_error_email(
                        md_utilities.prepare_email_html(
                            'MobiDetails stop forum spam validation error', """
                            <p>Stop forum spam validation failed:<br/> {0}<br /> - from {1} with args: {2}</p>
                            """.format(sfs_json, os.path.basename(__file__),
                                       e.args)),
                        '[MobiDetails - Email Validation Error]')
        if error is None:
            # curs.execute(
            #     "SELECT id FROM mobiuser WHERE username = '******'\
            #        OR email = '{1}'".format(username, email)
            # )
            curs.execute(
                """
                SELECT id
                FROM mobiuser
                WHERE username = %s OR email = %s
                """, (username, email))
            if curs.fetchone() is not None:
                error = 'User {0} or email address {1}\
                 is already registered.'.format(username, email)

        if error is None:
            key = secrets.token_urlsafe(32)
            curs.execute(
                """
                INSERT INTO mobiuser (username, password, country, institute, email, api_key, activated)
                VALUES (%s, %s, %s, %s, %s, %s, 'f')
                RETURNING id
                """, (username, generate_password_hash(password), country,
                      institute, email, key))
            user_id = curs.fetchone()[0]
            db.commit()
            md_utilities.send_email(
                md_utilities.prepare_email_html(
                    'MobiDetails - Account activation', """
                    Dear {0},
                    <p>thank you for registering in MobiDetails.
                     We hope you will find this website useful.</p>
                    <p>Please follow the link below to activate
                     your MobiDetails account:</p>
                    <p><a href="{1}{2}" title="Activate your MD account">
                    Activate your MD account</a></p>
                    <p>If you do not know why you receive this email,
                    do not follow the link and please alert
                    [email protected].</p><br />
                    """.format(
                        username, request.host_url.rstrip('/'),
                        url_for('auth.activate',
                                mobiuser_id=user_id,
                                api_key=key)),
                    False), '[MobiDetails - Account activation]', [email],
                [app.config["MAIL_ERROR_RECIPIENT"]])
            flash(
                """
                <br /><p>Your account has been created but requires an activation step.
                An email has been sent to {} with an activation link.</p><br />
                """.format(email), 'w3-pale-green')
            close_db()
            return redirect(url_for('md.index'), code=302)

        flash(error, 'w3-pale-red')
        if error is not None and not app.config['TESTING']:
            message_body = """
            <p>{0}</p><p>Originated from :</p><ul><li>
            Remote IP: {1}</li><li>Username: {2}</li>
            <li>Country: {3}</li><li>Institute: {4}</li>
            <li>Email: {5}</li></ul>
            """.format(error, request.remote_addr, username, country,
                       institute, email)
            md_utilities.send_error_email(
                md_utilities.prepare_email_html('MobiDetails error',
                                                message_body),
                '[MobiDetails - Registering Error]')
        close_db()
        return render_template('auth/register.html',
                               countries=md_utilities.countries,
                               prev_username=username,
                               prev_institute=institute,
                               prev_email=email)

    return render_template('auth/register.html',
                           countries=md_utilities.countries)
Esempio n. 16
0
def create():
    # start_time = time.time()
    # print(request.form['new_variant'])
    variant_regexp = md_utilities.regexp['variant']
    if request.form['new_variant'] == '':
        return md_utilities.danger_panel('variant creation attempt', 'Please fill in the form before submitting!')
    if re.search(r'^[\w-]+$', request.form['gene']) and \
            re.search(r'^NM_\d+$', request.form['acc_no']) and \
            re.search(rf'^c\.{variant_regexp}$', request.form['new_variant']) and \
            re.search(r'^\d+$', request.form['acc_version']):
        gene = request.form['gene']
        acc_no = request.form['acc_no']
        new_variant = request.form['new_variant']
        new_variant = new_variant.replace(" ", "").replace("\t", "")
        # new_variant = new_variant.replace("\t", "")
        original_variant = new_variant
        acc_version = request.form['acc_version']
        alt_nm = None
        if 'alt_iso' in request.form:
            alt_nm = request.form['alt_iso']
            # return md_utilities.danger_panel(alt_nm, acc_version)
            if alt_nm != '' and alt_nm != "{0}.{1}".format(acc_no, acc_version):
                acc_no, acc_version = alt_nm.split('.')
        # variant already registered?
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        var_db = new_variant.replace("c.", "")
        curs.execute(
            "SELECT id FROM variant_feature WHERE c_name = %s AND gene_name[2] = %s",
            (var_db, acc_no)
        )
        res = curs.fetchone()
        if res:
            close_db()
            return md_utilities.info_panel('Variant already in MobiDetails: ', var_db, res['id'])

        if re.search(r'c\..+', new_variant):
            # is vv alive?
            
            # vv_alive = None
            vv_base_url = md_utilities.get_vv_api_url()
            # try:
            #     json.loads(http.request('GET', md_utilities.urls['variant_validator_api_hello']).data.decode('utf-8'))
            # except Exception as e:
            #     try:
            #         json.loads(http.request('GET', md_utilities.urls['variant_validator_api_hello_backup']).data.decode('utf-8'))
            #         vv_base_url = md_utilities.urls['variant_validator_api_backup']
            #     except Exception as e:
            #         md_utilities.send_error_email(
            #             md_utilities.prepare_email_html(
            #                 'MobiDetails VariantValidator error',
            #                 '<p>VariantValidator looks down!!<br /> - from {0} with args: {1}</p>'.format(
            #                     os.path.basename(__file__), e.args
            #                 )
            #             ),
            #             '[MobiDetails - VariantValidator Error]'
            #         )
            #         # vv_data = {'apiVersion': 'Service Unavailable'}
            #         # vv_alive = {'status': 'Service Unavailable'}
            if not vv_base_url:
                close_db()
                return md_utilities.danger_panel(
                        new_variant, 'Variant Validator did not answer our call, status: Service Unavailable. \
                        I have been informed by email. Please retry later.')

            # http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
            if not alt_nm or acc_no == request.form['acc_no']:
                vv_url = "{0}VariantValidator/variantvalidator/GRCh38/{1}.{2}:{3}/{1}.{2}?content-type=application/json".format(
                    vv_base_url, acc_no, acc_version, new_variant
                )
            else:
                vv_url = "{0}VariantValidator/variantvalidator/GRCh38/{1}.{2}:{3}/all?content-type=application/json".format(
                    vv_base_url, acc_no, acc_version, new_variant
                )
            vv_key_var = "{0}.{1}:{2}".format(acc_no, acc_version, new_variant)
            try:
                http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
                vv_data = json.loads(http.request('GET', vv_url).data.decode('utf-8'))
            except Exception:
                close_db()
                return md_utilities.danger_panel(
                    new_variant,
                    'Variant Validator did not return any value for the variant.\
                    Either it is down or your nomenclature is very odd!'
                )
            if re.search('[di][neu][psl]', new_variant):
                # need to redefine vv_key_var for indels as the variant name returned by vv is likely to be different form the user's
                for key in vv_data:
                    if re.search('{0}.{1}'.format(acc_no, acc_version), key):
                        vv_key_var = key
                        # print(key)
                        var_obj = re.search(r':(c\..+)$', key)
                        if var_obj:
                            new_variant = var_obj.group(1)
        else:
            close_db()
            return md_utilities.danger_panel(new_variant, 'Please provide the variant name as HGVS c. nomenclature (including c.)')
        return md_utilities.create_var_vv(
            vv_key_var, gene, acc_no, new_variant,
            original_variant, acc_version,
            vv_data, 'webApp', db, g
        )
    else:
        close_db()
        return md_utilities.danger_panel('variant creation attempt', 'A mandatory argument is lacking or is malformed.')
Esempio n. 17
0
def reset_password():
    if (md_utilities.get_running_mode() == 'maintenance'):
        return render_template('md/index.html',
                               run_mode=md_utilities.get_running_mode())
    if request.method == 'GET':
        if re.search(r'^\d+$', request.args.get('mobiuser_id')) and \
                re.search(r'^[\d\.]+$', request.args.get('ts')):
            mobiuser_id = request.args.get('mobiuser_id')
            api_key = request.args.get('api_key')
            original_timestamp = request.args.get('ts')
            # we will keep the link alive for 30 minutes i.e. 1800 s
            if float(float(datetime.timestamp(
                datetime.now())
                ) - float(original_timestamp)) > 1800 or \
               float(float(datetime.timestamp(
                datetime.now())
                    ) - float(original_timestamp)) < 0:
                flash(
                    """
                    This link is outdated. Please try again the procedure.
                    """, 'w3-pale-red')
                return render_template('auth/login.html')
            db = get_db()
            curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            curs.execute(
                """
                SELECT id, api_key, activated
                FROM mobiuser
                WHERE id = %s AND api_key = %s
                """, (mobiuser_id, api_key))
            user = curs.fetchone()
            if user is None:
                message_body = """
                <p>Password reset exception</p><p>Received API key: {0} and mobiuser_id: {1} from {2}
                """.format(api_key, mobiuser_id, request.remote_addr)
                md_utilities.send_error_email(
                    md_utilities.prepare_email_html('MobiDetails error',
                                                    message_body),
                    '[MobiDetails - Password reset Error]')
                flash(
                    """
                    API key and user id do not seem to fit. An admin has been warned
                    """, 'w3-pale-red')
                close_db()
                return render_template('auth/forgot_pass.html')
            else:
                close_db()
                return render_template('auth/reset_pass.html',
                                       mobiuser_id=mobiuser_id,
                                       api_key=api_key)
        else:
            message_body = """
            <p>Password reset exception</p><p>Received timestamp: {0} and mobiuser_id: {1} from {2}
            """.format(request.args.get('ts'), request.args.get('mobiuser_id'),
                       request.remote_addr)
            md_utilities.send_error_email(
                md_utilities.prepare_email_html('MobiDetails error',
                                                message_body),
                '[MobiDetails - Password reset Error]')
            flash(
                """
                Some parameters are not legal. An admin has been warned
                """, 'w3-pale-red')
            return render_template('auth/forgot_pass.html')
    elif request.method == 'POST':
        mobiuser_id = request.form['mobiuser_id']
        api_key = request.form['api_key']
        password = request.form['password']
        error = None
        if len(password) < 8 or \
                not re.search(r'[a-z]', password) or \
                not re.search(r'[A-Z]', password) or \
                not re.search(r'[0-9]', password):
            error = """
                Password should be at least 8 characters and mix at least
                letters (upper and lower case) and numbers.
            """
        else:
            db = get_db()
            curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            curs.execute(
                """
                UPDATE mobiuser SET password= %s
                WHERE id = %s AND api_key = %s
                """, (generate_password_hash(password), mobiuser_id, api_key))
            db.commit()
            flash('Your password has just been reset.', 'w3-pale-green')
            close_db()
            return render_template('auth/login.html')
        if error is not None:
            flash(error, 'w3-pale-red')
            return render_template('auth/reset_pass.html',
                                   mobiuser_id=mobiuser_id,
                                   api_key=api_key)
    return render_template('md/unknown.html')
Esempio n. 18
0
def profile(mobiuser_id=0):
    if re.search(r'^\d+$', str(mobiuser_id)):
        user_id = g.user['id']
        if mobiuser_id != 0:
            user_id = mobiuser_id
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        curs.execute(
            """
            SELECT id, username, email, institute, country, api_key, email_pref, lovd_export, academic
            FROM mobiuser
            WHERE id = %s
            """, (user_id, ))
        mobiuser = curs.fetchone()
        error = None
        if mobiuser is None:
            md_utilities.send_error_email(
                md_utilities.prepare_email_html(
                    'MobiDetails error',
                    '<p>Bad profile attempt username: from id: {0} file: {1}\
</p>'.format(g.user['id'], os.path.basename(__file__))),
                '[MobiDetails - Profile Error]')
            error = 'You seem to be unknown by MobiDetails.'
            if mobiuser_id != 0:
                error = 'This user seems to be unknown by MobiDetails.'
        if mobiuser_id == 0:
            # curs.execute(
            #     "SELECT id, c_name, gene_name, p_name, creation_date \
            #     FROM variant_feature WHERE\
            #     creation_user = %s ORDER BY creation_date DESC",
            #     (g.user['id'],)
            # )
            curs.execute(
                """
                SELECT a.id, a.c_name, a.gene_symbol, a.p_name, a.creation_date, b.mobiuser_id
                FROM variant_feature a
                LEFT JOIN mobiuser_favourite b ON a.id = b.feature_id
                WHERE a.creation_user = %s
                ORDER BY a.creation_date DESC
                """, (g.user['id'], ))
            variants = curs.fetchall()
            num_var = curs.rowcount

            curs.execute(
                """
                SELECT * FROM variants_groups
                WHERE mobiuser_id = %s
                ORDER BY creation_date DESC
                """, (g.user['id'], ))
            variant_groups = curs.fetchall()
            variant_groups_number = curs.rowcount
            # we need to modify the username to propose a list name without special characters
            clean_username = re.sub(r'[^\w]', '_', mobiuser['username'])

            curs.execute(
                """
                SELECT a.id, a.c_name, a.ng_name, a.gene_symbol, a.p_name
                FROM variant_feature a, mobiuser_favourite b
                WHERE a.id = b.feature_id AND b.mobiuser_id = %s
                ORDER BY a.gene_symbol, a.ng_name
                """, (g.user['id'], ))
            variants_favourite = curs.fetchall()

            if error is None:
                # num_var_fav = curs.rowcount
                close_db()
                return render_template(
                    'auth/profile.html',
                    run_mode=md_utilities.get_running_mode(),
                    mobiuser=mobiuser,
                    view='own',
                    num_var=num_var,
                    num_var_fav=curs.rowcount,
                    variants=variants,
                    variants_favourite=variants_favourite,
                    variant_groups=variant_groups,
                    variant_groups_number=variant_groups_number + 1,
                    clean_username=clean_username)
        elif error is None:
            # other profile view
            close_db()
            return render_template('auth/profile.html',
                                   run_mode=md_utilities.get_running_mode(),
                                   mobiuser=mobiuser,
                                   view='other',
                                   num_var=None,
                                   num_var_fav=None,
                                   variants=None,
                                   variants_favourite=None,
                                   variant_groups=None,
                                   variant_groups_number=None,
                                   clean_username=None)

        flash(error, 'w3-pale-red')
        close_db()
        return render_template('md/index.html',
                               run_mode=md_utilities.get_running_mode())
    else:
        ('Invalid user ID!!', 'w3-pale-red')
        return render_template('md/index.html',
                               run_mode=md_utilities.get_running_mode())
Esempio n. 19
0
def login():
    referrer_page = None
    if request.method == 'GET':
        referrer_page = request.referrer
        # if request.referrer is not None and \
        #         (url_parse(request.referrer).host ==
        #            url_parse(request.base_url).host):
        #     referrer_page = request.referrer
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        try:
            referrer_page = request.form['referrer_page']
            # if request.form['referrer_page'] is not None and \
            #         (url_parse(request.form['referrer_page']).host ==
            #            url_parse(request.base_url).host:
            #     referrer_page = request.form['referrer_page']
        except Exception:
            pass
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        error = None
        curs.execute(
            """
            SELECT *
            FROM mobiuser
            WHERE email = %s
            """, (email, ))
        user = curs.fetchone()
        if user is None:
            error = 'Unknown email.'
        elif not check_password_hash(user['password'], password):
            error = 'Incorrect password.'
        elif user['activated'] is False:
            error = """
            This account is not activated.
            An email to activate your account
            has been sent to {}
            """.format(user['email'])
            # message, mail_object, receiver
            md_utilities.send_email(
                md_utilities.prepare_email_html(
                    'MobiDetails - Account activation', """
                    Dear {0},
                    <p>please follow the link below to activate your MobiDetails account:</p>
                    <p><a href="{1}{2}" title="Activate your MD account">
                    Activate your MD account</a></p>
                    <p>If you do not know why you receive this email,
                    do not follow the link and please alert
                    [email protected].</p><br />
                    """.format(
                        user['username'], request.host_url.rstrip('/'),
                        url_for('auth.activate',
                                mobiuser_id=user['id'],
                                api_key=user['api_key'])), False),
                '[MobiDetails - Account activation]', [email])

        if error is None:
            session.clear()
            close_db()
            flash(
                'You have successfully been logged in as {}.'.format(
                    user["username"]), 'w3-pale-green')
            session['user_id'] = user['id']
            if referrer_page is None or \
                    (url_parse(referrer_page).host !=
                        url_parse(request.base_url).host or
                        re.search(r'(login|register)', referrer_page)):
                return redirect(url_for(
                    'auth.profile',
                    run_mode=md_utilities.get_running_mode(),
                    mobiuser_id=0),
                                code=302)
            else:
                if referrer_page is not None and \
                        (url_parse(referrer_page).host ==
                            url_parse(request.base_url).host):
                    # not coming from mobidetails
                    # rebuild redirect URL
                    return redirect(
                        md_utilities.build_redirect_url(referrer_page),
                        code=302)
                else:
                    return redirect(url_for(
                        'auth.profile',
                        run_mode=md_utilities.get_running_mode(),
                        mobiuser_id=0),
                                    code=302)
        close_db()
        flash(error, 'w3-pale-red')
    # not coming from mobidetails
    # rebuild redirect URL
    return render_template(
        'auth/login.html',
        run_mode=md_utilities.get_running_mode(),
        referrer_page=md_utilities.build_redirect_url(referrer_page))
Esempio n. 20
0
def api_variant_create(variant_chgvs=None, caller=None, api_key=None):
    # print(request.form)
    # print(request.args)
    # get params
    # swagger/curl sends request.args e.g.
    # curl -X POST "http://10.34.20.79:5001/api/variant/create?variant_chgvs=NM_005422.2%3Ac.5040G%3ET&api_key=XXX" -H  "accept: application/json"
    # while
    # urllib3 request from create_vars_batch.py sends request.form
    if request.args.get('variant_chgvs') and \
            request.args.get('caller') and \
            request.args.get('api_key'):
        variant_chgvs = request.args.get('variant_chgvs', type=str)
        caller = request.args.get('caller', type=str)
        api_key = request.args.get('api_key', type=str)
    elif 'variant_chgvs' in request.form and \
            'caller' in request.form and \
            'api_key' in request.form:
        variant_chgvs = request.form['variant_chgvs']
        caller = request.form['caller']
        api_key = request.form['api_key']
    else:
        if caller == 'cli':
            return jsonify(mobidetails_error='I cannot fetch the right parameters')
        else:
            flash('I cannot fetch the right parameters', 'w3-pale-red')
            return redirect(url_for('md.index'))
    if variant_chgvs is not None and \
            caller is not None and \
            api_key is not None:
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        # mobiuser_id = None
        res_check_api_key = md_utilities.check_api_key(db, api_key)
        if 'mobidetails_error' in res_check_api_key:
            if caller == 'cli':
                return jsonify(res_check_api_key)
            else:
                flash(res_check_api_key['mobidetails_error'], 'w3-pale-red')
                return redirect(url_for('md.index'))
        else:
            g.user = res_check_api_key['mobiuser']
        if md_utilities.check_caller(caller) == 'Invalid caller submitted':
            if caller == 'cli':
                return jsonify(mobidetails_error='Invalid caller submitted')
            else:
                flash('Invalid caller submitted to API.', 'w3-pale-red')
                return redirect(url_for('md.index'))
        # if len(api_key) != 43:
        #     return jsonify(mobidetails_error='Invalid API key')
        # else:
        #     curs.execute(
        #         "SELECT * FROM mobiuser WHERE api_key = %s",
        #         (api_key,)
        #     )
        #     res = curs.fetchone()
        #     if res is None:
        #         return jsonify(mobidetails_error='Unknown API key')
        #     else:
        #         g.user = res
        # if variant_chgvs is None:
        #     return jsonify(mobidetails_error='No variant submitted')
        variant_regexp = md_utilities.regexp['variant']
        match_object = re.search(rf'^([Nn][Mm]_\d+)\.(\d{{1,2}}):c\.({variant_regexp})', urllib.parse.unquote(variant_chgvs))
        if match_object:
            # match_object = re.search(r'^([Nn][Mm]_\d+)\.(\d{1,2}):c\.(.+)', variant_chgvs)
            acc_no, acc_version, new_variant = match_object.group(1), match_object.group(2), match_object.group(3)
            new_variant = new_variant.replace(" ", "").replace("\t", "")
            # new_variant = new_variant.replace("\t", "")
            original_variant = new_variant
            curs.execute(
                "SELECT id FROM variant_feature WHERE c_name = %s AND gene_name[2] = %s",
                (new_variant, acc_no)
            )
            res = curs.fetchone()
            if res is not None:
                if caller == 'cli':
                    return jsonify(
                        mobidetails_id=res['id'],
                        url='{0}{1}'.format(
                            request.host_url[:-1],
                            url_for('md.variant', variant_id=res['id'])
                        )
                    )
                else:
                    return redirect(url_for('md.variant', variant_id=res['id']))
                
            else:
                # creation
                # get gene
                curs.execute(
                    "SELECT name[1] as gene FROM gene WHERE name[2] = %s",
                    (acc_no,)
                )
                res_gene = curs.fetchone()
                if res_gene is None:
                    return jsonify(mobidetails_error='The gene corresponding to {} is not yet present in MobiDetails'.format(acc_no))
               
                vv_base_url = md_utilities.get_vv_api_url()
                if not vv_base_url:
                    close_db()
                    if caller == 'cli':
                        return jsonify(mobidetails_error='Variant Validator looks down!.')
                    else:
                        flash('TVariant Validator looks down!.', 'w3-pale-red')
                        return redirect(url_for('md.index'))
                vv_url = "{0}VariantValidator/variantvalidator/GRCh38/{1}.{2}:{3}/all?content-type=application/json".format(
                    vv_base_url, acc_no, acc_version, new_variant
                )
                vv_key_var = "{0}.{1}:c.{2}".format(acc_no, acc_version, new_variant)

                try:
                    http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
                    vv_data = json.loads(http.request('GET', vv_url).data.decode('utf-8'))
                except Exception:
                    close_db()
                    if caller == 'cli':
                        return jsonify(mobidetails_error='Variant Validator did not return any value for the variant {}.'.format(new_variant))
                    else:
                        try:
                            flash('There has been a issue with the annotation of the variant via VariantValidator. \
                                  The error is the following: {}'.format(vv_data['validation_warning_1']['validation_warnings']), 'w3-pale-red')
                        except Exception:
                            flash('There has been a issue with the annotation of the variant via VariantValidator. \
                                  Sorry for the inconvenience. You may want to try directly in MobiDetails.', 'w3-pale-red')
                        return redirect(url_for('md.index'))
                if re.search('[di][neu][psl]', new_variant):
                    # need to redefine vv_key_var for indels as the variant name returned by vv is likely to be different form the user's
                    for key in vv_data.keys():
                        if re.search('{0}.{1}'.format(acc_no, acc_version), key):
                            vv_key_var = key
                            # print(key)
                            var_obj = re.search(r':c\.(.+)$', key)
                            if var_obj is not None:
                                new_variant = var_obj.group(1)
                creation_dict = md_utilities.create_var_vv(
                    vv_key_var, res_gene['gene'], acc_no,
                    'c.{}'.format(new_variant), original_variant,
                    acc_version, vv_data, 'api', db, g
                )
                if caller == 'cli':
                    return jsonify(creation_dict)
                else:
                    return redirect(url_for('md.variant', variant_id=creation_dict['mobidetails_id']))
        else:
            if caller == 'cli':
                return jsonify(mobidetails_error='Malformed query {}'.format(urllib.parse.unquote(variant_chgvs)))
            else:
                flash('The query seems to be malformed: {}.'.format(urllib.parse.unquote(variant_chgvs)), 'w3-pale-red')
                return redirect(url_for('md.index'))
    else:
        if caller == 'cli':
            return jsonify(mobidetails_error='Invalid parameters')
        else:
            flash('The submitted parameters looks invalid!!!', 'w3-pale-red')
            return redirect(url_for('md.index'))
Esempio n. 21
0
def intervar():
    genome_regexp = md_utilities.regexp['genome']
    nochr_chrom_regexp = md_utilities.regexp['nochr_chrom']
    if re.search(rf'^{genome_regexp}$', request.form['genome']) and \
            re.search(rf'^{nochr_chrom_regexp}$', request.form['chrom']) and \
            re.search(r'^\d+$', request.form['pos']) and \
            re.search(r'^[ATGC]+$', request.form['ref']) and \
            re.search(r'^[ATGC]+$', request.form['alt']) and \
            'gene' in request.form:
        genome = request.form['genome']
        chrom = request.form['chrom']
        pos = request.form['pos']
        ref = request.form['ref']
        alt = request.form['alt']
        gene = request.form['gene']
        if len(ref) > 1 or len(alt) > 1:
            return 'No wintervar for indels'
        if ref == alt:
            return 'hg19 reference is equal to variant: no wIntervar query'
        http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
        intervar_url = "{0}{1}_updated.v.201904&chr={2}&pos={3}&ref={4}&alt={5}".format(
            md_utilities.urls['intervar_api'], genome, chrom,
            pos, ref, alt
        )
        try:
            intervar_data = [json.loads(http.request('GET', intervar_url).data.decode('utf-8'))]
        except Exception:
            try:
                # intervar can return mutliple json objects, e.g.:
                # {"Intervar":"Uncertain significance","Chromosome":1,"Position_hg19":151141512,"Ref_allele":"T","Alt_allele":"A","Gene":"SCNM1","PVS1":0,"PS1":0,"PS2":0,"PS3":0,"PS4":0,"PM1":1,"PM2":1,"PM3":0,"PM4":0,"PM5":0,"PM6":0,"PP1":0,"PP2":0,"PP3":0,"PP4":0,"PP5":0,"BA1":0,"BP1":0,"BP2":0,"BP3":0,"BP4":0,"BP5":0,"BP6":0,"BP7":0,"BS1":0,"BS2":0,"BS3":0,"BS4":0}{"Intervar":"Uncertain significance","Chromosome":1,"Position_hg19":151141512,"Ref_allele":"T","Alt_allele":"A","Gene":"TNFAIP8L2-SCNM1","PVS1":0,"PS1":0,"PS2":0,"PS3":0,"PS4":0,"PM1":1,"PM2":1,"PM3":0,"PM4":0,"PM5":0,"PM6":0,"PP1":0,"PP2":0,"PP3":0,"PP4":0,"PP5":0,"BA1":0,"BP1":0,"BP2":0,"BP3":0,"BP4":0,"BP5":0,"BP6":0,"BP7":0,"BS1":0,"BS2":0,"BS3":0,"BS4":0}
                intervar_list = re.split('}{', http.request('GET', intervar_url).data.decode('utf-8'))
                i = 0
                for obj in intervar_list:
                    # some housekeeping to get proper strings
                    obj = obj.replace('{', '').replace('}', '')
                    obj = '{{{}}}'.format(obj)
                    intervar_list[i] = obj
                    i += 1
                #     if i == 0:
                #         intervar_list[i] = '{0}}}'.format(obj)
                #     else:
                #         intervar_list[i] = '{{{0}'.format(obj)
                # if i > 2:
                #     intervar_list[i-1] = '{0}}}'.format(intervar_list[i-1])
                intervar_data = []
                for obj in intervar_list:
                    # print(obj)
                    intervar_data.append(json.loads(obj))
            except Exception as e:
                md_utilities.send_error_email(
                    md_utilities.prepare_email_html(
                        'MobiDetails API error',
                        '<p>Intervar API call failed for {0}-{1}-{2}-{3}-{4} - url: {5} <br /> - from {6} with args: {7}</p>'.format(
                            genome, chrom, pos, ref, alt,
                            intervar_url, os.path.basename(__file__), e.args
                        )
                    ),
                    '[MobiDetails - API Error]'
                )
                return "<span>No wintervar class</span>"
        intervar_acmg = None
        if len(intervar_data) == 1:
            intervar_acmg = intervar_data[0]['Intervar']
        else:
            for intervar_dict in intervar_data:
                # intervar likely returns several json objects
                if intervar_dict['Gene'] == gene:
                    intervar_acmg = intervar_dict['Intervar']
        if intervar_acmg is not None:
            db = get_db()
            curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
            curs.execute(
                "SELECT html_code FROM valid_class WHERE acmg_translation = '{}'".format(
                    intervar_acmg.lower()
                )
            )
            res = curs.fetchone()
            close_db()
            return "<span style='color:{0};'>{1}</span>".format(res['html_code'], intervar_acmg)
        else:
            return "<span>No wintervar class</span>"
    else:
        md_utilities.send_error_email(
            md_utilities.prepare_email_html(
                'MobiDetails API error',
                '<p>Intervar API call failed for {0}-{1}-{2}-{3}-{4}<br /> - from {5} with args: A mandatory argument is missing</p>'.format(
                    request.form['genome'], request.form['chrom'],
                    request.form['pos'], request.form['ref'],
                    request.form['alt'], os.path.basename(__file__)
                )
            ),
            '[MobiDetails - API Error]'
        )
        return "<span>No wintervar class</span>"
Esempio n. 22
0
def api_variant_create(variant_chgvs=None, caller=None, api_key=None):
    # get params
    caller = md_utilities.get_post_param(request, 'caller')
    variant_chgvs = md_utilities.get_post_param(request, 'variant_chgvs')
    api_key = md_utilities.get_post_param(request, 'api_key')
    if variant_chgvs and \
            caller and \
            api_key:
        db = get_db()
        curs = db.cursor(cursor_factory=psycopg2.extras.DictCursor)
        # mobiuser_id = None
        res_check_api_key = md_utilities.check_api_key(db, api_key)
        if 'mobidetails_error' in res_check_api_key:
            if caller == 'cli':
                return jsonify(res_check_api_key)
            else:
                flash(res_check_api_key['mobidetails_error'], 'w3-pale-red')
                return redirect(url_for('md.index'))
        else:
            g.user = res_check_api_key['mobiuser']
        if md_utilities.check_caller(caller) == 'Invalid caller submitted':
            if caller == 'cli':
                return jsonify(mobidetails_error='Invalid caller submitted')
            else:
                flash('Invalid caller submitted to API.', 'w3-pale-red')
                return redirect(url_for('md.index'))

        variant_regexp = md_utilities.regexp['variant']
        match_object = re.search(
            rf'^([Nn][Mm]_\d+)\.(\d{{1,2}}):c\.({variant_regexp})',
            urllib.parse.unquote(variant_chgvs))
        if match_object:
            # match_object = re.search(r'^([Nn][Mm]_\d+)\.(\d{1,2}):c\.(.+)', variant_chgvs)
            acc_no, submitted_nm_version, new_variant = match_object.group(
                1), match_object.group(2), match_object.group(3)
            # acc_no, acc_version, new_variant = match_object.group(1), match_object.group(2), match_object.group(3)
            new_variant = new_variant.replace(" ", "").replace("\t", "")
            # new_variant = new_variant.replace("\t", "")
            original_variant = new_variant
            curs.execute(
                "SELECT id FROM variant_feature WHERE c_name = %s AND gene_name[2] = %s",
                (new_variant, acc_no))
            res = curs.fetchone()
            if res is not None:
                if caller == 'cli':
                    return jsonify(mobidetails_id=res['id'],
                                   url='{0}{1}'.format(
                                       request.host_url[:-1],
                                       url_for('md.variant',
                                               variant_id=res['id'])))
                else:
                    return redirect(url_for('md.variant',
                                            variant_id=res['id']))

            else:
                # creation
                # get gene
                curs.execute(
                    "SELECT name[1] as gene, nm_version FROM gene WHERE name[2] = %s and variant_creation = 'ok'",
                    (acc_no, ))
                res_gene = curs.fetchone()
                if res_gene is None:
                    if caller == 'cli':
                        return jsonify(
                            mobidetails_error=
                            'The gene corresponding to {} is not yet available for variant annotation in MobiDetails'
                            .format(acc_no))
                    else:
                        flash(
                            'The gene corresponding to {} is not available for variant annotation in MobiDetails.'
                            .format(acc_no), 'w3-pale-red')
                        return redirect(url_for('md.index'))
                if int(res_gene['nm_version']) != int(submitted_nm_version):
                    if caller == 'cli':
                        return jsonify(
                            mobidetails_error=
                            'The RefSeq accession number submitted ({0}) for {1} does not match MobiDetail\'s ({2}).'
                            .format(submitted_nm_version, acc_no,
                                    res_gene['nm_version']))
                    else:
                        flash(
                            'The RefSeq accession number submitted ({0}) for {1} does not match MobiDetail\'s ({2}).'
                            .format(submitted_nm_version, acc_no,
                                    res_gene['nm_version']), 'w3-pale-red')
                        return redirect(url_for('md.index'))
                acc_version = res_gene['nm_version']
                vv_base_url = md_utilities.get_vv_api_url()
                if not vv_base_url:
                    close_db()
                    if caller == 'cli':
                        return jsonify(
                            mobidetails_error='Variant Validator looks down!.')
                    else:
                        flash('Variant Validator looks down!.', 'w3-pale-red')
                        return redirect(url_for('md.index'))
                vv_url = "{0}VariantValidator/variantvalidator/GRCh38/{1}.{2}:{3}/all?content-type=application/json".format(
                    vv_base_url, acc_no, acc_version, new_variant)
                vv_key_var = "{0}.{1}:c.{2}".format(acc_no, acc_version,
                                                    new_variant)

                try:
                    http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',
                                               ca_certs=certifi.where())
                    vv_data = json.loads(
                        http.request('GET', vv_url).data.decode('utf-8'))
                except Exception:
                    close_db()
                    if caller == 'cli':
                        return jsonify(
                            mobidetails_error=
                            'Variant Validator did not return any value for the variant {}.'
                            .format(new_variant))
                    else:
                        try:
                            flash(
                                'There has been a issue with the annotation of the variant via VariantValidator. \
                                  The error is the following: {}'.format(
                                    vv_data['validation_warning_1']
                                    ['validation_warnings']), 'w3-pale-red')
                        except Exception:
                            flash(
                                'There has been a issue with the annotation of the variant via VariantValidator. \
                                  Sorry for the inconvenience. You may want to try directly in MobiDetails.',
                                'w3-pale-red')
                        return redirect(url_for('md.index'))
                if re.search('[di][neu][psl]', new_variant):
                    # need to redefine vv_key_var for indels as the variant name returned by vv is likely to be different form the user's
                    for key in vv_data.keys():
                        if re.search('{0}.{1}'.format(acc_no, acc_version),
                                     key):
                            vv_key_var = key
                            # print(key)
                            var_obj = re.search(r':c\.(.+)$', key)
                            if var_obj is not None:
                                new_variant = var_obj.group(1)
                creation_dict = md_utilities.create_var_vv(
                    vv_key_var, res_gene['gene'], acc_no,
                    'c.{}'.format(new_variant), original_variant, acc_version,
                    vv_data, 'api', db, g)
                if 'mobidetails_error' in creation_dict:
                    if caller == 'cli':
                        return jsonify(creation_dict)
                    else:
                        flash(creation_dict['mobidetails_error'],
                              'w3-pale-red')
                        return redirect(url_for('md.index'))
                if caller == 'cli':
                    return jsonify(creation_dict)
                else:
                    return redirect(
                        url_for('md.variant',
                                variant_id=creation_dict['mobidetails_id']))
        else:
            if caller == 'cli':
                return jsonify(mobidetails_error='Malformed query {}'.format(
                    urllib.parse.unquote(variant_chgvs)))
            else:
                flash(
                    'The query seems to be malformed: {}.'.format(
                        urllib.parse.unquote(variant_chgvs)), 'w3-pale-red')
                return redirect(url_for('md.index'))
    else:
        if caller == 'cli':
            return jsonify(mobidetails_error='Invalid parameters')
        else:
            flash('The submitted parameters looks invalid!!!', 'w3-pale-red')
            return redirect(url_for('md.index'))