{"id":5801,"date":"2025-03-03T18:22:02","date_gmt":"2025-03-03T17:22:02","guid":{"rendered":"https:\/\/spgoo.org\/?page_id=5801"},"modified":"2026-01-06T14:37:18","modified_gmt":"2026-01-06T13:37:18","slug":"web-service-sous-python","status":"publish","type":"page","link":"https:\/\/spgoo.org\/?page_id=5801","title":{"rendered":"Web Service Flask"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Web Service sous Python : Flask (Janvier 2026)<\/h2>\n\n\n\n<p>Mise en oeuvre et d\u00e9veloppement de web service s\u00e9curis\u00e9 sous Flask pour desservir plusieurs plateformes web : PASSY, Emolgine et d&#8217;autres.<\/p>\n\n\n\n<p>Nous allons d\u00e9tailler deux aspects de ces possibilit\u00e9s de couplage : <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>interfa\u00e7age  avec des bases de donn\u00e9es <\/li>\n\n\n\n<li>ex\u00e9cution de module python ou autres langage. <\/li>\n<\/ul>\n\n\n\n<p>Et pour finir faire une comparaison avec des environnement Java de type Spring Boot. <\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-68ece39ac96914d5253d83911251f2b7\">Mise en  oeuvre dans EMOLGINE : couplage ex\u00e9cution de code<\/p>\n\n\n\n<p>Emolgine plateforme de production et de s\u00e9lection de mol\u00e9cules \u00e0 usage pharmacologique. Le besoin de la plateforme est de pouvoir lors de la manipulation d&#8217;un ensemble de mol\u00e9cules de d\u00e9finir en fonction de la m\u00e9thode propos\u00e9e des similarit\u00e9s entre elles. Ce calcul de similarit\u00e9 doit \u00eatre \u00e9galement effectu\u00e9 au niveau des clusters. Pour ce faire deux codes d\u00e9di\u00e9s et mis au point par PK ont \u00e9t\u00e9 d\u00e9velopp\u00e9s et test\u00e9s. Le tout est d&#8217;offrir \u00e0 l&#8217;utilisateur lors de  sa s\u00e9lection de mol\u00e9cules la possibilit\u00e9 d&#8217;identifier des niveaux de similarit\u00e9 au niveau de son interface. Pour ce faire nous avons mis en place via des appels fetch en javascript  des liens vers l&#8217;ex\u00e9cution de ces scripts. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from flask import Flask, request, jsonify\nimport sys\nfrom rdkit import Chem\nfrom rdkit.Chem import  rdMolDescriptors\nfrom numba import njit\nimport numpy as np\nfrom create_sim_csv_from_smi import *\nfrom create_sim_csv_from_cluster_mol_site import *\nfrom create_sim_csv_from_Lcluster_with_smile import *\nfrom get_info import *\nimport uuid\n\napp = Flask(__name__)\n\n@app.route(\"\/exec\", methods=&#91;\"POST\"])\ndef index():\n    request_data = request.get_json()\n    smiles = request_data&#91;'smiles']\n    path=\".\/tmp\/\"\n    name_file=str(uuid.uuid4())\n    with open(path+name_file, 'w') as f:\n       for smile in smiles:\n         f.write(smile+\"\\n\")\n    tp=appel_exec(path,name_file)\n    code=\"\"\n    with open(path+name_file+\".csv\", mode=\"r\", encoding=\"utf-8\") as hello:\n         code = hello.read()\n\n    # lecture du fichier resultat pour renvoi\n    return format(code)\n\n@app.route(\"\/exec_ws_sim_mol\", methods=&#91;\"POST\"])\ndef index_ws():\n    request_data = request.get_json()\n    smiles = request_data&#91;'smiles']\n    similarites = request_data&#91;'similarites']\n    fingerprints = request_data&#91;'fingerprints']\n    tp=appel_exec_ws(smiles,similarites,fingerprints)\n    return format(tp)\n\n@app.route(\"\/exec_ws_sim_cluster\", methods=&#91;\"POST\"])\ndef index_wss_sim_cluster():\n    request_data = request.get_json()\n    cluster = request_data&#91;'cluster']\n    tp=appel_exec_ws_sim_cluster(cluster)\n    return format(tp)\n\n@app.route(\"\/exec_ws_sim_cluster_molecules\", methods=&#91;\"POST\"])\ndef index_wss_sim_cluster_molecules():\n    request_data = request.get_json()\n    inchikey = request_data&#91;'inchikey']\n    cluster = request_data&#91;'cluster']\n    tp=appel_exec_ws_cluster_mol(inchikey,cluster)\n    return format(tp)\n\n@app.route(\"\/exec_get_info\", methods=&#91;\"POST\"])\ndef index_wss_get_info():\n    request_data = request.get_json()\n    cas = request_data&#91;'cas']\n    elemnt = request_data&#91;'id']\n    tp=appel_info_emolgine(cas,elemnt)\n    return format(tp)\n\nif __name__ == \"__main__\":\n    from waitress import serve\n    serve(app,host=\"0.0.0.0\", port=8090)<\/code><\/pre>\n\n\n\n<p>D\u00e9tail d&#8217;un exemple d&#8217;ex\u00e9cution :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import sys\nfrom rdkit import Chem\nfrom rdkit.Chem import  rdFingerprintGenerator\nfrom rdkit.Chem import  rdMolDescriptors\nfrom numba import njit\nimport numpy as np\nimport json\n# -----------------------------------------------\n# avec fonction de regroupement implement\u00e9e \n# ---------------------------------------------------\ndef get_Vfp_from_mol( mol, radius=2, nBits=2048, with_chirality=False, with_features=True, as_bitVect=True,):\n    \"\"\"\n    Gets a  Morgan fingerprint for a molecule\n    \"\"\"\n    rfp=rdMolDescriptors.GetMorganFingerprintAsBitVect(mol,radius,nBits=nBits,useFeatures=with_features,\n             useChirality=with_chirality,)\n    Vfp =  np.frombuffer(rfp.ToBitString().encode(), 'u1') - ord('0') # https:\/\/github.com\/rdkit\/rdkit\/discussions\/3863\n    return Vfp.astype(bool)\n\ndef get_Mfp_from_Lmol( Lmol, with_chirality=False, radius=3,):\n    mfpgen = rdFingerprintGenerator.GetMorganGenerator(radius=3,fpSize=2048)\n    LVfp = &#91;]\n    for mol in Lmol:\n        rfp = mfpgen.GetFingerprint(mol)\n        Vfp = np.frombuffer(rfp.ToBitString().encode(), 'u1') - ord('0')\n        LVfp.append(Vfp.astype(bool))\n    return np.array(LVfp)\n\ndef get_sim_bw_Vfp( Vfp1, Vfp2):\n    return round(get_sim_bw_Vfp_njit(Vfp1,  Vfp2),2)\n\n@njit \ndef get_sim_bw_Vfp_njit(Vfp1,  Vfp2):\n    n = Vfp1.shape&#91;0]\n    # -----------------\n    n11 = 0\n    n00 = 0\n    for k in range(n):\n        n11 += (Vfp1&#91;k] * Vfp2&#91;k])\n        if (Vfp1&#91;k] == 0) and ( Vfp2&#91;k] == 0):\n            n00 += 1\n    return n11 \/ (n - n00) \n\ndef get_Ls_sim_from_Mfp( Mfp, sim_min=0.6,):\n    n = len(Mfp)\n    Ls = &#91;]\n    for i in range(n):\n        for j in range(i+1, n):\n            sim = get_sim_bw_Vfp(Mfp&#91;i], Mfp&#91;j])\n            if sim &gt; sim_min:\n                Ls.append(&#91;i,j,sim])\n                #Ls.append(f\"{i}, {j}\")\n    return Ls\n\ndef create_txt_from_L( L, fname,):\n    with open(fname, \"w\") as fw:\n        for x in L:\n            fw.write(f\"{x}\\n\")\n\ndef regroupement(tab):\n    groupes={}\n    # generation des groupes  par defaut, chaque element forme son propre groupe\n    for elem in tab:\n     if str(elem&#91;0]) not in groupes.keys():\n         groupes&#91;elem&#91;0]]=&#91;]\n     if str(elem&#91;1]) not in groupes.keys():\n         groupes&#91;elem&#91;1]]=&#91;]\n    for elem in tab:\n      # on detruit la cle du deuxi\u00e8me element\n      if elem&#91;0] in groupes:\n        if elem&#91;1] in groupes:\n           del groupes&#91;elem&#91;1]]\n           groupes&#91;elem&#91;0]].append(elem&#91;1])\n      # il est dans un sous groupe il faut trouver lequel et d\u00e9truire ensuite l'entr\u00e9e correspondante\n      else:\n        for grp in groupes:\n           if groupes&#91;grp].count(elem&#91;0])&gt;0 and groupes&#91;grp].count(elem&#91;1])==0:\n               groupes&#91;grp].append(elem&#91;1])\n               if elem&#91;1] in groupes:\n                  if len(groupes&#91;elem&#91;1]])==0:\n                      del groupes&#91;elem&#91;1]]\n                      break;\n    return groupes\n\n# ===============================================================\n\ndef appel_exec(path,smi):\n   with open(path+smi, \"r\") as fp:\n       Lsmile = fp.readlines()\n   Lmol = &#91;Chem.MolFromSmiles(smile) for smile in Lsmile]\n   Mfp = get_Mfp_from_Lmol(Lmol)\n   Ls = get_Ls_sim_from_Mfp(Mfp)\n   create_txt_from_L(Ls, path+smi+\".csv\")\n\n# on fournit un tableau contenant des dict &#91;id, smile]\ndef appel_exec_ws(Lsmile):\n   Lmol = &#91;Chem.MolFromSmiles(smile&#91;\"smile\"]) for smile in Lsmile]\n   Mfp = get_Mfp_from_Lmol(Lmol)\n   Ls = get_Ls_sim_from_Mfp(Mfp)\n   # on a des couples de similarit\u00e9s qu'il faut recomposer en groupes avec le bon id \n   Ls_YS=regroupement(Ls)\n   result=&#91;]\n   for couple in Ls:\n        tab_id=&#91;]\n        if len(Ls_YS&#91;couple])==1:\n           tab_id.append(Lsmile&#91;couple]&#91;\"id\"])\n           tab_id.append(Lsmile&#91;Ls_YS&#91;couple]&#91;0]]&#91;\"id\"])\n        else:\n           for el in Ls_YS&#91;couple]:\n              tab_id.append(Lsmile&#91;el]&#91;\"id\"])\n\n        result.append(tab_id)\n   return json.dumps(result)<\/code><\/pre>\n\n\n\n<p class=\"has-vivid-green-cyan-color has-text-color has-link-color has-medium-font-size wp-elements-697919250279fb0a763041a62190a4c0\">S\u00e9curisation du web service :<\/p>\n\n\n\n<p>Faire en sorte de limiter les acc\u00e8s \u00e0 ce service sur le serveur : par l&#8217;utilisation de token et de bloquer via le firewall par des r\u00e8gles toute tentative d&#8217;une machine externe.<\/p>\n\n\n\n<p class=\"has-vivid-green-cyan-color has-text-color has-link-color has-medium-font-size wp-elements-381571d58f3a09d20a6b5eda6d5e8830\">Conteneurisation :<\/p>\n\n\n\n<p>Encapsuler l&#8217;ensemble dans une image docker afinde permettre l&#8217;int\u00e9gration avec la plateforme. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-vivid-cyan-blue-color has-text-color has-link-color has-medium-font-size wp-elements-db3cce1382c2733e9a45c83822dbb781\">Mise en oeuvre dans le cadre de PASSY : <\/p>\n\n\n\n<p>L&#8217;objectif dans cette plateforme est de fournir des traitements d&#8217;analyse sonore. Plusieurs possibilit\u00e9s ont \u00e9t\u00e9 \u00e9tudi\u00e9es : le d\u00e9veloppement en javascript en s&#8217;appuyant sur des librairies d\u00e9di\u00e9es de type WaveSurfer ou autres et  l&#8217;utilisation d&#8217;application m\u00e9tiers.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Web Service sous Python : Flask (Janvier 2026) Mise en oeuvre et d\u00e9veloppement de web service s\u00e9curis\u00e9 sous Flask pour desservir plusieurs plateformes web : PASSY, Emolgine et d&#8217;autres. Nous allons d\u00e9tailler deux aspects de ces possibilit\u00e9s de couplage : Et pour finir faire une comparaison avec des environnement Java de type Spring Boot. Mise [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-5801","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/5801","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spgoo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5801"}],"version-history":[{"count":23,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/5801\/revisions"}],"predecessor-version":[{"id":11598,"href":"https:\/\/spgoo.org\/index.php?rest_route=\/wp\/v2\/pages\/5801\/revisions\/11598"}],"wp:attachment":[{"href":"https:\/\/spgoo.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5801"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}