Skip to content

Instantly share code, notes, and snippets.

@bogovicj
Last active August 29, 2022 20:38
Show Gist options
  • Save bogovicj/6de68b76f290cfb517ad1de67abc0170 to your computer and use it in GitHub Desktop.
Save bogovicj/6de68b76f290cfb517ad1de67abc0170 to your computer and use it in GitHub Desktop.
Visualize the hemibrain and fafb together
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import org.janelia.saalfeldlab.n5.N5DatasetDiscoverer;
import org.janelia.saalfeldlab.n5.N5FSReader;
import org.janelia.saalfeldlab.n5.N5Reader;
import org.janelia.saalfeldlab.n5.N5TreeNode;
import org.janelia.saalfeldlab.n5.hdf5.N5HDF5Reader;
import org.janelia.saalfeldlab.n5.ij.N5Importer;
import org.janelia.saalfeldlab.n5.imglib2.N5DisplacementField;
import org.janelia.saalfeldlab.n5.imglib2.N5Utils;
import org.janelia.saalfeldlab.n5.metadata.MultiscaleMetadata;
import org.janelia.saalfeldlab.n5.metadata.N5GenericSingleScaleMetadataParser;
import org.janelia.saalfeldlab.n5.metadata.N5Metadata;
import org.janelia.saalfeldlab.n5.metadata.N5SingleScaleMetadata;
import bdv.tools.transformation.TransformedSource;
import bdv.util.BdvFunctions;
import bdv.util.BdvOptions;
import bdv.util.BdvStackSource;
import bdv.util.RandomAccessibleIntervalMipmapSource;
import bdv.util.volatiles.SharedQueue;
import bdv.util.volatiles.VolatileViews;
import bdv.viewer.Source;
import mpicbg.spim.data.sequence.FinalVoxelDimensions;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.cache.volatiles.CacheHints;
import net.imglib2.cache.volatiles.LoadingStrategy;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.realtransform.ExplicitInvertibleRealTransform;
import net.imglib2.realtransform.InvertibleRealTransform;
import net.imglib2.realtransform.InvertibleRealTransformSequence;
import net.imglib2.type.volatiles.VolatileUnsignedByteType;
public class Hemi2Fafb
{
public static String FAFB_JRC18 = "/groups/saalfeld/public/jrc2018/transformations/public_transforms/JRC2018F_FAFB.h5";
public static String HEMI_JRC18 = "/groups/saalfeld/public/jrc2018/transformations/public_transforms/JRC2018F_JRCFIB2018F.h5";
public static String FAFB_N5 = "/nrs/saalfeld/FAFB00/v14_align_tps_20170818_dmg.n5/volumes/raw";
public static String FAFB_DSET = "";
public static String HEMI_N5 = "/nrs/flyem/data/tmp/Z0115-22.export.n5/22-34";
public static void main( String[] args ) throws Exception
{
final SharedQueue queue = new SharedQueue( 32 );
final Source<?> hemiSrc = loadHemiN5Pix( HEMI_N5, queue);
final Source< ? > hemiTransformedSrc = transformSource( hemiSrc, loadHemibrainN5ToFAFB() );
final BdvOptions opts = BdvOptions.options().numRenderingThreads( 32 );
final BdvStackSource< ? > bdv = BdvFunctions.show( hemiTransformedSrc, opts );
final Source<?> fafbSrc = loadFafbUm(queue);
BdvFunctions.show( fafbSrc, opts.addTo( bdv ) );
}
public static Source<?> transformSource( Source<?> src, InvertibleRealTransform transform )
{
System.out.println("tform src");
final RealTransformedSource wsrc = new RealTransformedSource(src, src.getName()+" transformed" );
wsrc.updateTransform( transform );
wsrc.setIsTransformed( true );
return wsrc;
}
public static Source<?> affineSource( Source<?> src, AffineTransform3D transform )
{
System.out.println("affine src");
TransformedSource tsrc = new TransformedSource( src );
tsrc.setFixedTransform( transform );
return tsrc;
}
public static AffineTransform3D hemiN5ToDvid()
{
final AffineTransform3D toDvid = new AffineTransform3D();
toDvid.set(
0.0, 0.0, -1.0, 34427,
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0 );
return toDvid;
}
public static AffineTransform3D hemiN5ToDvidUm()
{
final AffineTransform3D xfm = hemiN5ToDvid();
final AffineTransform3D res = new AffineTransform3D();
res.scale( 0.008, 0.008, 0.008 );
xfm.preConcatenate( res );
return xfm;
}
public static InvertibleRealTransform loadHemibrainN5ToFAFB() throws Exception
{
final N5HDF5Reader n5 = new N5HDF5Reader( HEMI_JRC18, 3, 32, 32, 32 );
final ExplicitInvertibleRealTransform dfield = N5DisplacementField.openInvertible(n5, 0);
final InvertibleRealTransform hemi2Fafb = loadJrc2018ToFafb();
final InvertibleRealTransformSequence seq = new InvertibleRealTransformSequence();
seq.add( hemi2Fafb );
seq.add( dfield );
seq.add( hemiN5ToDvidUm().inverse() );
return seq;
}
public static InvertibleRealTransform loadHemibrainN5ToJrc2018() throws Exception
{
final N5HDF5Reader n5 = new N5HDF5Reader( HEMI_JRC18, 3, 32, 32, 32 );
final ExplicitInvertibleRealTransform dfield = N5DisplacementField.openInvertible(n5, 0);
final InvertibleRealTransformSequence seq = new InvertibleRealTransformSequence();
seq.add( dfield );
seq.add( hemiN5ToDvidUm().inverse() );
return seq;
}
public static InvertibleRealTransform loadJrc2018ToHemibrain() throws Exception
{
N5HDF5Reader n5 = new N5HDF5Reader( HEMI_JRC18, 3, 32, 32, 32 );
return N5DisplacementField.openInvertible(n5, 0).inverse();
}
public static InvertibleRealTransform loadFafbToJrc2018() throws Exception
{
N5HDF5Reader n5 = new N5HDF5Reader( FAFB_JRC18, 3, 32, 32, 32 );
return N5DisplacementField.openInvertible(n5, 0);
}
public static InvertibleRealTransform loadJrc2018ToFafb() throws Exception
{
N5HDF5Reader n5 = new N5HDF5Reader( FAFB_JRC18, 3, 32, 32, 32 );
return N5DisplacementField.openInvertible(n5, 0).inverse();
}
public static Source< ? > loadHemiN5Pix( final SharedQueue queue ) throws IOException
{
return loadHemiN5Pix( HEMI_N5, queue );
}
public static Source< ? > loadFafbNm( final SharedQueue queue ) throws IOException
{
N5Reader n5 = new N5FSReader( FAFB_N5 );
return getRandomAccessibleIntervalMipmapSourceV( n5, FAFB_DSET, "fafb", queue, false, new double[] {4,4,40} );
}
public static Source< ? > loadFafbUm( final SharedQueue queue ) throws IOException
{
N5Reader n5 = new N5FSReader( FAFB_N5 );
return getRandomAccessibleIntervalMipmapSourceV( n5, FAFB_DSET, "fafb", queue, false, new double[] {0.004, 0.004 ,0.04} );
}
public static Source< ? > loadHemiN5Pix( final String hemiN5Path, final SharedQueue queue ) throws IOException
{
N5Reader n5hemi = new N5FSReader( hemiN5Path );
return getRandomAccessibleIntervalMipmapSourceV( n5hemi, "hemibrain", "hemibrain", queue );
}
public static Source< ? > loadHemiN5Um( final String hemiN5Path, final SharedQueue queue ) throws IOException
{
N5Reader n5hemi = new N5FSReader( hemiN5Path );
return getRandomAccessibleIntervalMipmapSourceV( n5hemi, "hemibrain", "hemibrain", queue, true, new double[] {0.004, 0.004, 0.004 });
}
public static Source<?> getRandomAccessibleIntervalMipmapSourceV(
final N5Reader n5, final String dataset, final String name, final SharedQueue queue ) throws IOException
{
return getRandomAccessibleIntervalMipmapSourceV( n5, dataset, name, queue, true );
}
public static Source<?> getRandomAccessibleIntervalMipmapSourceV(
final N5Reader n5, final String dataset, final String name, final SharedQueue queue, boolean relativeScales ) throws IOException
{
return getRandomAccessibleIntervalMipmapSourceV( n5, dataset, name, queue, relativeScales, new double[]{1,1,1} );
}
public static Source<?> getRandomAccessibleIntervalMipmapSourceV(
final N5Reader n5, final String dataset, final String name, final SharedQueue queue, boolean relativeScales, double[] res ) throws IOException
{
N5GenericSingleScaleMetadataParser metaParser = new N5GenericSingleScaleMetadataParser(
"min", "max",
"resolution", "offset", "unit",
"downsamplingFactors");
N5DatasetDiscoverer disc = new N5DatasetDiscoverer( n5, Collections.singletonList(metaParser), Arrays.asList( N5Importer.GROUP_PARSERS));
N5TreeNode node = disc.discoverAndParseRecursive("/");
N5Metadata meta = node.getMetadata();
MultiscaleMetadata<N5SingleScaleMetadata> ms = (MultiscaleMetadata)meta;
int N = ms.getPaths().length;
double[][] scales = new double[N][];
final RandomAccessibleInterval< ? >[] scaleLevelImgs = new RandomAccessibleInterval[ scales.length ];
int i = 0;
for ( N5SingleScaleMetadata scaleMeta : ms.getChildrenMetadata() )
{
N5Utils.openVolatile( n5, scaleMeta.getPath() );
// scales[i] = scaleMeta.getPixelResolution();
scales[i] = scaleMeta.getDownsamplingFactors();
for( int d = 0; d < 3; d++ )
{
scales[i][d] *= res[d];
}
System.out.println( String.format( "s%d", i ) + " " + Arrays.toString(scales[i]));
i++;
}
for ( int s = 0; s < scales.length; ++s )
{
RandomAccessibleInterval<?> rai = N5Utils.openVolatile( n5, getScaleGroupPath( s ) );
scaleLevelImgs[ s ] = VolatileViews.wrapAsVolatile( rai, queue,
new CacheHints(LoadingStrategy.VOLATILE, 0, true));
}
final RandomAccessibleIntervalMipmapSource< ? > source =
new RandomAccessibleIntervalMipmapSource(
scaleLevelImgs,
new VolatileUnsignedByteType(),
scales,
new FinalVoxelDimensions("", 1, 1, 1 ),
name );
return source;
}
public static String getScaleGroupPath( final int scale )
{
return String.format( "s%d", scale );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment