示例#1
0
def qc(t1files, wmfiles, asegfiles, whitefiles, pialfiles, annotfiles,
       actor_ang=[0., 0., 0.], output_directory=None,
       fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Compute some quality check plots on the converted FrreSurfer
    outputs.

    The subjecy id in the input files must appear in the -3 position:
        xxx/subject_id/convert/t1.nii.gz

    Steps:

    * t1-images overlays
    * 3d surface segmentation snaps
    * t1-surfaces overlays

    actor_ang: float (optional, default 0)
        the actor rotation in the z direction.

    <unit>
        <input name="t1files" type="List_File" description="The
            t1 subject files."/>
        <input name="wmfiles" type="List_File" description="The
            white matter subject files."/>
        <input name="asegfiles" type="List_File" description="The
            subcortical segmentation subject files."/>
        <input name="output_directory" type="Directory" description="The
            conversion destination folder."/>
        <input name="whitefiles" type="List_File" description="The subject
            cortex surfaces."/>
        <input name="pialfiles" type="List_File" description="The subject pial
            surfaces."/>
        <input name="annotfiles" type="List_File" description="The pial/white
            surface annotations."/>
        <input name="actor_ang" type="List_Float" description="The actor x, y,
            z position (in degrees)."/>
        <input name="fsconfig" type="File" description="The freesurfer
            configuration batch."/>
        <output name="qcfiles" type="List_File" description="The quality check
            snaps."/>
    </unit>
    """
    import clindmri.plot.pvtk as pvtk
    from clindmri.plot.slicer import plot_image

    # Create a t1 subject map
    t1map = {}
    for fname in t1files:
        subject_id = fname.split("/")[-3]
        if subject_id in t1map:
            raise Exception("Can't map two t1 for subject '{0}'"
                            ".".format(subject_id))
        t1map[subject_id] = fname

    # Create the output list that will contain all the qc files
    qcfiles = []

    # Construct the t1-surfaces overlays and the 3d surface segmentation snaps
    ren = pvtk.ren()
    for name, files in [("white", whitefiles), ("pial", pialfiles)]:
        for fname in files:

            # Get the t1 reference image
            subject_id = fname.split("/")[-3]
            t1file = t1map[subject_id]
            t1_image = nibabel.load(t1file)

            # Get the qc output directory
            qcdir = os.path.join(os.path.dirname(fname), "qc")
            qcname = os.path.basename(fname)
            if not os.path.isdir(qcdir):
                os.makedirs(qcdir)

            # Get the triangular mesh
            basename = os.path.basename(fname).replace(
                name, "aparc.annot").replace(".native", "")
            annotfile = os.path.join(os.path.dirname(fname), basename)
            if annotfile not in annotfiles:
                raise ValueError(
                    "Annotation file '{0}' can't be found.".format(annotfile))
            surface = TriSurface.load(fname, annotfile=annotfile)

            # Construct the surfaces binarized volume
            binarizedfile = os.path.join(qcdir, qcname + ".nii.gz")
            overlay = numpy.zeros(t1_image.shape, dtype=numpy.uint)
            indices = numpy.round(surface.vertices).astype(int).T
            indices[0, numpy.where(indices[0] >= t1_image.shape[0])] = 0
            indices[1, numpy.where(indices[1] >= t1_image.shape[1])] = 0
            indices[2, numpy.where(indices[2] >= t1_image.shape[2])] = 0
            overlay[indices.tolist()] = 1
            overlay_image = nibabel.Nifti1Image(overlay, t1_image.get_affine())
            nibabel.save(overlay_image, binarizedfile)
            snap_file = os.path.join(qcdir, qcname + ".png")
            plot_image(t1file, overlay_file=binarizedfile, snap_file=snap_file,
                       name=qcname, overlay_cmap="cold_hot")
            qcfiles.append(snap_file)

            # Create a vtk surface actor of the cortex surface with the
            # associated labels
            ctab = [item["color"] for _, item in surface.metadata.items()]
            actor = pvtk.surface(
                surface.vertices, surface.triangles, surface.labels, ctab)
            actor.RotateX(actor_ang[0])
            actor.RotateY(actor_ang[1])
            actor.RotateZ(actor_ang[2])

            # Create a 3d surface segmentation snap
            pvtk.add(ren, actor)
            snaps = pvtk.record(ren, qcdir, qcname, n_frames=36,
                                az_ang=10, animate=True, delay=50)
            qcfiles.append(snaps[0])
            snaps = pvtk.record(ren, qcdir, qcname + ".3d", n_frames=1)
            qcfiles.append(snaps[0])
            pvtk.clear(ren)

    # Get the FreeSurfer lookup table
    fs_lut_names, fs_lut_colors = parse_fs_lut(os.path.join(
        os.path.dirname(fsconfig), "FreeSurferColorLUT.txt"))
    cmap = []
    nb_values = numpy.asarray(fs_lut_colors.keys()).max()
    cmap = numpy.zeros((nb_values, 4), dtype=numpy.single)
    for key, color in fs_lut_colors.items():
        if key > 0:
            cmap[key - 1, :3] = color
    cmap[:, 3] = 200.
    cmap /= 255.

    # Compute t1-images overlays
    for name, files in [("aseg", asegfiles), ("wm", wmfiles)]:
        for fname in files:

            # Get the t1 reference image
            subject_id = fname.split("/")[-3]
            t1file = t1map[subject_id]
            t1_image = nibabel.load(t1file)

            # Get the qc output directory
            qcdir = os.path.join(os.path.dirname(fname), "qc")
            if not os.path.isdir(qcdir):
                os.makedirs(qcdir)

            # Troncate the color map based on the label max
            array = nibabel.load(fname).get_data()
            order = sorted(set(array.flatten()))
            ccmap = cmap[order[1]: order[-1] + 1]

            # Overlay the current image with the t1 image
            qcname = "t1-{0}".format(name)
            snap_file = os.path.join(qcdir, qcname + ".png")
            plot_image(t1file, overlay_file=fname, snap_file=snap_file,
                       name=qcname, overlay_cmap=ccmap, cut_coords=(0, 0, 0))
            qcfiles.append(snap_file)

    return qcfiles
if fsdir is None:
    raise NotImplementedError()
    # recon-all -s 0001 -i T1.nii.gz

if use_vtk:
    physical_to_index = numpy.linalg.inv(nibabel.load(t1_file).get_affine())
    hemi_surfaces = read_cortex_surface_segmentation(fsdir, physical_to_index)
    ren = pvtk.ren()
    for hemi in ["lh", "rh"]:
        surface = hemi_surfaces[hemi]
        ctab = [item["color"] for _, item in surface.metadata.items()]
        actor = pvtk.surface(surface.vertices, surface.triangles,
                             surface.labels, ctab)
        pvtk.add(ren, actor)
        pvtk.record(ren, qcdir, hemi + "_white")
        pvtk.clear(ren)
        actor = pvtk.surface(surface.inflated_vertices, surface.triangles,
                             surface.labels, ctab)
        pvtk.add(ren, actor)
        pvtk.record(ren, qcdir, hemi + "_inflated")
        pvtk.clear(ren)

"""
Diffusion Processing
====================

At this point we have a motion- & artifact-corrected image, the corrected
gradient table and a mask of the non-diffusion-weighted image.

From our DTI data, we need to produce the following information:
示例#3
0
if fsdir is None:
    raise NotImplementedError()
    # recon-all -s 0001 -i T1.nii.gz

if use_vtk:
    physical_to_index = numpy.linalg.inv(nibabel.load(t1_file).get_affine())
    hemi_surfaces = read_cortex_surface_segmentation(fsdir, physical_to_index)
    ren = pvtk.ren()
    for hemi in ["lh", "rh"]:
        surface = hemi_surfaces[hemi]
        ctab = [item["color"] for _, item in surface.metadata.items()]
        actor = pvtk.surface(surface.vertices, surface.triangles,
                             surface.labels, ctab)
        pvtk.add(ren, actor)
        pvtk.record(ren, qcdir, hemi + "_white")
        pvtk.clear(ren)
        actor = pvtk.surface(surface.inflated_vertices, surface.triangles,
                             surface.labels, ctab)
        pvtk.add(ren, actor)
        pvtk.record(ren, qcdir, hemi + "_inflated")
        pvtk.clear(ren)
"""
Diffusion Processing
====================

At this point we have a motion- & artifact-corrected image, the corrected
gradient table and a mask of the non-diffusion-weighted image.

From our DTI data, we need to produce the following information:

* The mask of the non-diffusion-weighted image.
示例#4
0
def qc(t1files,
       wmfiles,
       asegfiles,
       whitefiles,
       pialfiles,
       annotfiles,
       actor_ang=[0., 0., 0.],
       output_directory=None,
       fsconfig="/i2bm/local/freesurfer/SetUpFreeSurfer.sh"):
    """ Compute some quality check plots on the converted FrreSurfer
    outputs.

    The subjecy id in the input files must appear in the -3 position:
        xxx/subject_id/convert/t1.nii.gz

    Steps:

    * t1-images overlays
    * 3d surface segmentation snaps
    * t1-surfaces overlays

    actor_ang: float (optional, default 0)
        the actor rotation in the z direction.

    <unit>
        <input name="t1files" type="List_File" description="The
            t1 subject files."/>
        <input name="wmfiles" type="List_File" description="The
            white matter subject files."/>
        <input name="asegfiles" type="List_File" description="The
            subcortical segmentation subject files."/>
        <input name="output_directory" type="Directory" description="The
            conversion destination folder."/>
        <input name="whitefiles" type="List_File" description="The subject
            cortex surfaces."/>
        <input name="pialfiles" type="List_File" description="The subject pial
            surfaces."/>
        <input name="annotfiles" type="List_File" description="The pial/white
            surface annotations."/>
        <input name="actor_ang" type="List_Float" description="The actor x, y,
            z position (in degrees)."/>
        <input name="fsconfig" type="File" description="The freesurfer
            configuration batch."/>
        <output name="qcfiles" type="List_File" description="The quality check
            snaps."/>
    </unit>
    """
    import clindmri.plot.pvtk as pvtk
    from clindmri.plot.slicer import plot_image

    # Create a t1 subject map
    t1map = {}
    for fname in t1files:
        subject_id = fname.split("/")[-3]
        if subject_id in t1map:
            raise Exception("Can't map two t1 for subject '{0}'"
                            ".".format(subject_id))
        t1map[subject_id] = fname

    # Create the output list that will contain all the qc files
    qcfiles = []

    # Construct the t1-surfaces overlays and the 3d surface segmentation snaps
    ren = pvtk.ren()
    for name, files in [("white", whitefiles), ("pial", pialfiles)]:
        for fname in files:

            # Get the t1 reference image
            subject_id = fname.split("/")[-3]
            t1file = t1map[subject_id]
            t1_image = nibabel.load(t1file)

            # Get the qc output directory
            qcdir = os.path.join(os.path.dirname(fname), "qc")
            qcname = os.path.basename(fname)
            if not os.path.isdir(qcdir):
                os.makedirs(qcdir)

            # Get the triangular mesh
            basename = os.path.basename(fname).replace(name,
                                                       "aparc.annot").replace(
                                                           ".native", "")
            annotfile = os.path.join(os.path.dirname(fname), basename)
            if annotfile not in annotfiles:
                raise ValueError(
                    "Annotation file '{0}' can't be found.".format(annotfile))
            surface = TriSurface.load(fname, annotfile=annotfile)

            # Construct the surfaces binarized volume
            binarizedfile = os.path.join(qcdir, qcname + ".nii.gz")
            overlay = numpy.zeros(t1_image.shape, dtype=numpy.uint)
            indices = numpy.round(surface.vertices).astype(int).T
            indices[0, numpy.where(indices[0] >= t1_image.shape[0])] = 0
            indices[1, numpy.where(indices[1] >= t1_image.shape[1])] = 0
            indices[2, numpy.where(indices[2] >= t1_image.shape[2])] = 0
            overlay[indices.tolist()] = 1
            overlay_image = nibabel.Nifti1Image(overlay, t1_image.get_affine())
            nibabel.save(overlay_image, binarizedfile)
            snap_file = os.path.join(qcdir, qcname + ".png")
            plot_image(t1file,
                       overlay_file=binarizedfile,
                       snap_file=snap_file,
                       name=qcname,
                       overlay_cmap="cold_hot")
            qcfiles.append(snap_file)

            # Create a vtk surface actor of the cortex surface with the
            # associated labels
            ctab = [item["color"] for _, item in surface.metadata.items()]
            actor = pvtk.surface(surface.vertices, surface.triangles,
                                 surface.labels, ctab)
            actor.RotateX(actor_ang[0])
            actor.RotateY(actor_ang[1])
            actor.RotateZ(actor_ang[2])

            # Create a 3d surface segmentation snap
            pvtk.add(ren, actor)
            snaps = pvtk.record(ren,
                                qcdir,
                                qcname,
                                n_frames=36,
                                az_ang=10,
                                animate=True,
                                delay=50)
            qcfiles.append(snaps[0])
            snaps = pvtk.record(ren, qcdir, qcname + ".3d", n_frames=1)
            qcfiles.append(snaps[0])
            pvtk.clear(ren)

    # Get the FreeSurfer lookup table
    fs_lut_names, fs_lut_colors = parse_fs_lut(
        os.path.join(os.path.dirname(fsconfig), "FreeSurferColorLUT.txt"))
    cmap = []
    nb_values = numpy.asarray(fs_lut_colors.keys()).max()
    cmap = numpy.zeros((nb_values, 4), dtype=numpy.single)
    for key, color in fs_lut_colors.items():
        if key > 0:
            cmap[key - 1, :3] = color
    cmap[:, 3] = 200.
    cmap /= 255.

    # Compute t1-images overlays
    for name, files in [("aseg", asegfiles), ("wm", wmfiles)]:
        for fname in files:

            # Get the t1 reference image
            subject_id = fname.split("/")[-3]
            t1file = t1map[subject_id]
            t1_image = nibabel.load(t1file)

            # Get the qc output directory
            qcdir = os.path.join(os.path.dirname(fname), "qc")
            if not os.path.isdir(qcdir):
                os.makedirs(qcdir)

            # Troncate the color map based on the label max
            array = nibabel.load(fname).get_data()
            order = sorted(set(array.flatten()))
            ccmap = cmap[order[1]:order[-1] + 1]

            # Overlay the current image with the t1 image
            qcname = "t1-{0}".format(name)
            snap_file = os.path.join(qcdir, qcname + ".png")
            plot_image(t1file,
                       overlay_file=fname,
                       snap_file=snap_file,
                       name=qcname,
                       overlay_cmap=ccmap,
                       cut_coords=(0, 0, 0))
            qcfiles.append(snap_file)

    return qcfiles