Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature-based labeling #8

Open
binarybottle opened this issue May 12, 2013 · 9 comments
Open

Feature-based labeling #8

binarybottle opened this issue May 12, 2013 · 9 comments

Comments

@binarybottle
Copy link
Member

there are three ways i've been thinking about labeling brains with mindboggle:

  1. surface-based registration with freesurfer using the dkt40 or dkt100.
    this is already implemented in mindboggle's nipype. as satra pointed out, given the DKT-40 atlas inclusion in the new freesurfer, this doesn't add anything new -- we might as well inherit freesurfer's labels, and reduce the 31 cortical labels to 25 if we want to subscribe to the DKT25 protocol. mindboggle would then be used primarily for shape analysis, which is the primary contribution in the original r01 proposal.
  2. one of my original goals with mindboggle is feature-based labeling. i was hoping to identify fundi independent of labels based on position and shape, and then either drive atlas (volume/surface) registrations to label, or fill the cortex with labels between these delimiting landmarks. however, breaking up / combining fundi so that there is a one-to-one matching across brains turns out to be a harder problem than i thought it would be.
  3. we are currently developing a hybrid of pull request trial #1 and replaced freesurfer mri_surf2surf command with nipype's SurfaceTransform #2. the fundi are currently segmented/identified/labeled based on initial automated labels (pull request trial #1), and we would use label propagation to "fix" the label boundaries to the fundi (replaced freesurfer mri_surf2surf command with nipype's SurfaceTransform #2).

the realign_label_boundary() is the method to realign the label boundaries. it calls:

    self.initialize_seed_labels(init='label_boundary', 
       output_filename = label_boundary_filename)

which would simply be set to the initial automated labels or to the consensus set of labels, where there is extremely high probability that the label assignments are correct.

there is a lot of redundancy between rebound.py's functions and the rest of mindboggle's. it would be good to simply extract what is relevant from rebound.py, out of its current oop framework. the next method would be replaced by labels/labels.py's extract_borders() function, then separate same-label-pair segments:

    self.find_label_boundary_segments()

this is the heart of the label propagation:​

    self.graph_based_learning(realign=True, max_iters=max_iters)
    self.assign_realigned_labels(filename = output_file_regions)

f​inally, ​extract_borders() would replace:​

    self.find_label_boundary(realigned_labels=True,
        output_filename = output_file_boundaries)
@ohinds
Copy link
Contributor

ohinds commented May 13, 2013

ok, i can help with this if you want.

what is the status of the implementation of method 3? is all the functionality there, but just needs to be integrated into the standard mindboggle stream? or is there algorithmic / software dev work that needs to be done here?

@binarybottle
Copy link
Member Author

great!

if you look at the propagate() function in segment.py, you'll see that it calls rebound.py, and uses a simple weighted average algorithm for label propagation to resolve label boundaries between neighboring sulcus candidates:

            # Propagate seed IDs from seeds
            B.graph_based_learning(method='propagate_labels', realign=False,
                                   kernel=kernels.rbf_kernel, sigma=sigma,
                                   max_iters=max_iters, tol=tol, vis=False)

realign is set to False here, but it is this untested functionality that we would like to apply to the case of realigning label boundaries to fundus curves.

@ghost ghost assigned ohinds May 15, 2013
@ohinds
Copy link
Contributor

ohinds commented Jun 4, 2013

making good progress on this. question:
are we doing twice as much computation as necessary by propagating both label boundary cosegments? couldn't we propagate just one and get basically the same answer?

@binarybottle
Copy link
Member Author

in the trivial case of a two-label problem, establishing which vertices have one label automatically solves for the other label, but how would one know what label should flank a cosegment if there are multiple labeled regions?

@ohinds
Copy link
Contributor

ohinds commented Jun 4, 2013

well, since we are propagating boundaries, not labels themselves, we always know the label pair associated with the propagated boundary. i suppose what we wouldn't know for sure would be which label was on which side of the boundary. in the best case you could fill that in by assuming that labels are continuous, but that might not always work depending on how the propagation works out. after i finish implementing realignment i'll see if we can speed it up by only propagating boundaries instead of cosegments.

@binarybottle
Copy link
Member Author

i follow you exactly. you're on the mark. i would much prefer to propagate between fundus curves that define label boundaries without having to explicitly flank the curves with labels (which is a challenge). intuitively, if one has a label boundary A-B and neighboring label boundaries B-C, B-D, and C-D, then one would expect vertices that lie along the shortest path between A-B and B-C to have label B.

@ohinds
Copy link
Contributor

ohinds commented Jun 11, 2013

So, this is taking a little longer than I expected, so I wanted to
give a progress report about where I am now and where I'm going. I've
played around with a good number of different approaches for reliably
spliting the surface into labels that respect the fundus lines. Please
feel free to throw other ideas my way.

  1. Initialize boundary seed vertices from automatically generated
    FreeSurfer labels. (done)

  2. Propagate boundary probabilities from the seeds to the rest of the
    cortical vertices using graph based learning. (done)

  3. Connect all fundus curves with surface-based shortest-paths to
    create a tiling of the cortex based on new boundary
    locations. (skipping for now as we have a complete tiling from the
    manual labels)

  4. Find the highest probability boundary for each vertex on the new
    boundaries. (done)

  5. Chop the surface into connected components based on new label
    boundaries. (todo)

  6. Assign the vertices in each connected component the label most
    likely based on the boundary identities. (todo)

Does this make sense?

@binarybottle
Copy link
Member Author

This makes perfect sense to me -- #5 and #6 must be conquered!

I would really like to see #3! Could you please attach an image. Regardless of what we settle on, we should definitely compare shortest-path-connected fundus parcellations with manual labels!

@ohinds
Copy link
Contributor

ohinds commented Jun 18, 2013

Ok, so I made some good progress on this and just pushed a commit (90279f0) that accomplishes a good bit of what we are after here.

In the new file boundary_realignment.py, the function realign_boundaries_to_fundus_lines will take a surface with fundus lines and inital labels and lock the label boundaries to the fundus lines. An example of running this on a single left hemisphere is up at MB/data/realignment_example. The file names should be self-explanatory, but in effect we'd like lh.labels.DKT31.manual.vtk to match lh.pial.DKTatlas40_realigned.vtk as much as possible.

Remaining TODOs until this issue can be closed:

  • Fundus curves need to be connected via shortest paths.
  • Final label assignment needs to be debugged a little. There is one misassigned label in the example.
  • Validation of this method should be performed using the 101 brains.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants