예제 #1
0
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?',
        )
    ]
예제 #2
0
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
예제 #3
0
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')
    ]
예제 #4
0
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]
예제 #5
0
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
예제 #6
0
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)])