def annotate_bad_chs(ctx, subject_id, chs, session_id, acquisition_id):
    """
    Annotate (remove) channels from analysis.

    Command Format:
    ez annotate_bad_chs --subject_id <subject_id> --chs <chs> --session_id <session_id>
    --acquisition_id <acquisition_id>

    """
    clear_screen()
    input_params = {
        "subject_id": subject_id,
        "chs": chs,
        "session_id": session_id,
        "acquisition_id": acquisition_id,
    }
    _check_annotatechannelfunc_params(input_params, "annotate_bad_chs")
    logger.info(
        f"ez annotate_bad_chs with subject_id: {subject_id}, chs: {chs}, "
        f"session_id: {session_id}, and acquisition_id: {acquisition_id}")
    bids_root = Path(_get_bidsroot_path())
    if acquisition_id is None:
        acquisition_ids = ["ecog", "seeg"]
        # _get_subject_acquisitions(bids_root, subject_id, session_id)
    else:
        acquisition_ids = [acquisition_id]

    for acquisition_id in acquisition_ids:
        bad_channels = channels_to_list(chs)
        add_bad_chs(bids_root, subject_id, session_id, acquisition_id,
                    bad_channels)
def view_bad_chs(ctx, subject_id, session_id, acquisition_id):
    """Print bad channels for a specific subject.

    Command Format:
    ez view_bad_chs --subject_id <subject_id> --session_id <session_id> --acquisition_id <acquisition_id>

    """
    clear_screen()
    input_params = {
        "subject_id": subject_id,
        "session_id": session_id,
        "acquisition_id": acquisition_id,
    }
    _check_annotatechannelfunc_params(input_params, "view_bad_chs")
    logger.info(
        f"ez view_bad_chs with subject_id: {subject_id}, "
        f"session_id: {session_id}, and acquisition_id: {acquisition_id}")
    bids_root = Path(_get_bidsroot_path())
    print_channel_status(bids_root, subject_id, session_id, acquisition_id)
Exemple #3
0
def metadata(ctx, toggle_options, display_cols, clear=True):
    """
    Display (filtered) metadata to the terminal.

    Metadata needs no arguments, unless you wish to see a subset of the entire patient set. When this is desired, use
    the toggle options. For instance, the below command will display only male subjects over age 20:

        ez metadata 'sex=M' 'age>20'

    """
    if clear:
        clear_screen()

    baseBids = BaseBids(_get_bidsroot_path())
    participants_path = baseBids.participants_tsv_fpath
    dateparse = lambda x: pd.datetime.strptime(x, "%m/%d/%y")
    participants_df = pd.read_csv(participants_path,
                                  sep="\t",
                                  parse_dates=True,
                                  date_parser=dateparse)

    # Print out the column names only
    if display_cols:
        click.echo(f"Available columns and types: \n {participants_df.dtypes}")
        return

    participants_df, cols, bools, keys = filter_metadata(
        participants_df, toggle_options)
    toggle_count = len(cols)

    sub_ids = participants_df["participant_id"]
    subject_ids = []
    for sub in sub_ids:
        sub_id = sub.split("-")[1]
        subject_ids.append(sub_id)

    # display meessage and logger output
    click.echo("Displaying Subjects: " + ", ".join(subject_ids))
    info_msg = f"{toggle_count} filters: {', '.join(''.join(x) for x in zip(cols, bools, keys))}"
    logger.info(f"ez metadata with {info_msg}")

    # define layout using pybids
    layout = BIDSLayout(_get_bidsroot_path())
    # subject_ids = layout.get_subjects()
    # faster using os.glob if too many subjects
    bids_root = Path(_get_bidsroot_path())

    # for each subject, display metadata
    # query for sessions, tasks and acquisitions before run_ids
    for ind, subject in enumerate(subject_ids):
        subj_bids_parser = BidsParser(bids_root, subject)
        scans_fpaths = subj_bids_parser.get_scans_fpaths()
        acquisition_ids = subj_bids_parser.get_acquisitions()

        # display summary for each acquisition
        for acquisition in acquisition_ids:
            # get the file paths to datasets
            _fpaths = [
                x.as_posix()
                for x in Path(bids_root / f"sub-{subject}").rglob("*.vhdr")
            ]
            _fpaths = [x for x in _fpaths if acquisition in x]

            # extract run
            run_ids = [_extract_run(x) for x in _fpaths]
            run_ids = ",".join(run_ids)

            # display message to user about subject, their metadata, acquisition and run_ids
            message_str = (
                f"Subject ID: {subject} - {', '.join([x + ': ' + str(participants_df.at[ind + 1, x]) for x in cols])} \n"
                f"{acquisition} run_ids: {run_ids} \n"
                f"Here is a table of each dataset:")
            click.echo(_linebreak(message_str))
            click.echo(message_str)

            # display summary for all datasets with this acquisition
            for scans_fpath in scans_fpaths:
                pd.options.display.max_colwidth = 90
                # read in scans.tsv for each subject
                scans_tsv = _from_tsv(scans_fpath)
                scans_df = pd.DataFrame.from_dict(scans_tsv)
                acquisition_scans = scans_df["filename"].str.contains(
                    acquisition)
                scans_df = scans_df[acquisition_scans]
                click.echo(scans_df)
Exemple #4
0
def pat_summary(ctx, subject_id, clear=True):
    """
    Display the summary data for a certain patient, or all patients.

    If subject_id not specified, or listed as all, will simply print metadata again.

    Command Format:
    ez pat-summary --subject_id <subject_id>

    """
    if clear:
        clear_screen()

    summary_params = {"subject_id": subject_id}
    _check_metadatafunc_params(summary_params, "pat-summary")
    logger.info(f"ez pat-summary with subject_id: {subject_id}")

    # faster using os.glob if too many subjects - compared pybids
    bids_root = Path(_get_bidsroot_path())

    # read in participants.tsv file and display to user
    bids_parser = BaseBids(bids_root)
    participants_tsv = _from_tsv(bids_parser.participants_tsv_fpath)
    participants_df = pd.DataFrame.from_dict(participants_tsv)

    # summarize all patients
    if subject_id == "all":
        click.echo("All Subjects Summary:")
        click.echo(participants_df)

    # summarize a specific patient
    if subject_id is not None and subject_id != "all":
        # set display options for the pandas dataframes
        pd.options.display.max_columns = None
        pd.options.display.max_rows = None
        pd.options.display.max_colwidth = 500

        # find the location of the scans file
        subj_bids_parser = BidsParser(bids_root, subject_id)
        scans_fpaths = subj_bids_parser.get_scans_fpaths()

        # for each set of scans files, print out summary data
        for i, scans_fpath in enumerate(scans_fpaths):
            # read in scans.tsv for each subject
            scans_tsv = _from_tsv(scans_fpath)
            # get the scans sidecar dictionaries for eeg and ieeg data
            eeg_dict, ieeg_dict = split_dict(scans_tsv)

            # load in files and their corresponding sidecar info
            # and add it to the summary dictionaries
            _populate_summary_dict(eeg_dict, eeg_dict["filename"], bids_root)
            _populate_summary_dict(ieeg_dict, ieeg_dict["filename"], bids_root)

        # summarize a specific subject
        participants_df = participants_df.loc[participants_df["participant_id"]
                                              == f"sub-{subject_id}"]
        click.echo(f"Subject {subject_id} Summary:")
        click.echo(participants_df)

        message_str = "\n\nSummary of Snapshots for %s" % subject_id
        click.echo(message_str)
        click.echo(_linebreak(message_str))

        ###################################################
        # Display the summary for either EEG,  or iEEG data.
        ###################################################
        if eeg_dict["filename"] == []:
            message_str = "No scalp EEG data to summarize."
            click.echo(message_str)
            click.echo(_linebreak(message_str))
        else:
            message_str = "EEG data summary."
            click.echo(message_str)
            click.echo(_linebreak(message_str))
            eeg_df = pd.DataFrame.from_dict(eeg_dict)
            click.echo(eeg_df)

        if ieeg_dict["filename"] == []:
            message_str = "No iEEG data to summarize."
            click.echo(message_str)
            click.echo(_linebreak(message_str))
        else:
            message_str = "iEEG data summary."
            click.echo(message_str)
            click.echo(_linebreak(message_str))
            ieeg_df = pd.DataFrame.from_dict(ieeg_dict)
            click.echo(ieeg_df)
Exemple #5
0
def run(
    ctx,
    subject_id,
    session_id,
    task_id,
    acquisition_id,
    run_id,
    reference,
    overwrite,
    colorblind,
    clear=True,
):
    """
    Run the fragility analysis on a given subject's EEG snapshot.

    subject_id, session_id, and run_id are required.

    Command Format:
    ez run --subject_id <subject_id> --session_id <session_id> --run_id <run_id>

    """
    # Prompt for arguments not passed
    if clear:
        clear_screen()

    # perform a dynamic check on parameters passed in
    # to give user an insightful feedback
    run_params = {
        "subject_id": subject_id,
        "session_id": session_id,
        "acquisition_id": acquisition_id,
        "run_id": run_id,
    }
    _check_runfunc_params(run_params, "run")
    logger.info(
        f"ez run with subject_id: {subject_id}, session_id: {session_id}, task_id: {task_id},"
        f"acquisition_id: {acquisition_id}, run_id: {run_id}, reference: {reference}, "
        f"overwrite: {overwrite}, colorblind: {colorblind}")

    # determine kind from acquisition.
    if acquisition_id in ["ecog", "seeg"]:
        kind = "ieeg"
    elif acquisition_id == "eeg":
        kind = "eeg"
    ext = "vhdr"  # files need to be in BV format

    # initialize bids_root and derivatives directories
    bids_root = _get_bidsroot_path()
    # output_path = _get_derivatives_path

    # find the bids run file
    bids_root, bids_fname, datapath = find_bids_run_file(
        subject_id=subject_id,
        session_id=session_id,
        task_id=task_id,
        acquisition_id=acquisition_id,
        run_id=run_id,
        kind=kind,
        datadir=bids_root,
        ext=ext,
    )

    # run fragility analysis
    click.echo(f"Analyzing fragility for the file {datapath}...")
    deriv_path = setup_fragility(
        subject_id,
        acquisition_id,
        run_id,
        kind,
        Path(bids_root),
        reference,
        overwrite=overwrite,
    )
    # click.echo(f"Analysis complete. Results saved in {deriv_path}...")
    logger.info("Analysis complete. Plotting.")
    click.echo("Analysis complete. Plotting.")
    plot_params = {
        "subject_id": subject_id,
        "session_id": session_id,
        "task_id": task_id,
        "acquisition_id": acquisition_id,
        "run_id": run_id,
        "kind": kind,
        "datadir": deriv_path,
    }

    ch_names = find_run_channels(**plot_params)

    # Make sure the channels is in a list
    if isinstance(ch_names, str):
        channels = ch_names.split(",")

    # Find the output .npz file
    output_fname = find_bids_file(
        deriv_path,
        subject_id,
        session_id,
        task_id,
        acquisition_id,
        run_id,
        kind,
        "output",
        True,
    )
    # Create the filename
    fig_name = output_fname.replace(".npz", "_heatmap.pdf")
    results = np.load(output_fname)
    pertmats = results["pertmats"]
    # TODO: remove once version is stable
    if pertmats.shape[1] == len(ch_names):
        pertmats = pertmats.T

    # Normalize the perturbation matrix
    fragmat = Normalize.compute_fragilitymetric(pertmats)

    # Plot the heatmap with save on
    plotter = PlotFragilityHeatmap(figure_dir=os.path.dirname(output_fname))
    plotter.plot_fragility_heatmap(fragmat,
                                   ch_names,
                                   colorblind=colorblind,
                                   output_fpath=fig_name,
                                   fontsize=16)
    logger.info("Plotting finished")
    click.echo("Plotting finished!")
Exemple #6
0
def plot(
    ctx,
    subject_id,
    session_id,
    task_id,
    acquisition_id,
    run_id,
    colorblind,
    reference,
    ext,
    cmap,
    clear=True,
):
    """
    Display the heatmap from the fragility analysis.


    .. code-block:: python
        ez plot --subject_id=<subject_id> --run_id=<run_id>
    """
    if clear:
        clear_screen()

    plot_params = {
        "subject_id": subject_id,
        "session_id": session_id,
        "acquisition_id": acquisition_id,
        "run_id": run_id,
        "colorblind": colorblind,
        "cmap": cmap,
    }
    _check_runfunc_params(plot_params, "plot")
    del plot_params["colorblind"]
    del plot_params["cmap"]

    logger.info(
        f"ez plot with subject_id: {subject_id}, session_id: {session_id}, task_id: {task_id},"
        f"acquisition_id: {acquisition_id}, run_id: {run_id}, colorblind: {colorblind}, "
        f"reference: {reference}, ext: {ext}, cmap: {cmap}")
    counted("replotting")

    if "ecog" in acquisition_id or "seeg" in acquisition_id:
        kind = "ieeg"
    elif "eeg" in acquisition_id:
        kind = "eeg"

    # output_path = _get_derivatives_path
    deriv_path = Path(_get_derivatives_path() / "fragility" / reference /
                      subject_id)

    plot_params["task_id"] = task_id
    plot_params["kind"] = kind
    plot_params["datadir"] = deriv_path
    ch_names = find_run_channels(**plot_params)

    # Make sure the channels is in a list
    if isinstance(ch_names, str):
        channels = ch_names.split(",")

    # Find the output .npz file
    output_fname = find_bids_file(
        deriv_path,
        subject_id,
        session_id,
        task_id,
        acquisition_id,
        run_id,
        kind,
        "output",
        True,
    )
    # Create the filename
    fig_name = output_fname.replace(".npz", f"_heatmap.{ext}")
    fig_name = os.path.join(os.path.dirname(fig_name), "figures",
                            os.path.basename(fig_name))
    results = np.load(output_fname)
    pertmats = results["pertmats"]
    if pertmats.shape[1] == len(ch_names):
        pertmats = pertmats.T

    # Normalize the perturbation matrix
    fragmat = Normalize.compute_fragilitymetric(pertmats)

    # Plot the heatmap with save on
    plotter = PlotFragilityHeatmap(
        figure_dir=os.path.join(os.path.dirname(output_fname), "figures"))
    plotter.plot_fragility_heatmap(
        fragmat,
        ch_names,
        colorblind=colorblind,
        cmap=cmap,
        output_fpath=fig_name,
        fontsize=16,
    )
    logger.info("Plotting completed")
    click.echo("Plotting finished!")