def fill_sample_report(page_n, sample_store): page_n = int(page_n) sample_ids = list(map(lambda x: x["_id"], sample_store)) if len(sample_ids) == 0: return None data_table = import_data.filter_all(sample_ids=sample_ids, pagination={ "page_size": SAMPLE_PAGESIZE, "current_page": page_n }) max_page = len(sample_store) // SAMPLE_PAGESIZE # We need to have fake radio buttons with the same ids to account for times # when not all SAMPLE_PAGESIZE samples are shown and are not taking the ids required by the callback html_fake_radio_buttons = html.Div([ dcc.RadioItems(options=[{ 'label': '', 'value': 'nosample' }], value='noaction', id="sample-radio-{}".format(n_sample)) for n_sample in range(len(data_table), SAMPLE_PAGESIZE) ], style={"display": "none"}) return [ html.H4("Page {} of {}".format(page_n + 1, max_page + 1)), html.Div(children_sample_list_report(data_table)), html_fake_radio_buttons, admin.html_qc_expert_form(), html.H4("Page {} of {}".format(page_n + 1, max_page + 1)), dcc.ConfirmDialog( id='qc-confirm', message='Are you sure you want to send sample feedback?', ) ]
def update_selected_samples(n_clicks, param_store, collection_name, run_names, species_list, species_source, group_list, qc_list, sample_names, prev_sample_store, date_seq_start, date_seq_end): date_range = [date_seq_start, date_seq_end] for i in range(2): if date_range[i] is not None: date_range[i] = datetime.datetime.strptime( re.split('T| ', date_range[i])[0], '%Y-%m-%d') if sample_names is not None and sample_names != "": sample_names = sample_names.split("\n") else: sample_names = param_store.get("sample_names", []) if not run_names: run_names = param_store.get("run", []) if not group_list: group_list = param_store.get("group", []) if not species_list: species_list = param_store.get("species", []) if not qc_list: qc_list = param_store.get("qc", []) if not date_range[0]: date_range[0] = param_store.get("date_seq_start", None) if not date_range[1]: date_range[1] = param_store.get("date_seq_end", None) #override if selected collection if collection_name is not None: run_names = [collection_name] if (date_range[0] is None and date_range[1] is None): date_range = None if (n_clicks == 0 and sample_names == [] and run_names == [] and group_list == [] and species_list == [] and qc_list == [] and date_range is None): samples = prev_sample_store else: samples = import_data.filter_all(species=species_list, species_source=species_source, group=group_list, qc_list=qc_list, run_names=run_names, sample_names=sample_names, date_range=date_range, projection={"name": 1}) if "_id" in samples: samples["_id"] = samples["_id"].astype(str) samples = samples.to_dict('records') # if deleted_samples: # samples = [s for s in samples if s["_id"] not in deleted_samples] return samples
def generate_download_button(download_button, run_names, species_list, species_source, group_list, qc_list, sample_names): if download_button == 0: return None else: if sample_names is not None and sample_names != "": sample_names = sample_names.split("\n") tests_df = import_data.filter_all(species=species_list, species_source=species_source, group=group_list, qc_list=qc_list, run_names=run_names, sample_names=sample_names, pagination=None) # return samples.to_dict() if not len(tests_df): return None tests_df = generate_table(tests_df) rename_dict = {item["id"]: item["name"] for item in global_vars.COLUMNS} renamed = tests_df.rename(rename_dict, axis='columns') missing_columns = [ a for a in list(rename_dict.values()) if not a in list(renamed.columns) ] # add missing columns for column in missing_columns: renamed[column] = np.nan # reorder columns renamed = renamed[list(rename_dict.values())] csv_string_eur = renamed.to_csv(index=False, encoding="utf-8", sep=";", decimal=",") tsv_string_us = renamed.to_csv(index=False, encoding="utf-8", sep="\t") full_csv_string_eur = 'data:text/csv;charset=utf-8,' + \ urlparse.quote(csv_string_eur) full_tsv_string_us = 'data:text/tab-separated-values;charset=utf-8,' + \ urlparse.quote(tsv_string_us) return [ html.A("(tsv, US format)", href=full_tsv_string_us, download='report.tsv'), " - ", html.A("(csv, EUR Excel format)", href=full_csv_string_eur, download='report.csv') ]
def update_filter_table(_, sample_store): if len(sample_store) == 0: return ["0", [{}], False] sample_ids = list(map(lambda x: x["_id"], sample_store)) samples = import_data.filter_all(sample_ids=sample_ids) samples = generate_table(samples) if len(sample_store) > 500: virtualization = True else: virtualization = False return [len(sample_store), samples.to_dict("rows"), virtualization]
def pipeline_report_data(sample_data): if len(sample_data) == 0: return [], [{ "id": "Priority", "name": "Priority" }, { "id": "Sample", "name": "Sample" }, { "id": "QC status", "name": "QC status" }], [], [], [] status_dict = { "Success": "OK", "Running": "Running", "initialized": "init.", "Failure": "Fail", "Requirements not met": "Req.", "queued to run": "queue", } samples = import_data.filter_all( sample_ids=[s["_id"] for s in sample_data], projection={ "properties.stamper": 1, 'name': 1, 'sample_sheet.priority': 1, "components": 1 }) s_c_components = [] for _id, sample in samples.iterrows(): try: for component in sample["components"]: s_c_components.append(component["name"]) except TypeError: pass components_list = [ comp for comp in components_order if comp in s_c_components ] rows = [] columns = [{ "name": "Priority", "id": "priority" }, { "name": "Sample", "id": "sample" }, { "name": "QC status", "id": "qc_val" }] rerun_form_components = [] for comp in components_list: columns.append({"name": comp, "id": comp}) # HERE rerun_form_components.append({"label": comp, "value": comp}) # Conditional data colors style_data_conditional = [{ "if": { "column_id": "qc_val", "filter_query": '{qc_val} contains "CF"' }, "backgroundColor": "#ea6153" }, { "if": { "column_id": "qc_val", "filter_query": '{qc_val} contains "CF(LF)"' }, "backgroundColor": "#ea6153" }, { "if": { "column_id": "qc_val", "filter_query": '{qc_val} contains "OK"' }, "backgroundColor": "#27ae60" }, { "if": { "column_id": "qc_val", "filter_query": '{qc_val} eq "SL"' }, "backgroundColor": "#f1c40f" }] for col in components_list: style_data_conditional.append({ "if": { "column_id": col, "filter_query": '{{{}}} eq "Fail"'.format(col) }, "backgroundColor": "#ea6153" }) style_data_conditional.append({ "if": { "column_id": col, "filter_query": '{{{}}} eq "OK"'.format(col) }, "backgroundColor": "#3498db" }) style_data_conditional.append({ "if": { "column_id": col, "filter_query": '{{{}}} eq "Running"'.format(col) }, "backgroundColor": "#f1c40f" }) style_data_conditional.append({ "if": { "column_id": col, "filter_query": '{{{}}} eq "Req."'.format(col) }, "backgroundColor": "#d3d3d3", "color": "#525252" }) rerun_form_samples = [] for _id, sample in samples.iterrows(): name = sample["name"] row = {} if name == "Undetermined": continue # ignore this row row["sample"] = name row["_id"] = str(sample["_id"]) rerun_form_samples.append({ "label": name, "value": "{}:{}".format(_id, name) }) priority = str(sample.get("sample_sheet.priority", "")).lower() # prio_display = " " Emoji not supported # if priority == "high": # prio_display = "High" # else: # prio_display = "Low" row["priority"] = priority qc_val = sample.get("properties.stamper.summary.stamp.value", "N/A") if pd.isna(qc_val): qc_val = "N/A" expert_check = False expert_stamp = sample.get('stamps.supplying_lab_check.value') if expert_stamp is not None and not pd.isna(expert_stamp): qc_val = sample.get('stamps.supplying_lab_check.value') expert_check = True statusname = "" if qc_val == "supplying lab": qc_val = "SL" statusname = "status-1" elif qc_val == "N/A": statusname = "status--2" elif (qc_val == "core facility"): statusname = "status--1" qc_val = "CF" elif qc_val == "OK": statusname = "status-2" qc_val = "OK" if expert_check: try: qc_val += "*" except: print(sample) row["qc_val"] = qc_val try: for component in sample["components"]: row[component["name"]] = status_dict[component["status"]] row["{}_id".format(component["name"])] = str(component["_id"]) except TypeError: pass except KeyError: print(sample["_id"]) print(sample["components"]) rows.append(row) def sort_name(e): return e["sample"] rows.sort(key=sort_name) return rows, columns, style_data_conditional, rerun_form_components, rerun_form_samples
def link_to_files(sample_store): """Generates a script string """ sample_ids = [str(s["_id"]) for s in sample_store] samples = import_data.filter_all(sample_ids=sample_ids, projection={"name": 1, "properties.datafiles.summary.paired_reads": 1}) samples["_id"] = samples["_id"].astype(str) samples = samples.set_index("_id") # Access samples by their id assemblies = import_data.get_assemblies_paths(sample_ids) reads_script = "mkdir samples\ncd samples\n" assemblies_script = "mkdir assemblies\ncd assemblies\n" reads_errors = [] assemblies_errors = [] samples_total = set() for _id, sample in samples.iterrows(): try: reads_script += "#{}\nln -s {} .\nln -s {} .\n".format( sample["name"], sample["properties.datafiles.summary.paired_reads"][0], sample["properties.datafiles.summary.paired_reads"][1]) samples_total.add((sample["name"], sample.name)) except (KeyError, TypeError): reads_errors.append("Missing data for sample: {} - {}. In database:\n{}".format( sample.get("name", "None"), sample.name, sample.get( "properties.datafiles.summary.paired_reads", "No data") )) if len(reads_errors): reads_html = [ html.Div([ html.Div([ html.H6("Read files", className="m-0 font-weight-bold text-primary"), ], className="card-header py-3"), html.Div([ "A few errors occurred locating the read paths. If you need more info, " + "please contact an admin.", html.Pre("\n".join(reads_errors), className="error-pre"), html.Pre(reads_script, className="folder-pre") ], className="card-body") ], className="card shadow") ] else: reads_html = [ html.Div([ html.Div([ html.H6("Read files", className="m-0 font-weight-bold text-primary"), ], className="card-header py-3"), html.Div([ html.Pre(reads_script, className="folder-pre") ], className="card-body") ], className="card shadow") ] samples_assemblies = set() for assembly in assemblies: sample = samples.loc[str(assembly["sample"]["_id"]), :] assemblies_script += "#{}\nln -s {} {}\n".format( sample["name"], assembly["path"] + "/contigs.fasta", sample["name"] + "_contigs.fasta") samples_assemblies.add((sample["name"], sample.name)) assemblies_missing = samples_total - samples_assemblies for sample in assemblies_missing: assemblies_errors.append("Missing data for sample: {} - {}.".format(sample[0], sample[1])) if len(assemblies_errors): assemblies_html = [ html.Div([ html.Div([ html.H6("Assemblies", className="m-0 font-weight-bold text-primary"), ], className="card-header py-3"), html.Div([ "A few errors occurred locating the contigs. If you need more info, " + "please contact an admin.", html.Pre("\n".join(assemblies_errors), className="error-pre"), html.Pre(assemblies_script, className="folder-pre") ], className="card-body") ], className="card mb-4 shadow") ] else: assemblies_html = [ html.Div([ html.Div([ html.H6("Assemblies", className="m-0 font-weight-bold text-primary"), ], className="card-header py-3"), html.Div([ html.Pre(assemblies_script, className="folder-pre") ], className="card-body") ], className="card mb-4 shadow") ] return html.Div([html.Div(assemblies_html), html.Div(reads_html)])