Last active
January 20, 2023 17:06
-
-
Save NicoKiaru/a07c88db1be4ec6524170627819d6f60 to your computer and use it in GitHub Desktop.
A Fiji script that can generate a procedural big image (>4GPix) and resaves it as a multi resolution OME TIFF image #BIOP #Fiji
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Makes a big 2d procedural plane and saves it as a multiresolution ome.tiff image | |
* | |
* Tested on a 128 000 x 128 000 images with 8000 objects (11G pix), 10 resolutions levels, downscale 2 ~ 30 minutes to generate | |
* | |
* PTBIOP update site needed | |
* @author Nicolas Chiaruttini, 2023 | |
*/ | |
#@Integer nPixelsX | |
#@Integer nPixelsY | |
#@Integer nObjects | |
#@TaskService taskService | |
#@File(label = "save path, '.ome.tiff' extension", style="save") filepath | |
// Get a test image | |
RandomAccessibleInterval< UnsignedByteType > labelImage = getTestLabelImage([ nPixelsX, nPixelsY, 1 ] as long[], nObjects); | |
BdvOptions opt = new BdvOptions(); | |
// Show it in BigDataViewer, that's in fact the most easy way I found to turn a RandomAccessibleInterval | |
// into a SourceAndConverter. A SourceAndConverter has many useful extra 'metadata': | |
// Color per channel, a display range (min max) | |
// And 'location' metadata: through its AffineTransform3d, a position in space (x0, y0, z0) | |
// as well as voxel sizes can be written in the bioformats metadata (it's not as general as a fully free affine transform 3d however) | |
final BdvSource source = BdvFunctions.show( | |
labelImage, | |
"Label Image 80000 byte" ); | |
def sourceAndConverter = source.getBdvHandle().getViewerPanel().state().getCurrentSource() | |
// Set color and display range | |
source.setColor(new ARGBType((int)0xFF00FF00)); | |
source.setDisplayRange(0,255); | |
// Builder pattern for OME TIFF export, parallel reading and block computation, serial writing | |
OMETiffPyramidizerExporter.builder() | |
.tileSize(1024, 1024) // One block = size 1024x1024x1 | |
.lzw() // lossless LZW compression | |
.downsample(2) // downscale by a factor 2 between resolution levels (integer compulsory) | |
.nResolutionLevels(10) // ten resolution levels | |
.monitor(taskService) // Optional, but providing it gives a time estimation for the export | |
.nThreads(16) // Each thread computes a block, taken from a queue of blocks to be processed | |
.maxTilesInQueue(60) // Naximum number of blocks computed in advanced. The queue of blocks to be processed won't be longer than this value | |
.savePath(filepath.getAbsolutePath()) // output path : you need to add .ome.tiff to this path | |
.micrometer() // units | |
.create(sourceAndConverter) // an array of sourceandconverter can be passed, each source and converter is a channel | |
.export() // actually performs the export (blocking) | |
// For other arguments that can be provided in the builder patterm look at https://github.com/BIOP/ijp-kheops/blob/2ed70fe5009682903243abf7b1a8aadf83467476/src/main/java/ch/epfl/biop/kheops/ometiff/OMETiffPyramidizerExporter.java#L679 | |
// (channel names, selecting a subset of CZT range, compression type, compression of the temporary files) | |
//------------------------------------- METHODS TO CREATE TEST IMAGE | |
public static RandomAccessibleInterval< UnsignedByteType > getTestLabelImage(final long[] imgTestSize, int nPts) { | |
// the interval in which to create random points | |
FinalInterval interval = new FinalInterval( imgTestSize ); | |
// create an IterableRealInterval | |
IterableRealInterval< UnsignedByteType > realInterval = createRandomPoints( interval, nPts ); | |
// using nearest neighbor search we will be able to return a value an any position in space | |
NearestNeighborSearch< UnsignedByteType > search = | |
new NearestNeighborSearchOnKDTree<>( | |
new KDTree<>( realInterval ) ); | |
// make it into RealRandomAccessible using nearest neighbor search | |
RealRandomAccessible< UnsignedByteType > realRandomAccessible = | |
Views.interpolate( search, new NearestNeighborSearchInterpolatorFactory< UnsignedByteType >() ); | |
// convert it into a RandomAccessible which can be displayed | |
RandomAccessible< UnsignedByteType > randomAccessible = Views.raster( realRandomAccessible ); | |
// set the initial interval as area to view | |
RandomAccessibleInterval< UnsignedByteType > labelImage = Views.interval( randomAccessible, interval ); | |
// Returning it | |
return labelImage; // labelImageCopy; | |
} | |
/** | |
* Create a number of n-dimensional random points in a certain interval | |
* having a random intensity 0...1 | |
* | |
* @param interval - the interval in which points are created | |
* @param numPoints - the amount of points | |
* | |
* @return a RealPointSampleList (which is an IterableRealInterval) | |
*/ | |
public static RealPointSampleList< UnsignedByteType > createRandomPoints( | |
RealInterval interval, int numPoints ) | |
{ | |
// the number of dimensions | |
int numDimensions = interval.numDimensions(); | |
// a random number generator | |
Random rnd = new Random( 2001);//System.currentTimeMillis() ); | |
// a list of Samples with coordinates | |
RealPointSampleList< FloatType > elements = | |
new RealPointSampleList<>( numDimensions ); | |
for ( int i = 0; i < numPoints; ++i ) | |
{ | |
RealPoint point = new RealPoint( numDimensions ); | |
for ( int d = 0; d < numDimensions; ++d ) | |
point.setPosition( rnd.nextDouble() * | |
( interval.realMax( d ) - interval.realMin( d ) ) + interval.realMin( d ), d ); | |
// add a new element with a random intensity in the range 0...1 | |
elements.add( point, new UnsignedByteType( (int) (rnd.nextFloat()*255) ) ); | |
} | |
return elements; | |
} | |
import bdv.util.BdvFunctions | |
import bdv.util.BdvOptions | |
import bdv.util.BdvSource | |
import bdv.util.volatiles.SharedQueue | |
import bdv.util.volatiles.VolatileViews | |
import net.imglib2.* | |
import net.imglib2.algorithm.util.Grids | |
import net.imglib2.cache.img.* | |
import net.imglib2.img.Img | |
import net.imglib2.img.array.ArrayImgFactory | |
import net.imglib2.img.basictypeaccess.AccessFlags | |
import net.imglib2.img.basictypeaccess.array.ArrayDataAccess | |
import net.imglib2.img.cell.CellGrid | |
import net.imglib2.interpolation.neighborsearch.NearestNeighborSearchInterpolatorFactory | |
import net.imglib2.neighborsearch.NearestNeighborSearch | |
import net.imglib2.neighborsearch.NearestNeighborSearchOnKDTree | |
import net.imglib2.type.NativeType | |
import net.imglib2.type.Type | |
import net.imglib2.type.numeric.ARGBType | |
import net.imglib2.type.numeric.integer.ByteType | |
import net.imglib2.type.numeric.integer.UnsignedByteType | |
import net.imglib2.type.numeric.real.FloatType | |
import net.imglib2.util.Intervals | |
import net.imglib2.util.Util | |
import net.imglib2.view.Views | |
import java.io.IOException | |
import java.util.Random | |
import static java.lang.Math.abs | |
import static net.imglib2.cache.img.DiskCachedCellImgOptions.options | |
import ch.epfl.biop.kheops.ometiff.OMETiffPyramidizerExporter |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment