diff --git a/pages/FLASHDeconvViewer.py b/pages/FLASHDeconvViewer.py index 10d7bc6..b88cc93 100644 --- a/pages/FLASHDeconvViewer.py +++ b/pages/FLASHDeconvViewer.py @@ -7,6 +7,7 @@ from src.components import PlotlyHeatmap, PlotlyLineplot, Plotly3Dplot, Tabulator, SequenceView, InternalFragmentMap, \ FlashViewerComponent, flash_viewer_grid_component from src.sequence import getFragmentDataFromSeq, getInternalFragmentDataFromSeq +from pages.FileUpload import initializeWorkspace, parseUploadedFiles, getUploadedFileDF DEFAULT_LAYOUT = [['ms1_deconv_heat_map'], ['scan_table', 'mass_table'], @@ -119,6 +120,17 @@ def select_experiment(): st.title("FLASHViewer") setSequenceViewInDefaultView() + # Parse previously uploaded files + input_file_types = ["deconv-mzMLs", "anno-mzMLs", "tsv-files"] + parsed_df_types = ["deconv_dfs", "anno_dfs", "parsed_tsv_files"] + initializeWorkspace(input_file_types, parsed_df_types) + st.session_state['progress_bar_space'] = st.container() + parseUploadedFiles() + + deconv_files = sorted(st.session_state["deconv_dfs"].keys()) + anno_files = sorted(st.session_state["anno_dfs"].keys()) + st.session_state["experiment-df"] = getUploadedFileDF(deconv_files, anno_files) + ### if no input file is given, show blank page if "experiment-df" not in st.session_state: st.error('Upload input files first!') diff --git a/pages/FileUpload.py b/pages/FileUpload.py index 5ba967b..c14e18c 100644 --- a/pages/FileUpload.py +++ b/pages/FileUpload.py @@ -165,7 +165,7 @@ def showUploadedFilesTable() -> bool: # for Workflow -def postprocessingAfterUpload_FD(uploaded_files: list) -> None: +def postprocessingAfterUpload_FD(uploaded_files: list = None) -> None: initializeWorkspace(input_file_types, parsed_df_types) #handleInputFiles(uploaded_files) parseUploadedFiles() diff --git a/src/Workflow.py b/src/Workflow.py index b9a27c3..abf67be 100644 --- a/src/Workflow.py +++ b/src/Workflow.py @@ -73,7 +73,7 @@ def configure(self) -> None: def execution(self) -> None: # Get input files try: - in_mzMLs = self.file_manager.get_files(self.params["mzML-files"]) + in_mzmls = self.file_manager.get_files(self.params["mzML-files"]) except ValueError: st.error('Please select at least one mzML file.') return @@ -103,10 +103,10 @@ def execution(self) -> None: threads = DEFAULT_THREADS # Process files in sequence - for in_mzML in in_mzMLs: + for in_mzml in in_mzmls: # Generate output folder - current_base = splitext(basename(in_mzML))[0] + current_base = splitext(basename(in_mzml))[0] current_time = time.strftime("%Y%m%d-%H%M%S") folder_path = join(base_path, 'FLASHTaggerOutput', '%s_%s'%(current_base, current_time)) if exists(folder_path): @@ -120,6 +120,19 @@ def execution(self) -> None: out_tag = join(base_path, self.tool_name, 'tags-tsv', f'{current_base}_{current_time}_tagged.tsv') out_protein = join(base_path, self.tool_name, 'proteins-tsv', f'{current_base}_{current_time}_protein.tsv') + # Additional outputs are directly written to download folder + out_tsv = join(folder_path, f'out.tsv') + out_spec1 = join(folder_path, f'spec1.tsv') + out_spec2 = join(folder_path, f'spec2.tsv') + out_spec3 = join(folder_path, f'spec3.tsv') + out_spec4 = join(folder_path, f'spec4.tsv') + out_quant = join(folder_path, f'quant.tsv') + out_msalign1 = join(folder_path, f'toppic_ms1.msalign') + out_msalign2 = join(folder_path, f'toppic_ms2.msalign') + out_feature1 = join(folder_path, f'toppic_ms1.feature') + out_feature2 = join(folder_path, f'toppic_ms2.feature') + out_prsm = join(folder_path, f'prsms.tsv') + # Check if a decoy database needs to be generated tagger_params = self.executor.parameter_manager.get_parameters_from_json()['FLASHTnT'] if ((tagger_params.get('tnt:prsm_fdr', 1) < 1) or (tagger_params.get('tnt:pro_fdr', 1) < 1)): @@ -150,10 +163,19 @@ def execution(self) -> None: self.executor.run_topp( 'FLASHDeconv', input_output={ - 'in' : [in_mzML], - 'out' : ['_.tsv'], - 'out_annotated_mzml' : [out_anno], - 'out_mzml' : [out_deconv], + 'in' : [in_mzml], + 'out' : [out_tsv], + 'out_spec1' : [out_spec1], + 'out_spec2' : [out_spec2], + 'out_spec3' : [out_spec3], + 'out_spec4' : [out_spec4], + 'out_mzml' : [out_deconv], + 'out_quant' : [out_quant], + 'out_annotated_mzml' : [out_anno], + 'out_msalign1' : [out_msalign1], + 'out_msalign2' : [out_msalign2], + 'out_feature1' : [out_feature1], + 'out_feature2' : [out_feature2], }, params_manual = { 'threads' : threads @@ -168,7 +190,7 @@ def execution(self) -> None: 'fasta' : [out_db], 'out_tag' : [out_tag], 'out_pro' : [out_protein], - 'out_prsm' : ['_.tsv'] + 'out_prsm' : [out_prsm] }, params_manual = { 'threads' : threads @@ -226,7 +248,7 @@ def configure(self) -> None: def execution(self) -> None: # Get input files try: - in_mzMLs = self.file_manager.get_files(self.params["mzML-files"]) + in_mzmls = self.file_manager.get_files(self.params["mzML-files"]) except ValueError: st.error('Please select at least one mzML file.') return @@ -247,10 +269,10 @@ def execution(self) -> None: threads = DEFAULT_THREADS # Process files in sequence - for in_mzML in in_mzMLs: + for in_mzml in in_mzmls: # Generate output folder - current_base = splitext(basename(in_mzML))[0] + current_base = splitext(basename(in_mzml))[0] current_time = time.strftime("%Y%m%d-%H%M%S") folder_path = join(base_path, 'FLASHDeconvOutput', '%s_%s'%(current_base, current_time)) if exists(folder_path): @@ -259,8 +281,8 @@ def execution(self) -> None: # Define output paths for viewer out_tsv = join(base_path, self.tool_name, 'tsv-files', f'{current_base}_{current_time}.tsv') - out_mzml = join(base_path, self.tool_name, 'deconv-mzMLs', f'{current_base}_{current_time}_deconv.mzML') - out_annotated_mzml = join(base_path, self.tool_name, 'anno-mzMLs', f'{current_base}_{current_time}_annotated.mzML') + out_deconv = join(base_path, self.tool_name, 'deconv-mzMLs', f'{current_base}_{current_time}_deconv.mzML') + out_anno = join(base_path, self.tool_name, 'anno-mzMLs', f'{current_base}_{current_time}_annotated.mzML') # Additional outputs are directly written to download folder out_spec1 = join(folder_path, f'spec1.tsv') @@ -277,15 +299,15 @@ def execution(self) -> None: self.executor.run_topp( 'FLASHDeconv', input_output={ - 'in' : [in_mzML], + 'in' : [in_mzml], 'out' : [out_tsv], 'out_spec1' : [out_spec1], 'out_spec2' : [out_spec2], 'out_spec3' : [out_spec3], 'out_spec4' : [out_spec4], - 'out_mzml' : [out_mzml], + 'out_mzml' : [out_deconv], 'out_quant' : [out_quant], - 'out_annotated_mzml' : [out_annotated_mzml], + 'out_annotated_mzml' : [out_anno], 'out_msalign1' : [out_msalign1], 'out_msalign2' : [out_msalign2], 'out_feature1' : [out_feature1], @@ -297,8 +319,8 @@ def execution(self) -> None: ) # Copy generated files to output - copyfile(out_mzml, join(folder_path, f'out_deconv.mzML')) - copyfile(out_annotated_mzml, join(folder_path, f'anno_annotated.mzML')) + copyfile(out_deconv, join(folder_path, f'out_deconv.mzML')) + copyfile(out_anno, join(folder_path, f'anno_annotated.mzML')) copyfile(out_tsv, join(folder_path, f'out.tsv')) # Store settings diff --git a/src/workflow/ParameterManager.py b/src/workflow/ParameterManager.py index 942bfd0..9b25ef7 100644 --- a/src/workflow/ParameterManager.py +++ b/src/workflow/ParameterManager.py @@ -1,4 +1,5 @@ import pyopenms as poms +import os import json import shutil import streamlit as st @@ -50,12 +51,19 @@ def save_parameters(self) -> None: # for each TOPP tool, open the ini file for tool in current_topp_tools: json_params[tool] = {} + if os.path.isfile(self.params_file): + with open(self.params_file, "r") as f: + file_params = json.load(f) + if tool in file_params: + json_params[tool] = file_params[tool] # load the param object param = poms.Param() poms.ParamXMLFile().load(str(Path(self.ini_dir, f"{tool}.ini")), param) # get all session state param keys and values for this tool + print('xxxxx') for key, value in st.session_state.items(): if key.startswith(f"{self.topp_param_prefix}{tool}:1:"): + print(key, value) # get ini_key ini_key = key.replace(self.topp_param_prefix, "").encode() # get ini (default) value by ini_key @@ -75,7 +83,7 @@ def save_parameters(self) -> None: cast_type = str value = [cast_type(v) for v in value.split("\n")] # check if value is different from default - if ini_value != value: + if (ini_value != value) or (json_params[tool].get(key.split(":1:")[1], value) != value): # store non-default value json_params[tool][key.split(":1:")[1]] = value # Save to json file diff --git a/src/workflow/StreamlitUI.py b/src/workflow/StreamlitUI.py index 9af76a3..90a32f4 100644 --- a/src/workflow/StreamlitUI.py +++ b/src/workflow/StreamlitUI.py @@ -825,7 +825,12 @@ def file_upload_section(self, custom_upload_function) -> None: self.zip_and_download_files(Path(self.workflow_dir, "input-files")) def parameter_section(self, custom_paramter_function) -> None: - st.toggle("Show advanced parameters", value=False, key="advanced") + if "advanced" not in st.session_state: + st.session_state["advanced"] = False + def toggle_advanced(): + self.parameter_manager.save_parameters() + st.session_state["advanced"] = not st.session_state["advanced"] + st.toggle("Show advanced parameters", value=st.session_state["advanced"], on_change=toggle_advanced) form = st.form( key=f"{self.workflow_dir.stem}-input-form",