/*-
* #%L
* Fiji distribution of ImageJ for the life sciences.
* %%
* Copyright (C) 2007 - 2017 Fiji developers.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
package spim.process.fusion.export;
import ij.gui.GenericDialog;
import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mpicbg.spim.data.SpimDataException;
import mpicbg.spim.data.registration.ViewRegistration;
import mpicbg.spim.data.registration.ViewRegistrations;
import mpicbg.spim.data.registration.ViewTransform;
import mpicbg.spim.data.registration.ViewTransformAffine;
import mpicbg.spim.data.sequence.MissingViews;
import mpicbg.spim.data.sequence.SequenceDescription;
import mpicbg.spim.data.sequence.TimePoint;
import mpicbg.spim.data.sequence.TimePoints;
import mpicbg.spim.data.sequence.TimePointsPattern;
import mpicbg.spim.data.sequence.ViewDescription;
import mpicbg.spim.data.sequence.ViewId;
import mpicbg.spim.data.sequence.ViewSetup;
import mpicbg.spim.io.IOFunctions;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.type.NativeType;
import net.imglib2.type.numeric.RealType;
import spim.fiji.plugin.resave.Resave_TIFF;
import spim.fiji.plugin.resave.Resave_TIFF.Parameters;
import spim.fiji.spimdata.SpimData2;
import spim.fiji.spimdata.XmlIoSpimData2;
import spim.fiji.spimdata.boundingbox.BoundingBoxes;
import spim.fiji.spimdata.imgloaders.StackImgLoaderIJ;
import spim.fiji.spimdata.interestpoints.ViewInterestPointLists;
import spim.fiji.spimdata.interestpoints.ViewInterestPoints;
import spim.process.fusion.boundingbox.BoundingBoxGUI;
public class ExportSpimData2TIFF implements ImgExport
{
List< TimePoint > newTimepoints;
List< ViewSetup > newViewSetups;
Parameters params;
Save3dTIFF saver;
SpimData2 spimData;
public static class FileNamePattern
{
public int layoutTP = 0, layoutChannels = 0, layoutIllum = 0, layoutAngles = 0;
public String fileNamePattern;
}
@Override
public < T extends RealType< T > & NativeType< T > > boolean exportImage( final RandomAccessibleInterval<T> img, final BoundingBoxGUI bb, final TimePoint tp, final ViewSetup vs )
{
return exportImage( img, bb, tp, vs, Double.NaN, Double.NaN );
}
@Override
public < T extends RealType< T > & NativeType< T > > boolean exportImage( final RandomAccessibleInterval<T> img, final BoundingBoxGUI bb, final TimePoint tp, final ViewSetup vs, final double min, final double max )
{
// write the image
if ( !this.saver.exportImage( img, bb, tp, vs, min, max ) )
return false;
// update the registrations
final ViewRegistration vr = spimData.getViewRegistrations().getViewRegistration( new ViewId( tp.getId(), vs.getId() ) );
final double scale = bb.getDownSampling();
final AffineTransform3D m = new AffineTransform3D();
m.set( scale, 0.0f, 0.0f, bb.min( 0 ),
0.0f, scale, 0.0f, bb.min( 1 ),
0.0f, 0.0f, scale, bb.min( 2 ) );
final ViewTransform vt = new ViewTransformAffine( "fusion bounding box", m );
vr.getTransformList().clear();
vr.getTransformList().add( vt );
return true;
}
@Override
public boolean finish()
{
XmlIoSpimData2 io = new XmlIoSpimData2( "" );
try
{
io.save( spimData, new File( params.getXMLFile() ).getAbsolutePath() );
IOFunctions.println( "(" + new Date( System.currentTimeMillis() ) + "): Saved xml '" + io.lastFileName() + "'." );
// this spimdata object was not modified, we just wrote a new one
return false;
}
catch ( SpimDataException e )
{
IOFunctions.println( "(" + new Date( System.currentTimeMillis() ) + "): Could not save xml '" + io.lastFileName() + "'." );
e.printStackTrace();
return false;
}
}
@Override
public void setXMLData ( final List< TimePoint > newTimepoints, final List< ViewSetup > newViewSetups )
{
this.newTimepoints = newTimepoints;
this.newViewSetups = newViewSetups;
}
@Override
public boolean queryParameters( final SpimData2 spimData, final boolean is16bit )
{
if ( newTimepoints == null || newViewSetups == null )
{
IOFunctions.println( "new timepoints and new viewsetup list not set yet ... cannot continue" );
return false;
}
if ( Resave_TIFF.defaultPath == null )
Resave_TIFF.defaultPath = "";
this.params = Resave_TIFF.getParameters();
if ( this.params == null )
return false;
this.saver = new Save3dTIFF( new File( this.params.getXMLFile() ).getParent(), this.params.compress() );
this.saver.setImgTitler( new XMLTIFFImgTitler( newTimepoints, newViewSetups ) );
this.spimData = createSpimData2( newTimepoints, newViewSetups, params );
return true;
}
@Override
public void queryAdditionalParameters( final GenericDialog gd, final SpimData2 spimData ) {}
@Override
public boolean parseAdditionalParameters( final GenericDialog gd, final SpimData2 spimData ) { return true; }
@Override
public ImgExport newInstance() { return new ExportSpimData2TIFF(); }
@Override
public String getDescription() { return "Save as new XML Project (TIFF)"; }
protected SpimData2 createSpimData2(
final List< TimePoint > timepointsToProcess,
final List< ViewSetup > viewSetupsToProcess,
final Parameters params )
{
final FileNamePattern fnp = getFileNamePattern( timepointsToProcess, viewSetupsToProcess, params.compress() );
// Assemble a new SpimData object containing the subset of viewsetups and timepoints
final SpimData2 newSpimData = assembleSpimData2( timepointsToProcess, viewSetupsToProcess, new File( params.getXMLFile() ).getParentFile() );
final StackImgLoaderIJ imgLoader = new StackImgLoaderIJ(
new File( params.getXMLFile() ).getParentFile(),
fnp.fileNamePattern, params.getImgFactory(),
fnp.layoutTP, fnp.layoutChannels, fnp.layoutIllum, fnp.layoutAngles, null );
newSpimData.getSequenceDescription().setImgLoader( imgLoader );
return newSpimData;
}
public static FileNamePattern getFileNamePattern(
final List< TimePoint > timepoints,
final List< ViewSetup > viewSetups,
final boolean compress )
{
final FileNamePattern fnp = new FileNamePattern();
fnp.layoutTP = 0;
fnp.layoutChannels = 0;
fnp.layoutIllum = 0;
fnp.layoutAngles = 0;
fnp.fileNamePattern = "img";
if ( timepoints.size() > 1 )
{
fnp.fileNamePattern += "_TL{t}";
fnp.layoutTP = 1;
}
if ( XMLTIFFImgTitler.getAllChannels( viewSetups ).size() > 1 )
{
fnp.fileNamePattern += "_Ch{c}";
fnp.layoutChannels = 1;
}
if ( XMLTIFFImgTitler.getAllIlluminations( viewSetups ).size() > 1 )
{
fnp.fileNamePattern += "_Ill{i}";
fnp.layoutIllum = 1;
}
if ( XMLTIFFImgTitler.getAllAngles( viewSetups ).size() > 1 )
{
fnp.fileNamePattern += "_Angle{a}";
fnp.layoutAngles = 1;
}
fnp.fileNamePattern += ".tif";
if ( compress )
fnp.fileNamePattern += ".zip";
return fnp;
}
/**
* Assembles a new SpimData2 based on the timepoints and viewsetups.
* The imgloader is still not set here.
*
*/
public static SpimData2 assembleSpimData2(
final List< TimePoint > timepointsToProcess,
final List< ViewSetup > viewSetupsToProcess,
final File basePath )
{
final TimePoints timepoints;
try
{
timepoints = new TimePointsPattern( Resave_TIFF.listAllTimePoints( timepointsToProcess ) );
}
catch (ParseException e)
{
IOFunctions.println( "Automatically created list of timepoints failed to parse. This should not happen, really :) -- " + e );
IOFunctions.println( "Here is the list: " + Resave_TIFF.listAllTimePoints( timepointsToProcess ) );
e.printStackTrace();
return null;
}
final MissingViews missingViews = new MissingViews( new ArrayList< ViewId >() );
// instantiate the sequencedescription
final SequenceDescription sequenceDescription = new SequenceDescription( timepoints, viewSetupsToProcess, null, missingViews );
// assemble the viewregistrations
final Map< ViewId, ViewRegistration > regMap = new HashMap< ViewId, ViewRegistration >();
for ( final ViewDescription vDesc : sequenceDescription.getViewDescriptions().values() )
{
final ViewRegistration viewRegistration = new ViewRegistration( vDesc.getTimePointId(), vDesc.getViewSetupId() );
viewRegistration.identity();
regMap.put( viewRegistration, viewRegistration );
}
final ViewRegistrations viewRegistrations = new ViewRegistrations( regMap );
// assemble the interestpoints and a list of filenames to copy
final ViewInterestPoints viewsInterestPoints = new ViewInterestPoints( new HashMap< ViewId, ViewInterestPointLists >() );
final SpimData2 newSpimData = new SpimData2(
basePath,
sequenceDescription,
viewRegistrations,
viewsInterestPoints,
new BoundingBoxes() );
return newSpimData;
}
}