Skip to content

Commit

Permalink
Merge pull request #68 from Jumitti/beta
Browse files Browse the repository at this point in the history
Genome assembly
  • Loading branch information
Jumitti authored Oct 8, 2024
2 parents 1064489 + dfefceb commit fa119b8
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 18 deletions.
15 changes: 10 additions & 5 deletions TFinder-v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,11 @@ def load_lottiefile(filepath: str):
f" - TFinder on [Streamlit](https://streamlit.io/): [https://tfinder-ipmc.streamlit.app/](https://tfinder-ipmc.streamlit.app/)\n"
f" - TFinder on [Health Universe](https://www.healthuniverse.com/): [https://apps.healthuniverse.com/nhu-dxv-ktj](https://apps.healthuniverse.com/nhu-dxv-ktj)\n"
f" - (BETA) TFinder: [https://tfinder-beta.streamlit.app/](https://tfinder-beta.streamlit.app/)\n")

if st.secrets['ncbi_error'] == "True":
st.error("⚠ NCBI server maintenance, problems and slowdowns may be observed")
try:
if st.secrets['ncbi_error'] == "True":
st.error("⚠ NCBI server maintenance, problems and slowdowns may be observed")
except Exception as e:
print(e)

if chosen_tab == HOME:
home_page()
Expand Down Expand Up @@ -261,8 +263,11 @@ def load_lottiefile(filepath: str):
st.markdown(
'TFinder use [NCBI API](https://www.ncbi.nlm.nih.gov/books/NBK25497/#chapter2.Usage_Guidelines_and_Requiremen)'
': More information [NCBI Website and Data Usage Policies and Disclaimers](https://www.ncbi.nlm.nih.gov/home/about/policies/)')
if st.secrets['ncbi_error'] == "True":
st.error("⚠ NCBI server maintenance, problems and slowdowns may be observed")
try:
if st.secrets['ncbi_error'] == "True":
st.error("⚠ NCBI server maintenance, problems and slowdowns may be observed")
except Exception as e:
print(e)
st.markdown("TFinder use [JASPAR API](https://doi.org/10.1093/bioinformatics/btx804)")
st.markdown('')
st.markdown(
Expand Down
12 changes: 6 additions & 6 deletions navigation/aio.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ def aio_page():
with tab1:
# Species
st.markdown("🔹 :blue[**Step 1.2**] Species of gene names and sliced variants:")
col1, col2, = st.columns(2)
with col1:
species = st.selectbox("🔹 :blue[**Step 1.2**] Select species of gene names:",
col1, col2, col3 = st.columns(3)
species = col1.selectbox("🔹 :blue[**Step 1.2**] Select species of gene names:",
["Human", "Mouse", "Rat", "Drosophila", "Zebrafish"], index=0,
label_visibility='collapsed')

with col2:
all_variants = st.toggle('All variant')
all_variants = col2.toggle('All variant')

gr = col3.selectbox("Genome", ["Current", "Previous"], index=0, help="For human Current is GRCh38 and Previous is GRCh37 for example")

# Upstream/Downstream Promoter
st.markdown("🔹 :blue[**Step 1.3**] Regulatory region:")
Expand Down Expand Up @@ -226,7 +226,7 @@ def aio_page():
pbar.progress(i / len(gene_ids),
text=f'**:blue[Extract sequence... {gene_id}] ⚠️:red[PLEASE WAIT UNTIL END WITHOUT CHANGING ANYTHING]**')
result_promoter_output = NCBIdna(gene_id, prom_term, upstream, downstream,
species,
species, gr,
all_slice_forms=True if all_variants else False).find_sequences()
if not str(result_promoter_output).startswith('P'):
pbar.progress((i + 1) / len(gene_ids),
Expand Down
168 changes: 168 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import requests
import time

def get_gene_info(gene_id):
"""
Récupère les informations d'un gène via l'API NCBI Entrez en utilisant l'ID du gène.
"""
url = f"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi"
params = {
"db": "gene", # On cherche dans la base "gene"
"id": gene_id, # ID du gène obtenu via esearch
"retmode": "json" # Retourne le résultat en format JSON
}

response = requests.get(url, params=params)

# Vérifier si la requête est réussie
if response.status_code == 200:
print(response.text)
return response.json()
else:
print(f"Erreur : Impossible de récupérer les informations (status code: {response.status_code})")
return None


def extract_genomic_info(gene_info):
print(gene_info)
time.sleep(1)
"""
Extrait les NC_, chrstart et chrstop de la réponse JSON.
Ne garde que les accession versions qui partagent la même base avant le point.
"""
accession_dict = {}

# Extraction depuis la section locationhist
location_hist = gene_info.get('locationhist', [])
if len(location_hist) == 0:
location_hist = gene_info.get('genomicinfo', [])
for loc in location_hist:
nc_accver = loc.get('chraccver') # Extrait le NC_XXXXX.YY
chrstart = loc.get('chrstart')
chrstop = loc.get('chrstop')
print(nc_accver, chrstart, chrstop)

if nc_accver:
base_accession = nc_accver
if base_accession not in accession_dict:
accession_dict[base_accession] = (chrstart, chrstop)
else:
# Conserver la première occurrence des coordonnées
existing_start, existing_stop = accession_dict[base_accession]
accession_dict[base_accession] = (min(existing_start, chrstart), max(existing_stop, chrstop))

print(accession_dict) # Afficher le dictionnaire des NC_ sans les suffixes
return accession_dict


def fetch_nc_info(nc_accver):
time.sleep(1)
"""
Récupère les informations détaillées pour un NC_ via l'API NCBI.
"""
url = f"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi"
params = {
"db": "nuccore",
"id": nc_accver,
"retmode": "json"
}

response = requests.get(url, params=params)

if response.status_code == 200:
print(response.text)
return response.json()
else:
print(f"Erreur : Impossible de récupérer les informations pour {nc_accver} (status code: {response.status_code})")
return None


def main():
gene_id = input("Entrez l'ID du gène (par ex. 4843 pour NOS2) : ").strip()

# Étape 1 : Récupérer les informations du gène via son ID
gene_info = get_gene_info(gene_id)

if gene_info and 'result' in gene_info and gene_id in gene_info['result']:
gene_details = gene_info['result'][gene_id]
print(gene_details)
print(f"Informations pour le gène (ID: {gene_id}):")

# Étape 2 : Extraire les NC_, chrstart et chrstop
nc_dict = extract_genomic_info(gene_details)
print("\nNC_ Accession, chrstart, chrstop:")

# Affichage des NC_ et leurs informations de position
for base_accver, (chrstart, chrstop) in nc_dict.items():
print(f"{base_accver}: chrstart={chrstart}, chrstop={chrstop}")

# Filtrer pour garder uniquement les entrées qui commencent par "NC_"
nc_dict = {base_accver: (chrstart, chrstop) for base_accver, (chrstart, chrstop) in nc_dict.items() if
base_accver.startswith("NC_")}

# Si le dictionnaire n'est pas vide, récupérez la base avant le point du premier élément
if nc_dict:
first_base = next(iter(nc_dict)).split('.')[0] # Récupérer la base avant le point de la première clé

# Filtrer le dictionnaire pour ne garder que les éléments avec la même base
nc_dict = {base_accver: (chrstart, chrstop) for base_accver, (chrstart, chrstop) in nc_dict.items() if
base_accver.split('.')[0] == first_base}

# Votre code existant pour afficher le dictionnaire filtré
print("\nDictionnaire filtré :")
for base_accver, (chrstart, chrstop) in nc_dict.items():
print(f"{base_accver}: chrstart={chrstart}, chrstop={chrstop}")

# Trouver l'entrée avec le chiffre le plus grand et le plus petit après le point
max_version = -1
max_accver = None
max_coords = None # Pour stocker les coordonnées associées à la version maximale
min_version = float('inf') # Initialiser à l'infini pour trouver la plus petite version
min_accver = None
min_coords = None # Pour stocker les coordonnées associées à la version minimale

for base_accver in nc_dict.keys():
version = int(base_accver.split('.')[1]) # Extraire la version après le point

# Mise à jour pour la version maximale
if version > max_version:
max_version = version
max_accver = base_accver
max_coords = nc_dict[base_accver] # Stocker les coordonnées

# Mise à jour pour la version minimale
if version < min_version:
min_version = version
min_accver = base_accver
min_coords = nc_dict[base_accver] # Stocker les coordonnées

# Afficher les résultats
if max_accver:
print(f"\nL'accès avec la version la plus élevée est : {max_accver} avec la version {max_version}.")
print(f"Coordonnées : chrstart={max_coords[0]}, chrstop={max_coords[1]}")
else:
print("\nAucun accès trouvé.")

if min_accver:
print(f"L'accès avec la version la plus basse est : {min_accver} avec la version {min_version}.")
print(f"Coordonnées : chrstart={min_coords[0]}, chrstop={min_coords[1]}")
else:
print("Aucun accès trouvé.")

# Étape 3 : Faire une requête sur chaque accession version pour récupérer les infos détaillées
for base_accver in nc_dict.keys():
nc_info = fetch_nc_info(base_accver)
if nc_info and 'result' in nc_info and base_accver in nc_info['result']:
nc_details = nc_info['result'][base_accver]
print(f"\nDétails pour {base_accver} :")
print(f"Organisme : {nc_details.get('organism', {}).get('scientificname', 'Inconnu')}")
print(f"Description : {nc_details.get('title', 'Inconnu')}")
else:
print(f"Aucune information détaillée trouvée pour {base_accver}.")

else:
print(f"Aucune information détaillée trouvée pour l'ID {gene_id}.")


if __name__ == "__main__":
main()
113 changes: 106 additions & 7 deletions tfinder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,22 @@
from sklearn.preprocessing import StandardScaler
from tqdm import tqdm

from test import extract_genomic_info


class NCBIdna:
def __init__(self,
gene_id,
prom_term,
upstream,
downstream,
species=None, all_slice_forms=None):
species=None, gr="Current", all_slice_forms=None):
self.gene_id = gene_id
self.prom_term = prom_term if prom_term is not None else None
self.upstream = upstream if upstream is not None else None
self.downstream = downstream if downstream is not None else None
self.species = species if species is not None else None
self.gr = gr if gr is not None else "Current"
self.all_slice_forms = True if all_slice_forms is True else False

@staticmethod
Expand Down Expand Up @@ -136,7 +139,7 @@ def find_sequences(self):
return result_promoter

if not self.all_slice_forms:
gene_name, chraccver, chrstart, chrstop, species_API = NCBIdna.get_gene_info(entrez_id)
gene_name, chraccver, chrstart, chrstop, species_API = NCBIdna.get_gene_info(entrez_id, self.gr)
if gene_name == 'Bad ID':
result_promoter = f'Please verify ID of {self.gene_id}'
return result_promoter
Expand Down Expand Up @@ -210,9 +213,9 @@ def convert_gene_to_entrez_id(gene_name, species):

@staticmethod
# Get gene information
def get_gene_info(entrez_id):
def get_gene_info(entrez_id, gr):
# Request gene information
url = f"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=gene&id={entrez_id}&retmode=json&rettype=xml"
url = f"https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=gene&id={entrez_id}&retmode=json"
response = requests.get(url)

if response.status_code == 200:
Expand All @@ -221,15 +224,111 @@ def get_gene_info(entrez_id):
gene_info = response_data['result'][str(entrez_id)]
if 'chraccver' in str(gene_info):
gene_name = gene_info['name']
chraccver = gene_info['genomicinfo'][0]['chraccver']
chrstart = int(gene_info['genomicinfo'][0]['chrstart'])
chrstop = int(gene_info['genomicinfo'][0]['chrstop'])
if gr != "Current":
chraccver, chrstart, chrstop = NCBIdna.extract_genomic_info(entrez_id, response_data)
else:
chraccver = gene_info['genomicinfo'][0]['chraccver']
chrstart = int(gene_info['genomicinfo'][0]['chrstart'])
chrstop = int(gene_info['genomicinfo'][0]['chrstop'])
species_API = gene_info['organism']['scientificname']
print(chraccver, chrstart, chrstop)
return gene_name, chraccver, chrstart, chrstop, species_API
else:
gene_name = 'Bad ID'
return gene_name, None, None, None, None

@staticmethod
def extract_genomic_info(gene_id, gene_info):
# print(gene_id, gene_info)

if gene_info and 'result' in gene_info and gene_id in gene_info['result']:
accession_dict = {}
gene_details = gene_info['result'][gene_id]

time.sleep(1)

# Extraction depuis la section locationhist
location_hist = gene_details.get('locationhist', [])
if len(location_hist) == 0:
location_hist = gene_details.get('genomicinfo', [])
for loc in location_hist:
nc_accver = loc.get('chraccver') # Extrait le NC_XXXXX.YY
chrstart = loc.get('chrstart')
chrstop = loc.get('chrstop')

if nc_accver:
base_accession = nc_accver
if base_accession not in accession_dict:
accession_dict[base_accession] = (chrstart, chrstop)
else:
# Conserver la première occurrence des coordonnées
existing_start, existing_stop = accession_dict[base_accession]
accession_dict[base_accession] = (min(existing_start, chrstart), max(existing_stop, chrstop))


nc_dict = accession_dict

# Affichage des NC_ et leurs informations de position
# for base_accver, (chrstart, chrstop) in nc_dict.items():
# print(f"{base_accver}: chrstart={chrstart}, chrstop={chrstop}")

# Filtrer pour garder uniquement les entrées qui commencent par "NC_"
nc_dict = {base_accver: (chrstart, chrstop) for base_accver, (chrstart, chrstop) in nc_dict.items() if
base_accver.startswith("NC_")}

# Si le dictionnaire n'est pas vide, récupérez la base avant le point du premier élément
if nc_dict:
first_base = next(iter(nc_dict)).split('.')[0] # Récupérer la base avant le point de la première clé

# Filtrer le dictionnaire pour ne garder que les éléments avec la même base
nc_dict = {base_accver: (chrstart, chrstop) for base_accver, (chrstart, chrstop) in nc_dict.items() if
base_accver.split('.')[0] == first_base}

# Votre code existant pour afficher le dictionnaire filtré
# print("\nDictionnaire filtré :")
# for base_accver, (chrstart, chrstop) in nc_dict.items():
# print(f"{base_accver}: chrstart={chrstart}, chrstop={chrstop}")

# Trouver l'entrée avec le chiffre le plus grand et le plus petit après le point
max_version = -1
max_accver = None
max_coords = None # Pour stocker les coordonnées associées à la version maximale
min_version = float('inf') # Initialiser à l'infini pour trouver la plus petite version
min_accver = None
min_coords = None # Pour stocker les coordonnées associées à la version minimale

for base_accver in nc_dict.keys():
version = int(base_accver.split('.')[1]) # Extraire la version après le point

# Mise à jour pour la version maximale
if version > max_version:
max_version = version
max_accver = base_accver
max_coords = nc_dict[base_accver] # Stocker les coordonnées

# Mise à jour pour la version minimale
if version < min_version:
min_version = version
min_accver = base_accver
min_coords = nc_dict[base_accver] # Stocker les coordonnées

# Afficher les résultats
# if max_accver:
# print(f"\nL'accès avec la version la plus élevée est : {max_accver} avec la version {max_version}.")
# print(f"Coordonnées : chrstart={max_coords[0]}, chrstop={max_coords[1]}")
# else:
# print("\nAucun accès trouvé.")
#
# if min_accver:
# print(f"L'accès avec la version la plus basse est : {min_accver} avec la version {min_version}.")
# print(f"Coordonnées : chrstart={min_coords[0]}, chrstop={min_coords[1]}")
# else:
# print("Aucun accès trouvé.")

# print("Test", min_accver, min_coords[0], min_coords[1])
# print("test")
return min_accver, min_coords[0], min_coords[1]

@staticmethod
# Get gene information
def get_variant_info(entrez_id, variant):
Expand Down

0 comments on commit fa119b8

Please sign in to comment.