changed 3 years ago
Published Linked with GitHub

NiBabel Surface API meeting logs

10 February 2022

28 January 2022

Attending: Chris, Joshua Teves

  • MNE/STC
    • Unincluded reference TriangularMesh
    • Includes subsample indices
      • lvertno = array of indices into left surface, rvertno
      • (lvertno + rvertno, tpts)
    • 2 patches, with deferred geometry (FreeSurfer subject)
      • How to determine decimated mesh (mne.surface.decimate_surface)
    • dsurface.triangles, dsurface.points

14 January 2022

Attending: Chris, Eric Larson

Notes:

  • Patches
    • (surface, index array-like)

19 November 2021

  • Agenda
    • CJM summary
      • Geometry is now Pointset and SurfaceGeometry is now TriangularMesh
        • From consideration of nitransforms SampledSpatialData + NURBS, should try to be more specific
        • Pointset could be Pointcloud, which seems common in graphics world
        • Haven't come up with a good name for VolumeGeometry; nitransforms uses ImageGrid
      • CIFTI keeps throwing up wrinkles
        • Loading VolumeGeometry is straightforward
        • Meshes are subsetted without actually providing the mesh. Haven't fully thought through the deferred loading model, whether we need objects with different guarantees from TriangularMesh or to relax those guarantees.
      • Got a CaretSpecFile DTD out of hcp-users
  • Decisions:
    • Bundle fsLR spec to reduce the scope for missing CIFTI geometry data
    • Example task:
      • Load patch by name from parcellation file, subsample CIFTI without loading wb.spec. Load wb.spec and retrieve coordinates.

Hao-Ting will take another shot at GIFTI. Oscar will review with an eye toward making sure we aren't making life harder for nitransforms.

5 November 2021

BIAP: https://github.com/nipy/nibabel/pull/1056

  • BF: Make sure subsampling (e.g selecting parcels) of surface geometry is straightforward
  • JT: MNE's STC format (pointset) -> GIFTI
    • See test NPSurfaceImage
  • OE: Nitransforms has a common concept for surface/volumetric structures

Resources:

Post-meeting comments from Satra, mixed freely with CJM commentary:

  • Non-triangular meshes, such as NURBS are worth considering (nurbs-python), to avoid precluding in the future
    • This represents a more generic curve/surface class. may be worthwhile looking into the library a bit.
  • potential class structure: genericmesh -> triangularmesh-> GIFTI
  • The SpeechLab Toolkit has SurfTools for operating on surfaces. Ensuring that we enable these things (if not directly implement) would be a good check.
  • other considerations are disconnected meshes (like left + right pairs) or tessellations for every parcellation?
  • Are boundary-element/finite-element models in-scope for nibabel? In any event, ensure they are possible with our data structures.

Nibabel Surface API initial meeting

Logistics

Poll for date/time: https://doodle.com/poll/ih86eymx9h64vhai
Selected date/time: Thursday 16 September 2021 @ 9am EDT
Call link: Zoom (has waiting room) (expired)

Follow-up date/time: Thursday 30 September 2021 @ 9am EDT
Follow-up call link: Zoom

Meeting Notes

Resources

Potential API sketches

Please feel free to start an H3 block here and fiddle. Note your name so you can walk us through it. This does not need to be fully thought out.

Chris M sketch

Desiderata

  • Combine / select brain structures
    • Simplest: lh + rh
    • More complex: one or more parcellations
def plot(surf_img, surface=None): texture = surf_img.get_data() coords, triangles = surf_img.get_mesh(surface) ... plot(surf_img) # Default surface plot(surf_img, "inflated") # Associated surface plot(surf_img, "pial") def surface_maths(mathstr, surf_img1, surf_img2): assert surf_img1.header == surf_img2.header res = domaths(mathstr, surf_img1.get_data(), surf_img2.get_data()) return SurfaceImage(res, surf_img1.header) def smooth_surf(surf_img, fwhm, surface=None): coords, triangles = surf_img.get_mesh(surface) ... def decimate(surf_hdr, *, vtx_count=None, ratio=None): # Decimation creates a new mesh in the same space # Can be simplified on a per-format basis if assumptions are met def resample_from_to(surf_img, surf_hdr): ... def decimate_and_resample(surf_img, *, vtx_count=None, ratio=None): # From https://nipy.discourse.group/t/collecting-use-cases/58/4 new_header = decimate(surf_img.header, vtx_count=vtx_count, ratio=ratio) fwhm = calculate_antialiasing_window(surf_img.header.vtx_count, new_header.vtx_count) smoothed_img = smooth_surf(surf_img, fwhm) return resample_from_to(surf_img, new_header) class SurfaceImage: header : SurfaceHeader data : ndarray def __init__(self, ndarray, ): ... def load_header(self, path): ... class SurfaceHeader:
  • What happens when we lack some metadata?

Diffusion emedding on connectome

https://github.com/MICA-MNI/BrainSpace

GLM on surface data:

https://github.com/MICA-MNI/BrainStat

A MATLAB tool for surface based GLM - reference for potential use cases and interface

https://www.math.mcgill.ca/keith/surfstat/

Surfplot

https://github.com/danjgale/surfplot

Select a repo