/*- * #%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.fiji.plugin.resave; import ij.plugin.PlugIn; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import mpicbg.spim.data.SpimDataException; import mpicbg.spim.data.generic.sequence.BasicViewSetup; import mpicbg.spim.data.registration.ViewRegistration; import mpicbg.spim.data.registration.ViewRegistrations; 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.Dimensions; import spim.fiji.ImgLib2Temp.Pair; import spim.fiji.ImgLib2Temp.ValuePair; import spim.fiji.plugin.Toggle_Cluster_Options; import spim.fiji.plugin.queryXML.LoadParseQueryXML; import spim.fiji.plugin.resave.Generic_Resave_HDF5.Parameters; import spim.fiji.spimdata.SpimData2; import spim.fiji.spimdata.interestpoints.ViewInterestPointLists; import spim.fiji.spimdata.interestpoints.ViewInterestPoints; import bdv.export.ExportMipmapInfo; import bdv.export.ProgressWriter; import bdv.export.ProposeMipmaps; import bdv.img.hdf5.Hdf5ImageLoader; import bdv.img.hdf5.Partition; public class Resave_HDF5 implements PlugIn { public static void main( final String[] args ) { new Resave_HDF5().run( null ); } @Override public void run( final String arg0 ) { boolean rememberClusterProcessing = Toggle_Cluster_Options.displayClusterProcessing; Toggle_Cluster_Options.displayClusterProcessing = false; final LoadParseQueryXML xml = new LoadParseQueryXML(); if ( !xml.queryXML( "Resaving as HDF5", "Resave", true, true, true, true ) ) return; Toggle_Cluster_Options.displayClusterProcessing = rememberClusterProcessing; // load all dimensions if they are not known (required for estimating the mipmap layout) if ( loadDimensions( xml.getData(), xml.getViewSetupsToProcess() ) ) { // save the XML again with the dimensions loaded SpimData2.saveXML( xml.getData(), xml.getXMLFileName(), xml.getClusterExtension() ); } final Map< Integer, ExportMipmapInfo > perSetupExportMipmapInfo = proposeMipmaps( xml.getViewSetupsToProcess() ); Generic_Resave_HDF5.lastExportPath = LoadParseQueryXML.defaultXMLfilename; final int firstviewSetupId = xml.getData().getSequenceDescription().getViewSetupsOrdered().get( 0 ).getId(); final Parameters params = Generic_Resave_HDF5.getParameters( perSetupExportMipmapInfo.get( firstviewSetupId ), true, true ); if ( params == null ) return; LoadParseQueryXML.defaultXMLfilename = params.getSeqFile().toString(); final ProgressWriter progressWriter = new ProgressWriterIJ(); progressWriter.out().println( "starting export..." ); final SpimData2 data = xml.getData(); final List< ViewId > viewIds = SpimData2.getAllViewIdsSorted( data, xml.getViewSetupsToProcess(), xml.getTimePointsToProcess() ); // write hdf5 Generic_Resave_HDF5.writeHDF5( reduceSpimData2( data, viewIds ), params, progressWriter ); // write xml sequence description if ( !params.onlyRunSingleJob || params.jobId == 0 ) { try { final Pair< SpimData2, List< String > > result = createXMLObject( data, viewIds, params, progressWriter, false ); xml.getIO().save( result.getA(), params.seqFile.getAbsolutePath() ); progressWriter.setProgress( 0.95 ); // copy the interest points if they exist Resave_TIFF.copyInterestPoints( xml.getData().getBasePath(), params.getSeqFile().getParentFile(), result.getB() ); } catch ( SpimDataException e ) { IOFunctions.println( "(" + new Date( System.currentTimeMillis() ) + "): Could not save xml '" + params.getSeqFile() + "': " + e ); throw new RuntimeException( e ); } finally { IOFunctions.println( "(" + new Date( System.currentTimeMillis() ) + "): Saved xml '" + params.getSeqFile() + "'." ); } } progressWriter.setProgress( 1.0 ); progressWriter.out().println( "done" ); } public static Map< Integer, ExportMipmapInfo > proposeMipmaps( final List< ? extends BasicViewSetup > viewsetups ) { final HashMap< Integer, ExportMipmapInfo > perSetupExportMipmapInfo = new HashMap< Integer, ExportMipmapInfo >(); for ( final BasicViewSetup setup : viewsetups ) perSetupExportMipmapInfo.put( setup.getId(), ProposeMipmaps.proposeMipmaps( setup ) ); return perSetupExportMipmapInfo; } public static boolean loadDimensions( final SpimData2 spimData, final List< ViewSetup > viewsetups ) { boolean loadedDimensions = false; for ( final ViewSetup vs : viewsetups ) { if ( vs.getSize() == null ) { IOFunctions.println( "Dimensions of viewsetup " + vs.getId() + " unknown. Loading them ... " ); for ( final TimePoint t : spimData.getSequenceDescription().getTimePoints().getTimePointsOrdered() ) { final ViewDescription vd = spimData.getSequenceDescription().getViewDescription( t.getId(), vs.getId() ); if ( vd.isPresent() ) { Dimensions dim = spimData.getSequenceDescription().getImgLoader().getSetupImgLoader( vd.getViewSetupId() ).getImageSize( vd.getTimePointId() ); IOFunctions.println( "Dimensions: " + dim.dimension( 0 ) + "x" + dim.dimension( 1 ) + "x" + dim.dimension( 2 ) + ", loaded from tp:" + t.getId() + " vs: " + vs.getId() ); vs.setSize( dim ); loadedDimensions = true; break; } else { IOFunctions.println( "ViewSetup: " + vs.getId() + " not present in timepoint: " + t.getId() ); } } } } return loadedDimensions; } /** * Reduces a given SpimData2 to the subset of timepoints and viewsetups as selected by the user, including the original imgloader. * * @param oldSpimData * @return */ public static SpimData2 reduceSpimData2( final SpimData2 oldSpimData, final List< ViewId > viewIds ) { final TimePoints timepoints; try { timepoints = new TimePointsPattern( Resave_TIFF.listAllTimePoints( SpimData2.getAllTimePointsSorted( oldSpimData, viewIds ) ) ); } 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( SpimData2.getAllTimePointsSorted( oldSpimData, viewIds ) ) ); e.printStackTrace(); return null; } final List< ViewSetup > viewSetupsToProcess = SpimData2.getAllViewSetupsSorted( oldSpimData, viewIds ); // a hashset for all viewsetups that remain final Set< ViewId > views = new HashSet< ViewId >(); for ( final ViewId viewId : viewIds ) views.add( new ViewId( viewId.getTimePointId(), viewId.getViewSetupId() ) ); final MissingViews oldMissingViews = oldSpimData.getSequenceDescription().getMissingViews(); final HashSet< ViewId > missingViews = new HashSet< ViewId >(); if( oldMissingViews != null && oldMissingViews.getMissingViews() != null ) for ( final ViewId id : oldMissingViews.getMissingViews() ) if ( views.contains( id ) ) missingViews.add( id ); // add the new missing views!!! for ( final TimePoint t : timepoints.getTimePointsOrdered() ) for ( final ViewSetup v : viewSetupsToProcess ) { final ViewId viewId = new ViewId( t.getId(), v.getId() ); if ( !views.contains( viewId ) ) missingViews.add( viewId ); } // instantiate the sequencedescription final SequenceDescription sequenceDescription = new SequenceDescription( timepoints, viewSetupsToProcess, oldSpimData.getSequenceDescription().getImgLoader(), new MissingViews( missingViews ) ); // re-assemble the registrations final Map< ViewId, ViewRegistration > oldRegMap = oldSpimData.getViewRegistrations().getViewRegistrations(); final Map< ViewId, ViewRegistration > newRegMap = new HashMap< ViewId, ViewRegistration >(); for ( final ViewId viewId : oldRegMap.keySet() ) if ( views.contains( viewId ) ) newRegMap.put( viewId, oldRegMap.get( viewId ) ); final ViewRegistrations viewRegistrations = new ViewRegistrations( newRegMap ); // re-assemble the interestpoints and a list of filenames to copy final Map< ViewId, ViewInterestPointLists > oldInterestPoints = oldSpimData.getViewInterestPoints().getViewInterestPoints(); final Map< ViewId, ViewInterestPointLists > newInterestPoints = new HashMap< ViewId, ViewInterestPointLists >(); for ( final ViewId viewId : oldInterestPoints.keySet() ) if ( views.contains( viewId ) ) newInterestPoints.put( viewId, oldInterestPoints.get( viewId ) ); final ViewInterestPoints viewsInterestPoints = new ViewInterestPoints( newInterestPoints ); final SpimData2 newSpimData = new SpimData2( oldSpimData.getBasePath(), sequenceDescription, viewRegistrations, viewsInterestPoints, oldSpimData.getBoundingBoxes() ); return newSpimData; } public static Pair< SpimData2, List< String > > createXMLObject( final SpimData2 spimData, final List< ViewId > viewIds, final Parameters params, final ProgressWriter progressWriter, final boolean useRightAway ) { // Re-assemble a new SpimData object containing the subset of viewsetups and timepoints selected final List< String > filesToCopy = new ArrayList< String >(); final SpimData2 newSpimData = Resave_TIFF.assemblePartialSpimData2( spimData, viewIds, params.seqFile.getParentFile(), filesToCopy ); final ArrayList< Partition > partitions = Generic_Resave_HDF5.getPartitions( newSpimData, params ); final Hdf5ImageLoader hdf5Loader; if ( useRightAway ) hdf5Loader = new Hdf5ImageLoader( params.hdf5File, partitions, newSpimData.getSequenceDescription(), true ); else hdf5Loader = new Hdf5ImageLoader( params.hdf5File, partitions, null, false ); newSpimData.getSequenceDescription().setImgLoader( hdf5Loader ); newSpimData.setBasePath( params.seqFile.getParentFile() ); return new ValuePair< SpimData2, List< String > >( newSpimData, filesToCopy ); } }