Skip to content

Commit

Permalink
Merge pull request #2 from Robbie1977/main
Browse files Browse the repository at this point in the history
bringing in line with main
  • Loading branch information
Robbie1977 authored Nov 10, 2021
2 parents 6c8d2c6 + d133489 commit b224a8c
Show file tree
Hide file tree
Showing 19 changed files with 234,039 additions and 17 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
include flybrains/data/*.json
include flybrains/data/*.csv
include flybrains/data/*.txt
include flybrains/meshes/*.ply
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ pip3 install flybrains
In order to use the Jefferis lab transforms, you will need to have
[CMTK](https://www.nitrc.org/projects/cmtk/) installed.

For the FANC to JRCVNC2018F transform, you will need to download
[elastix](https://elastix.lumc.nl/index.php) and make sure that the path
to the binaries is in your `PATH` variable.

## Bridging transforms

<p align="center">
Expand Down Expand Up @@ -91,6 +95,8 @@ Please see the [transform tutorial](https://navis.readthedocs.io/en/latest/sourc
for navis to learn how to use the data `flybrains` provides.

## Changes
- `0.1.14` (21/10/21): added FANC <-> JRCVNC2018F transform (requires Elastix and navis >=1.0.0)
- `0.1.13` (14/10/21): add template and mirror transform for FANC
- `0.1.12` (18/09/21): fixed directionality of Jefferis lab CMTK transforms
- `0.1.11` (02/08/21): make downloads work if file size unknown
- `0.1.10` (01/08/21): fix bug that led to warnings during transform registration on Windows systems
Expand Down
Binary file added _static/bridging_graph.afdesign
Binary file not shown.
Binary file modified _static/bridging_graph.pdf
Binary file not shown.
Binary file modified _static/bridging_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions flybrains/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.

__version__ = '0.1.13'
__version_vector__ = (0, 1, 13)
__version__ = '0.1.14'
__version_vector__ = (0, 1, 14)
173 changes: 161 additions & 12 deletions flybrains/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,44 @@ def inject_paths():
transforms.registry.scan_paths()


def _FANCnm_JRCVNC2018F_pre(points):
"""Apply necessary pre-transforms for FANC -> JRCVNC2018F elastix transform."""
# Dark magic transforms see:
# https://github.com/htem/GridTape_VNC_paper/blob/main/template_registration_pipeline/register_EM_dataset_to_template/README.md
points -= (533.2, 533.2, 945) # (1.24, 1.24, 2.1) vox at (430, 430, 450)nm/vox
points /= (430, 430, 450)
points *= (300, 300, 400)
points[:, 2] = 435*400 - points[:, 2] # z flipping a stack with 436 slices

# Convert to microns
points /= 1000

return points


def _FANCnm_JRCVNC2018F_reflect(points):
"""Apply reflect."""
# Unreflect
template_plane_of_symmetry_x_microns = 329 * 0.4
points[:, 0] = template_plane_of_symmetry_x_microns * 2 - points[:, 0]

return points


def _JRCVNC2018F_FANCnm_post(points):
"""Apply necessary post-transforms for JRCVNC2018F -> FANCnm elastix transform."""
points *= 1000 # Convert microns to nm so that the math below works

# Dark magic transforms see:
# https://github.com/htem/GridTape_VNC_paper/blob/main/template_registration_pipeline/register_EM_dataset_to_template/README.md
points[:, 2] = 435*400 - points[:, 2] # z flipping a stack with 436 slices
points /= (300, 300, 400)
points *= (430, 430, 450)
points += (533.2, 533.2, 945) # (1.24, 1.24, 2.1) vox at (430, 430, 450)nm/vox

return points


def register_transforms():
"""Register transforms with navis."""
# These are the paths we need to scan
Expand Down Expand Up @@ -251,56 +289,56 @@ def register_transforms():
warnings.warn(f'Error registering {hit} as transform: {str(e)}')

# Add transform between JRCFIB2018Fraw (8nm voxel) and JRCFIB2018F (nm)
tr = transforms.affine.AffineTransform(np.diag([8, 8, 8, 1]))
tr = transforms.AffineTransform(np.diag([8, 8, 8, 1]))
transforms.registry.register_transform(transform=tr,
source='JRCFIB2018Fraw',
target='JRCFIB2018F',
transform_type='bridging')

# Add transform between JRCFIB2018F (nm) and JRCFIB2018Fum (um)
tr = transforms.affine.AffineTransform(np.diag([1e3, 1e3, 1e3, 1]))
tr = transforms.AffineTransform(np.diag([1e3, 1e3, 1e3, 1]))
transforms.registry.register_transform(transform=tr,
source='JRCFIB2018Fum',
target='JRCFIB2018F',
transform_type='bridging')

# Add transform between FAFB14um and FAFB14 (nm)
tr = transforms.affine.AffineTransform(np.diag([1e3, 1e3, 1e3, 1]))
tr = transforms.AffineTransform(np.diag([1e3, 1e3, 1e3, 1]))
transforms.registry.register_transform(transform=tr,
source='FAFB14um',
target='FAFB14',
transform_type='bridging')

# Add alias transform between JRCFIB2018F and hemibrain (they are synonymous)
tr = transforms.base.AliasTransform()
tr = transforms.AliasTransform()
transforms.registry.register_transform(transform=tr,
source='hemibrain',
target='JRCFIB2018F',
transform_type='bridging')

# Add alias transform between JRCFIB2018F and hemibrain (they are synonymous)
tr = transforms.base.AliasTransform()
tr = transforms.AliasTransform()
transforms.registry.register_transform(transform=tr,
source='hemibrainraw',
target='JRCFIB2018Fraw',
transform_type='bridging')

# Add alias transform between JRCFIB2018F and hemibrain (they are synonymous)
tr = transforms.base.AliasTransform()
tr = transforms.AliasTransform()
transforms.registry.register_transform(transform=tr,
source='hemibrainum',
target='JRCFIB2018Fum',
transform_type='bridging')

# Add alias transform between FAFB and FAFB14 (they are synonymous)
tr = transforms.base.AliasTransform()
tr = transforms.AliasTransform()
transforms.registry.register_transform(transform=tr,
source='FAFB',
target='FAFB14',
transform_type='bridging')

# Bogovic et al seem to have a difference in Z calibration
tr = transforms.affine.AffineTransform(np.diag([1, 1, 1/0.6220880, 1]))
tr = transforms.AffineTransform(np.diag([1, 1, 1/0.6220880, 1]))
transforms.registry.register_transform(transform=tr,
source='JFRC2',
target='JFRC2010',
Expand All @@ -309,8 +347,8 @@ def register_transforms():
# Add a simple mirror transform for FAFB14
fp = os.path.join(data_filepath, 'FAFB14_mirror_landmarks.csv')
lm = pd.read_csv(fp)
tr = transforms.thinplate.TPStransform(lm[['x_flip', 'y_flip', 'z_flip']].values,
lm[['x_mirr', 'y_mirr', 'z_mirr']].values)
tr = transforms.TPStransform(lm[['x_flip', 'y_flip', 'z_flip']].values,
lm[['x_mirr', 'y_mirr', 'z_mirr']].values)
transforms.registry.register_transform(transform=tr,
source='FAFB14',
target=None,
Expand All @@ -319,9 +357,120 @@ def register_transforms():
# Add a simple symmetrization transform for FAFB14
fp = os.path.join(data_filepath, 'FAFB14_symmetrize_landmarks_nm.csv')
lm = pd.read_csv(fp)
tr = transforms.thinplate.TPStransform(lm[['x', 'y', 'z']].values,
lm[['x_sym', 'y_sym', 'z_sym']].values)
tr = transforms.TPStransform(lm[['x', 'y', 'z']].values,
lm[['x_sym', 'y_sym', 'z_sym']].values)
transforms.registry.register_transform(transform=tr,
source='FAFB14',
target='FAFB14sym',
transform_type='bridging')
tr = transforms.AliasTransform()
transforms.registry.register_transform(transform=tr,
source='FANC',
target='FANCnm',
transform_type='bridging')

# Add FANC mirror transform based on subsampling a FANC -> MANCsym transform
fp = os.path.join(data_filepath, 'FANC_mirror_landmarks.csv')
lm = pd.read_csv(fp)
tr = transforms.TPStransform(lm[['x_flip', 'y_flip', 'z_flip']].values,
lm[['x_mirr', 'y_mirr', 'z_mirr']].values)
transforms.registry.register_transform(transform=tr,
source='FANC',
target=None,
transform_type='mirror')

# Add a FANC-MANC transform. These landmarks are created from the
# CMTK transforms between FANC -> MANCsym -> MANC
fp = os.path.join(data_filepath, 'MANC_FANC_landmarks_nm.csv')
lm = pd.read_csv(fp)
tr = transforms.TPStransform(lm[['x_manc', 'y_manc', 'z_manc']].values,
lm[['x_fanc', 'y_fanc', 'z_fanc']].values)
transforms.registry.register_transform(transform=tr,
source='MANC',
target='FANC',
transform_type='bridging')

# Add transform between raw (voxel) and nanometer space for MANC and FANC
tr = transforms.AffineTransform(np.diag([8, 8, 8, 1]))
transforms.registry.register_transform(transform=tr,
source='MANCraw',
target='MANC',
transform_type='bridging')
tr = transforms.AffineTransform(np.diag([4.3, 4.3, 45, 1]))
transforms.registry.register_transform(transform=tr,
source='FANCraw',
target='FANC',
transform_type='bridging')

# Add alias transform between MANC/FANC and MANC/FANCnm (they are synonymous)
tr = transforms.AliasTransform()
transforms.registry.register_transform(transform=tr,
source='MANC',
target='MANCnm',
transform_type='bridging')

# Some general notes for the Elastix transform between FANC and JRCVNC2018F:
# 1. Elastix transforms are not invertible - hence there are two separate
# transforms for forward and reverse directions
# 2. Both directions require some pre-/postprocessing: unit conversion,
# some offset correction and an inversion across the x-axis.
# These extra steps are realized via two intermediate template spaces:
# FANCum_fixed and JRCVNC2018F_reflected. The bridging path is hence:
# FANC <-> FANC_fixed <-(elastix)-> JRCVNC2018F_reflected <-> JRCVNC2018F
# 3. This transform is technically for FANC v3 but according to Jasper can
# also be applied to v4.

# First up: forward FANC (nm) -> JRCVNC2018F
# Preflight for FANCnm (v3) -> JRCVNC2018F
tr = transforms.FunctionTransform(_FANCnm_JRCVNC2018F_pre)
transforms.registry.register_transform(transform=tr,
source='FANC',
target='FANCum_fixed',
transform_type='bridging')

# Elastix FANC_fixed -> JRCVNC2018F (reflected) transform
fp = os.path.join(data_filepath, 'TransformParameters.FixedFANC.txt')
tr = transforms.ElastixTransform(fp)
transforms.registry.register_transform(transform=tr,
source='FANCum_fixed',
target='JRCVNC2018F_reflected',
transform_type='bridging')

# Unreflect
tr = transforms.FunctionTransform(_FANCnm_JRCVNC2018F_reflect)
transforms.registry.register_transform(transform=tr,
source='JRCVNC2018F_reflected',
target='JRCVNC2018F',
transform_type='bridging')

# Now the reverse: JRCVNC2018F -> FANC (nm)
# First reflect
tr = transforms.FunctionTransform(_FANCnm_JRCVNC2018F_reflect)
transforms.registry.register_transform(transform=tr,
source='JRCVNC2018F',
target='JRCVNC2018F_reflected',
transform_type='bridging')

# Second apply Elastix FANC_fixed -> JRCVNC2018F transform
fp1 = os.path.join(data_filepath, 'TransformParameters.FixedTemplate.Bspline.txt')
fp2 = os.path.join(data_filepath, 'TransformParameters.FixedTemplate.affine.txt')
tr = transforms.ElastixTransform(fp1, copy_files=[fp2])
transforms.registry.register_transform(transform=tr,
source='JRCVNC2018F_reflected',
target='FANCum_fixed',
transform_type='bridging')

# Postflight for JRCVNC2018F -> FANCnm (v3)
tr = transforms.FunctionTransform(_JRCVNC2018F_FANCnm_post)
transforms.registry.register_transform(transform=tr,
source='FANCum_fixed',
target='FANC',
transform_type='bridging')

# To help with cases where data is in FANC voxel space:
# Add transform between FANC (nm) and FANCraw (voxels)
tr = transforms.AffineTransform(np.diag([4.3, 4.3, 45, 1]))
transforms.registry.register_transform(transform=tr,
source='FANCraw',
target='FANC',
transform_type='bridging')
Loading

0 comments on commit b224a8c

Please sign in to comment.