def render(assay): with st.sidebar.beta_expander('Customizations'): interface.info('Rename the labels.<br>Merge by giving the same name.') lab_map = {} keep_labs = [] pal = assay.get_palette() lab_set = np.unique(assay.get_labels()) for lab in lab_set: col1, col2, col3 = st.beta_columns([1, 0.1, 0.07]) with col1: new_name = st.text_input(f'Give a new name to {lab}', lab) with col2: st.markdown(f"<p style='margin-bottom:34px'></p>", unsafe_allow_html=True) pal[lab] = st.color_picker('', pal[lab], key=f'colorpicker-{lab}') with col3: st.markdown(f"<p style='margin-bottom:42px'></p>", unsafe_allow_html=True) keep = st.checkbox('', True, key=f'keep-cells-{lab}-{lab_set}') if keep: keep_labs.append(lab) if new_name != lab: lab_map[lab] = new_name pal[new_name] = pal[lab] del pal[lab] if len(keep_labs) == 0: interface.error('At least one label must be selected.') return lab_map, pal, keep_labs
def render(sample, assay_names): with st.sidebar.beta_expander('Preprocessing'): info = st.empty() assay_name = {DNA_ASSAY: 'DNA', PROTEIN_ASSAY: 'Protein'} assay_type = st.selectbox('Assay', assay_names, format_func=lambda x: assay_name[x]) if assay_type == DNA_ASSAY: dp, gq, af, std = sample.dna.metadata[DFT.PREPROCESS_ARGS] dp = st.slider('Minimum read depth (DP)', min_value=0, max_value=100, value=int(dp)) gq = st.slider('Minimum genotype quality (GQ)', min_value=0, max_value=100, value=int(gq)) af = st.slider('Minimum allele frequency (VAF)', min_value=0, max_value=100, value=int(af)) std = st.slider('Minimum standard deviation of AF', min_value=0, max_value=100, value=int(std)) ids = sample.dna.metadata[DFT.ALL_IDS] ids = list(ids[ids.argsort()]) drop_vars = st.multiselect( 'Variants to discard', ids, default=sample.dna.metadata[DFT.DROP_IDS]) keep_vars = st.multiselect( 'Variants to keep', ids, default=sample.dna.metadata[DFT.KEEP_IDS]) if len(keep_vars) != 0 and len(drop_vars) != 0: interface.error( 'Cannot keep and drop variants both. Choose only one of the options' ) assay_args = [drop_vars, keep_vars, dp, gq, af, std] elif assay_type == PROTEIN_ASSAY: ids = sample.protein.metadata[DFT.ALL_IDS] ids = list(ids[ids.argsort()]) drop_abs = st.multiselect( 'Antibodies to discard', ids, default=sample.protein.metadata[DFT.DROP_IDS]) assay_args = [drop_abs] interface.info(f'{assay_type} currently loaded', info) clicked = st.button('Process') return assay_type, clicked, assay_args
def run(sample, name, should_save): for assay, og_assay in zip( [sample.dna, sample.protein], [sample._original_dna, sample._original_protein]): if assay is not None: for key in assay.metadata: og_assay.add_metadata(key, assay.metadata[key]) for key in assay.row_attrs: og_assay.add_row_attr(key, assay.row_attrs[key]) if should_save: interface.status('Saving h5 file.') if name == '': interface.error('Please provide a name to save by.') elif name[-3:] == '.h5': name = name[:-3] try: os.remove(DFT.ROOT / f'h5/analyzed/{name}.h5') except FileNotFoundError: pass samp = sample[:] set_defaults(samp) mio.save(samp, DFT.ROOT / f'h5/analyzed/{name}.h5') interface.status('Saved.') interface.rerun()
def _get_file_from_name(typed_name): if typed_name[-3:] == '.h5': typed_name = typed_name[:-3] if typed_name + '.h5' in analyzed_files: typed_name = DFT.ROOT / f'h5/analyzed/{typed_name}.h5' elif typed_name + '.h5' in downloaded_files: typed_name = DFT.ROOT / f'h5/downloads/{typed_name}.h5' else: interface.error( f'Cannot find "{typed_name}" in the available files') return typed_name
def run(): file, load_raw, apply_filter, kind, should_save, save_name, info = render() if kind == DFT.S3: file = download(file) if file is None: interface.error( 'Please use the options available in the sidebar to load a sample.<br>' 'New h5 files should be copied to the <i>/h5/downloads/</i> folder where the app is stored.' ) sample = load(file, load_raw, apply_filter) interface.info(f'Currently loaded {sample.name}', info) return sample, should_save, save_name
def download(link): interface.status('Downloading from s3.') s3 = boto3.client('s3') link = link.replace('s3://', '') link = link.split('/') bucket, file = link[0], '/'.join(link[1:]) filename = file.split('/')[-1] filename = DFT.ROOT / f'h5/downloads/{filename}' filename = str(filename) try: s3.download_file(bucket, file, filename) except Exception as e: interface.status('Done.') interface.error(f'Could not find the given h5 file. {e}') return filename
def run(sample, name): interface.status('Saving h5 file.') if name == '': interface.error('Please provide a name to save by.') elif name[-3:] == '.h5': name = name[:-3] try: os.remove(DFT.ROOT / f'h5/analyzed/{name}.h5') except FileNotFoundError: pass samp = sample[:] set_defaults(samp) mio.save(samp, DFT.ROOT / f'h5/analyzed/{name}.h5') interface.status('Saved.') interface.rerun()
def preprocess_dna(sample, clicked, drop_vars, keep_vars, dp, gq, af, std): args_changed = ( list(sample.dna.metadata[DFT.PREPROCESS_ARGS]) != [dp, gq, af, std] or set(sample.dna.metadata[DFT.DROP_IDS]) != set(drop_vars) or set(sample.dna.metadata[DFT.KEEP_IDS]) != set(keep_vars)) if sample.dna.metadata[DFT.INITIALIZE] or (args_changed and clicked): interface.status('Processing DNA assay.') sample.reset('dna') if len(keep_vars) == 0: dna_vars = sample.dna.filter_variants(min_dp=dp, min_gq=gq, min_vaf=af, min_std=std) sample.dna.add_metadata(DFT.ALL_IDS, sample.dna.ids()) if len(drop_vars) > 0: sample.dna = sample.dna.drop(drop_vars) else: dna_vars = keep_vars if len(dna_vars) == 0: interface.status('Done.') interface.error( 'No variants found. Adjust the filters and process again. Make sure "Filter" is deselected in the Files section.' ) sample.dna = sample.dna[:, dna_vars] sample.dna.add_metadata(DFT.PREPROCESS_ARGS, [dp, gq, af, std]) sample.dna.add_metadata(DFT.DROP_IDS, drop_vars) sample.dna.add_metadata(DFT.KEEP_IDS, keep_vars) if not sample.dna.metadata[DFT.INITIALIZE]: sample.dna.add_metadata(DFT.PREPPED, False) sample.dna.add_metadata(DFT.CLUSTERED, False)
def render(): with st.sidebar.beta_expander('Files', expanded=True): interface.info('Load or download a file from s3') info = st.empty() col1, col2 = st.beta_columns([0.3, 1]) with col1: st.markdown(f"<sup><p style='margin-bottom:22px'></p></sup>", unsafe_allow_html=True) load_raw = st.checkbox('Raw') with col2: st.markdown(f"<sup><p style='margin-bottom:22px'></p></sup>", unsafe_allow_html=True) apply_filter = st.checkbox('Filter', False) link = st.text_input('Load from s3', value='') if not os.path.exists(DFT.ROOT / 'h5'): os.mkdir(DFT.ROOT / 'h5') if not os.path.exists(DFT.ROOT / 'h5/downloads'): os.mkdir(DFT.ROOT / 'h5/downloads/') if not os.path.exists(DFT.ROOT / 'h5/analyzed'): os.mkdir(DFT.ROOT / 'h5/analyzed/') downloaded_files = np.array(os.listdir(DFT.ROOT / 'h5/downloads/')) analyzed_files = np.array(os.listdir(DFT.ROOT / 'h5/analyzed/')) filenames = list(analyzed_files[analyzed_files.argsort()]) + list( downloaded_files[downloaded_files.argsort()]) filenames = [None] + [f for f in filenames if f[-3:] == '.h5'] def shownames(name): nonlocal analyzed_files if name in analyzed_files: return '* ' + name else: return name kind = None selector = st.empty() file = selector.selectbox('Load existing file', filenames, format_func=shownames) if link != '': kind = DFT.S3 file = link elif file is not None: if file in downloaded_files: file = DFT.ROOT / f'h5/downloads/{file}' else: file = DFT.ROOT / f'h5/analyzed/{file}' kind = DFT.LOCAL typed_name = st.text_input('Save, download or delete the given file', value='') def _get_file_from_name(typed_name): if typed_name[-3:] == '.h5': typed_name = typed_name[:-3] if typed_name + '.h5' in analyzed_files: typed_name = DFT.ROOT / f'h5/analyzed/{typed_name}.h5' elif typed_name + '.h5' in downloaded_files: typed_name = DFT.ROOT / f'h5/downloads/{typed_name}.h5' else: interface.error( f'Cannot find "{typed_name}" in the available files') return typed_name col1, col2, col3 = st.beta_columns([0.25, 0.4, 0.4]) with col1: st.markdown('') should_save = st.button('Save') with col2: st.markdown('') if st.button('Download'): download_path = _get_file_from_name(typed_name) interface.download(download_path) with col3: st.markdown('') if st.button('Delete'): typed_name = _get_file_from_name(typed_name) if file is not None and typed_name == file: interface.error( 'Cannot delete the file used in the current analysis.') os.remove(typed_name) interface.rerun() return file, load_raw, apply_filter, kind, should_save, typed_name, info