diff --git a/navigation/IMF.py b/navigation/IMF.py index d4a5ef2e..d54d0c45 100644 --- a/navigation/IMF.py +++ b/navigation/IMF.py @@ -93,14 +93,13 @@ def email(excel_file, csv_file, txt_output, email_receiver, body, jaspar): st.toast(f"Unknown error occurred: {e}") -def result_table_output(df): - source = df +def result_table_output(source): score_range = source['Rel Score'].astype(float) ystart = score_range.min() - 0.02 ystop = score_range.max() + 0.02 source['Gene_Region'] = source['Gene'] + " " + source['Species'] + " " + source['Region'] source['Beginning of sequences'] = source['Position'] - if 'Rel Position' in source: + if "Rel Position" in source: source['From TSS/gene end'] = source['Rel Position'] scale = alt.Scale(scheme='category10') color_scale = alt.Color("Gene_Region:N", scale=scale) @@ -108,10 +107,10 @@ def result_table_output(df): gene_region_selection = alt.selection_point(fields=['Gene_Region'], on='click', bind='legend') dropdown = alt.binding_select( - options=['Beginning of sequences', 'From TSS/gene end' if "Rel Position" in source else []], + options=['Beginning of sequences', 'From TSS/gene end'] if "Rel Position" in source else ['Beginning of sequences'], name='(X-axis) Position from: ') - xcol_param = alt.param(value='Beginning of sequences', bind=dropdown) + xcol_param = alt.param(value='Beginning of sequences', bind=dropdown, name="x_axis") chart = alt.Chart(source).mark_circle().encode( x=alt.X('x:Q').title('Position (bp)'), @@ -120,11 +119,12 @@ def result_table_output(df): color=alt.condition(gene_region_selection, color_scale, alt.value('lightgray')), tooltip=['Sequence', 'Position'] + (['Rel Position'] if "Rel Position" in source else []) + ( ['Ch Position'] if "Ch Position" in source else []) + ['Rel Score'] + ( - ['p-value'] if 'p-value' in source else []) + ['Gene', 'Species', 'Region'], + ['p-value'] if 'p-value' in source else []) + ['Gene', 'Species', 'Region'], opacity=alt.condition(gene_region_selection, alt.value(0.8), alt.value(0.2)) - ).transform_calculate(x=f'datum[{xcol_param.name}]').properties(width=600, - height=400).interactive().add_params( - gene_region_selection, xcol_param) + ).transform_calculate(x=f'datum[{xcol_param.name}]' + ).properties(width=600, height=400).interactive( + ).add_params(gene_region_selection, xcol_param) + st.altair_chart(chart, theme=None, use_container_width=True) @@ -491,64 +491,70 @@ def BSF_page(): with stqdm(total=iteration, desc='**:blue[Analyse sequence...] ⚠️:red[PLEASE WAIT UNTIL END WITHOUT CHANGING ANYTHING]**', mininterval=0.1) as progress_bar: - individual_motif_occurrences = IMO.individual_motif_finder(dna_sequences, threshold, log_odds_matrix, - progress_bar, - calc_pvalue, - tss_ge_distance, alldirection) - st.session_state['individual_motif_occurrences'] = individual_motif_occurrences + individual_motif_occurrences, message = IMO.individual_motif_finder(dna_sequences, threshold, + log_odds_matrix, + progress_bar, + calc_pvalue, + tss_ge_distance, alldirection) + if message is True: + st.session_state['individual_motif_occurrences'] = individual_motif_occurrences + st.session_state['message'] = message + elif message is False: + st.error(individual_motif_occurrences) st.divider() - if 'individual_motif_occurrences' in st.session_state: - if len(st.session_state['individual_motif_occurrences']) > 1: - current_date_time = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") - st.subheader(':blue[Results]') - - df = pd.DataFrame(st.session_state['individual_motif_occurrences'][1:], - columns=st.session_state['individual_motif_occurrences'][0]) - - df = df.sort_values(by='Rel Score', ascending=False) - - st.session_state['df'] = df - - st.markdown('**Table**') - tablecol1, tablecol2 = st.columns([0.75, 0.25]) - with tablecol1: - st.dataframe(df, hide_index=True) - csv_file = df.to_csv(index=False) - excel_file = io.BytesIO() - df.to_excel(excel_file, index=False, sheet_name='Sheet1') - excel_file.seek(0) - - with tablecol2: - st.success(f"Finding responsive elements done !") - - st.markdown("") - st.markdown('**Graph**', - help='Zoom +/- with the mouse wheel. Drag while pressing the mouse to move the graph. Selection of a group by clicking on a point of the graph (double click de-selection). Double-click on a point to reset the zoom and the moving of graph.') - - result_table_output(df) - - with tablecol2: - st.download_button("💾 Download table (.xlsx)", excel_file, - file_name=f'Results_TFinder_{current_date_time}.xlsx', - mime="application/vnd.ms-excel", key='download-excel') - st.download_button(label="💾 Download table (.csv)", data=csv_file, - file_name=f"Results_TFinder_{current_date_time}.csv", mime="text/csv") - - if st.session_state["LOCAL"] == "False": - email_receiver = st.text_input('Send results by email ✉', - value='', placeholder='Send results by email ✉', - label_visibility="collapsed") - if st.button("Send ✉"): - if jaspar == 'PWM': - if matrix_type == 'With PWM': - body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nPosition Weight Matrix:\n{matrix_str}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" - if matrix_type == 'With FASTA sequences': - body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nResponsive Elements:\n{individual_motif}\n\nPosition Weight Matrix:\n{matrix_text}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" - elif jaspar == 'JASPAR_ID': - body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nJASPAR_ID: {jaspar_id} | Transcription Factor name: {TF_name}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" - else: - body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nResponsive Elements:\n{IUPAC}\n\nPosition Weight Matrix:\n{matrix_text}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" - email(excel_file, csv_file, txt_output, email_receiver, body, jaspar) - else: - st.error(f"No consensus sequence found with the specified threshold") + try: + if 'individual_motif_occurrences' in st.session_state: + if len(st.session_state['individual_motif_occurrences']) > 0: + current_date_time = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + st.subheader(':blue[Results]') + + st.markdown('**Table**') + tablecol1, tablecol2 = st.columns([0.75, 0.25]) + with tablecol1: + st.dataframe(st.session_state['individual_motif_occurrences'], hide_index=True) + csv_file = st.session_state['individual_motif_occurrences'].to_csv(index=False) + excel_file = io.BytesIO() + st.session_state['individual_motif_occurrences'].to_excel(excel_file, index=False, + sheet_name='Sheet1') + excel_file.seek(0) + + with tablecol2: + st.success(f"Finding responsive elements done !") + + st.markdown("") + st.markdown('**Graph**', + help='Zoom +/- with the mouse wheel. Drag while pressing the mouse to move the graph. Selection of a group by clicking on a point of the graph (double click de-selection). Double-click on a point to reset the zoom and the moving of graph.') + + result_table_output(st.session_state['individual_motif_occurrences']) + + with tablecol2: + st.download_button("💾 Download table (.xlsx)", excel_file, + file_name=f'Results_TFinder_{current_date_time}.xlsx', + mime="application/vnd.ms-excel", key='download-excel') + st.download_button(label="💾 Download table (.csv)", data=csv_file, + file_name=f"Results_TFinder_{current_date_time}.csv", mime="text/csv") + + try: + if st.session_state["LOCAL"] == "False": + email_receiver = st.text_input('Send results by email ✉', + value='', placeholder='Send results by email ✉', + label_visibility="collapsed") + if st.button("Send ✉"): + if jaspar == 'PWM': + if matrix_type == 'With PWM': + body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nPosition Weight Matrix:\n{matrix_str}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" + if matrix_type == 'With FASTA sequences': + body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nResponsive Elements:\n{individual_motif}\n\nPosition Weight Matrix:\n{matrix_text}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" + elif jaspar == 'JASPAR_ID': + body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nJASPAR_ID: {jaspar_id} | Transcription Factor name: {TF_name}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" + else: + body = f"Hello 🧬\n\nResults obtained with TFinder.\n\nResponsive Elements:\n{IUPAC}\n\nPosition Weight Matrix:\n{matrix_text}\n\nThis email also includes the sequences used in FASTA format and an Excel table of results.\n\nFor all requests/information, please refer to the 'Contact' tab on the TFinder website. We would be happy to answer all your questions.\n\nBest regards\nTFinder Team 🔎🧬" + email(excel_file, csv_file, txt_output, email_receiver, body, jaspar) + except Exception: + print("You are in LOCAL") + else: + st.error(f"No consensus sequence found with the specified threshold") + except Exception as e: + print(e) + st.write(e) diff --git a/navigation/aio.py b/navigation/aio.py index d752a2b9..06864f5f 100644 --- a/navigation/aio.py +++ b/navigation/aio.py @@ -103,7 +103,8 @@ def result_table_output(source): ystop = score_range.max() + 0.02 source['Gene_Region'] = source['Gene'] + " " + source['Species'] + " " + source['Region'] source['Beginning of sequences'] = source['Position'] - source['From TSS/gene end'] = source['Rel Position'] + if "Rel Position" in source: + source['From TSS/gene end'] = source['Rel Position'] scale = alt.Scale(scheme='category10') color_scale = alt.Color("Gene_Region:N", scale=scale) @@ -113,7 +114,7 @@ def result_table_output(source): options=['Beginning of sequences', 'From TSS/gene end'] if "Rel Position" in source else ['Beginning of sequences'], name='(X-axis) Position from: ') - xcol_param = alt.param(value='Beginning of sequences', bind=dropdown) + xcol_param = alt.param(value='Beginning of sequences', bind=dropdown, name="x_axis") chart = alt.Chart(source).mark_circle().encode( x=alt.X('x:Q').title('Position (bp)'), diff --git a/navigation/regulatory_regions_extractor.py b/navigation/regulatory_regions_extractor.py index aa74da9d..4baacbe7 100644 --- a/navigation/regulatory_regions_extractor.py +++ b/navigation/regulatory_regions_extractor.py @@ -278,17 +278,16 @@ def prom_extractor_page(): pbar.progress((i + 1) / len(data_dff), text=f'**:blue[Extract sequence... {prom_term} **{gene_id}** from **{species}**] ⚠️:red[PLEASE WAIT UNTIL END WITHOUT CHANGING ANYTHING]**') - result_promoter_output = NCBIdna(gene_id, prom_term, upstream, - downstream).find_sequences() + result_promoter_output, message = NCBIdna(gene_id, prom_term, upstream, + downstream).find_sequences() - if not result_promoter_output.startswith('P'): - st.toast(f'{prom_term} **{gene_id}** from **{species}** extracted', + if message == "OK": + st.toast(f"{prom_term} **{gene_id}** from **{species}** extracted", icon='🧬') - result_promoter.append(result_promoter_output) - pass + result_promoter.append(result_promoter_output) else: - st.error(result_promoter_output) + st.error(message) continue else: @@ -301,19 +300,17 @@ def prom_extractor_page(): pbar.progress((i + 1) / len(data_dff), text=f'**:blue[Extract sequence... {prom_term} **{gene_id}** from **{species.capitalize()}**] ⚠️:red[PLEASE WAIT UNTIL END WITHOUT CHANGING ANYTHING]**') - result_promoter_output = NCBIdna(gene_id, prom_term, upstream, - downstream, - species).find_sequences() + result_promoter_output, message = NCBIdna(gene_id, prom_term, upstream, + downstream, + species).find_sequences() - if not result_promoter_output.startswith('P'): - st.toast( - f'{prom_term} **{gene_id}** from **{species.capitalize()}** extracted', - icon='🧬') - result_promoter.append(result_promoter_output) - pass + if message == "OK": + st.toast(f"{prom_term} **{gene_id}** from **{species}** extracted", + icon='🧬') + result_promoter.append(result_promoter_output) else: - st.error(result_promoter_output) + st.error(message) continue result_promoter_text = "\n".join(result_promoter) diff --git a/requirements.txt b/requirements.txt index a083496d..8a9bdb73 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,7 +21,7 @@ # Old requirements: biopython -altair~=5.4.1 +altair~=5.5.0 deprecation~=2.1.0 future hydralit_components @@ -32,7 +32,7 @@ pandas~=2.2.2 plotly requests~=2.32.3 stqdm~=0.0.5 -streamlit~=1.34.0 +streamlit~=1.40.1 streamlit_analytics streamlit-lottie tqdm~=4.66.4