Fiji MVR (Multiview Reconstruction)

This software is for registering and fusing the datasets from two views. It was originally developed for OpenSPIM-like setups but works well for diSPIM data as well.

See homepage at http://fiji.sc/Multiview-Reconstruction.

As of April 2015 the MVR plugin allows for direct importing of Micro-Manager datasets. Previously the Micro-Manager plugin's export function was used (it is still required for MIPAV GenerateFusion).

Fiji MVR scripts

This script was used during the 2018 EMBO Practical Course for Light sheet microscopy in Dresden to roughly align two views collected on the ct-dSPIM:

#@File (label="Freshly loaded BDV XML File Location") xml_file
 
/** 
 *  Simple script to deskew, flip and move a DiSPIM dataset
 *  
 *  Olivier BURRI, Jon Daniels
 *  EMBO Lightsheet Course 2018
 *  
 *  INPUT: XML file which contains two angles named 0 and 90
 *  
 *  This will apply the transformations to the XML file and reopen the multiview applications
 *  
 *  Last modification: August 8 2018
 */
import groovy.util.XmlSlurper
import ij.IJ
 
def meta = new XmlSlurper().parse( xml_file )
//def size = meta.SpimData.SequenceDescription.ViewSetups.ViewSetup.sizexml_file
def size = meta.SequenceDescription.ViewSetups.ViewSetup.size[0] as String
 
def dimensions = size.tokenize(" ");
def width  = dimensions[0] as double
def height = dimensions[1] as double
def depth  = dimensions[2] as double
 
println("Width: "+width)
println("Height: "+height)
println("Depth: "+depth)
 
def deskew = "1.0, 0.0, -1.0, 0.0, "+
			 "0.0, 1.0, 0.0, 0.0, "+
			 "0.0, 0.0, 1.0, 0.0"
 
println(deskew)
 
def flip  =  "0.0, 0.0, -1.0, 0.0, "+
			 "0.0, -1.0, 0.0, 0.0, "+
			 "-1.0, 0.0, 0.0, 0.0"
 
def trans =  "1.0, 0.0, 0.0, "+(height/2)+", "+
			 "0.0, 1.0, 0.0, "+(width)+", "+
			 "0.0, 0.0, 1.0, "+depth
 
// Return to calibration only, if necessary
IJ.run("Apply Transformations", "select=["+xml_file.getAbsolutePath()+"] "+
							 "apply_to_angle=[All angles] apply_to_channel=[All channels] apply_to_illumination=[All illuminations] apply_to_tile=[All tiles] apply_to_timepoint=[All Timepoints] "+
							 "transformation=[Identity (no transformation)] "+
							 "apply=[Calibration (removes any existing transforms)] "+ 
							 "same_transformation_for_all_angles");
 
// Apply deskew to all angles
IJ.run("Apply Transformations", "select=["+xml_file.getAbsolutePath()+"] "+
							 "apply_to_angle=[All angles] apply_to_channel=[All channels] apply_to_illumination=[All illuminations] apply_to_tile=[All tiles] apply_to_timepoint=[All Timepoints] "+
							 "transformation=Affine apply=[Current view transformations (appends to current transforms)] "+
							 "same_transformation_for_all_angles "+
							 "timepoint_0_channel_0_illumination_0_all_angles=["+deskew+"]");
 
// Apply Flip to angle 90
IJ.run("Apply Transformations", "select=["+xml_file.getAbsolutePath()+"] "+
							 "apply_to_angle=[Single angle (Select from List)] apply_to_channel=[All channels] apply_to_illumination=[All illuminations] apply_to_tile=[All tiles] apply_to_timepoint=[All Timepoints] "+
							 "processing_angle=[angle 90] "+
							 "transformation=Affine apply=[Current view transformations (appends to current transforms)] "+
							 ""+
							 "timepoint_0_channel_0_illumination_0_angle_90=["+flip+"]");
 
// Aplly Rough translation to angle 90
IJ.run("Apply Transformations", "select=["+xml_file.getAbsolutePath()+"] "+ 
							 "apply_to_angle=[Single angle (Select from List)] apply_to_channel=[All channels] apply_to_illumination=[All illuminations] apply_to_tile=[All tiles] apply_to_timepoint=[All Timepoints] "+
							 "processing_angle=[angle 90] "+
							 "transformation=Affine apply=[Current view transformations (appends to current transforms)] "+
							 ""+
							 "timepoint_0_channel_0_illumination_0_angle_90=["+trans+"]");
 
// Open MultiView Application
IJ.run("MultiView Reconstruction Application", "select_xml=["+xml_file.getAbsolutePath()+"]");

This script did some other pre-processing:

 
#@File main_folder (label="Main Folder", style="directory")
 
// Iterate and find all files
import static groovy.io.FileType.FILES
import ij.IJ
import ij.plugin.ChannelSplitter
import ij.io.Opener
 
import groovyx.gpars.GParsPool
 
 
def save_folder = new File(main_folder, "exploded_channels_views")
save_folder.mkdir()
 
 
def opener = new Opener()
// Find all files.
def all_files = []
main_folder.eachFile(FILES) { file ->
    if(file.getName().endsWith(".tif") && !file.getName().contains("_1")) {
    	all_files.add(file)
    	//println(file)
    }
}
 
Collections.reverse(all_files)  // reverse order
 
 
//all_files = all_files.take(1)
 
//GParsPool.withPool(10) {
	//all_files.eachParallel{ file ->
	all_files.each { file ->
	    //def temp_image = opener.openTiff(file.getParent()+File.separator, file.getName())
 
		println("starting " + file)
 
	    def temp_image = IJ.openImage(file.getAbsolutePath())
 
	    def images = ChannelSplitter.split(temp_image)
 
	    // 0 is ch1 view 1
	    // 1 is ch1 view 2
	    // 2 is ch2 view 1
	    // 3 is ch2 view 2
 
	    //resave all
	    def image_name = file.name.take(file.name.lastIndexOf('.'))
	    IJ.saveAsTiff(images[0], new File(save_folder, sprintf("%s_Ch%d_Angle%d.tif",image_name, 1, 0)).getAbsolutePath())
	    IJ.saveAsTiff(images[1], new File(save_folder, sprintf("%s_Ch%d_Angle%d.tif",image_name, 1, 90)).getAbsolutePath())
	    IJ.saveAsTiff(images[2], new File(save_folder, sprintf("%s_Ch%d_Angle%d.tif",image_name, 2, 0)).getAbsolutePath())
	    IJ.saveAsTiff(images[3], new File(save_folder, sprintf("%s_Ch%d_Angle%d.tif",image_name, 2, 90)).getAbsolutePath())
	    images.each{it.close()}
 
	    temp_image.close()	
 
	    println("finished " + file)
	}
//}