package org.autoplot.binarydatasource; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; import java.util.Map; import org.autoplot.datasource.AbstractDataSourceFormat; import org.das2.qds.buffer.BufferDataSet; import org.das2.util.monitor.ProgressMonitor; import org.das2.qds.QDataSet; import org.das2.qds.QubeDataSetIterator; import org.das2.qds.SemanticOps; import org.autoplot.datasource.URISplit; import org.das2.qds.DataSetOps; import org.das2.qds.MutablePropertyDataSet; /** * Format data to binary file. * @author jbf */ public class BinaryDataSourceFormat extends AbstractDataSourceFormat { /** * copy the dataset into a DoubleBuffer by wrapping a DoubleBuffer with * a DoubleBufferDataSet, then copy the data into the dataset. * @param data * @param mon * @return byteBuffer view of the dataset. */ private ByteBuffer formatRank2( QDataSet data, ProgressMonitor mon, Map params ) { QDataSet dep0 = (QDataSet) data.property(QDataSet.DEPEND_0); //dep1 is ignored. //QDataSet dep1 = (QDataSet) data.property(QDataSet.DEPEND_1); String type= params.get("type"); if ( type==null ) type= "double"; String dep0Type= params.get("depend0Type" ); if ( dep0Type==null ) dep0Type= "double"; int dep0Len= ( dep0==null ? 0 : 1 ); int typeSize= BufferDataSet.byteCount(type); int dep0TypeSize= BufferDataSet.byteCount(dep0Type); int recSize= dep0Len*dep0TypeSize + data.length(0) * typeSize; int size= data.length() * recSize; ByteBuffer result= ByteBuffer.allocate(size); result.order( "big".equals( params.get("byteOrder") ) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN ); BufferDataSet ddata= BufferDataSet.makeDataSet( 2, recSize, dep0Len * dep0TypeSize, data.length(), data.length(0), 1, 1, result, type ); /*Double ddata= new Double( 2, recSize, dep0Len * typeSize, data.length(), data.length(0), 1, result );*/ QubeDataSetIterator it= new QubeDataSetIterator(data); while ( it.hasNext() ) { it.next(); it.putValue( ddata, it.getValue(data) ); } if ( dep0!=null && dep0.rank()==1 ) { BufferDataSet ddep0= BufferDataSet.makeDataSet( 1, recSize, 0, dep0.length(), 1, 1, 1, result, dep0Type ); it= new QubeDataSetIterator(dep0); while ( it.hasNext() ) { it.next(); it.putValue( ddep0, it.getValue(dep0) ); } } return result; } private ByteBuffer formatRank1( QDataSet data, ProgressMonitor mon, Map params ) { QDataSet dep0 = (QDataSet) data.property(QDataSet.DEPEND_0); String type= params.get("type"); if ( type==null ) type= "double"; String dep0Type= params.get("depend0Type" ); if ( dep0Type==null ) dep0Type= "double"; int dep0Len= ( dep0==null ? 0 : 1 ); int typeSize= BufferDataSet.byteCount(type); int dep0TypeSize= BufferDataSet.byteCount(dep0Type); int recSize= dep0Len*dep0TypeSize + typeSize; int size= data.length() * recSize ; ByteBuffer result= ByteBuffer.allocate(size); result.order( "big".equals( params.get("byteOrder") ) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN ); BufferDataSet ddata= BufferDataSet.makeDataSet( 1, recSize, dep0Len*dep0TypeSize, data.length(), 1, 1, 1, result, type ); QubeDataSetIterator it= new QubeDataSetIterator(data); while ( it.hasNext() ) { it.next(); it.putValue( ddata, it.getValue(data) ); } if ( dep0!=null ) { BufferDataSet ddep0= BufferDataSet.makeDataSet( 1, recSize, 0, data.length(), 1, 1, 1, result, dep0Type ); it= new QubeDataSetIterator(dep0); while ( it.hasNext() ) { it.next(); it.putValue( ddep0, it.getValue(dep0) ); } } return result; } @Override public void formatData( String uri, QDataSet data, ProgressMonitor mon) throws IOException { super.setUri(uri); super.maybeMkdirs(); String doDep= getParam("doDep", ""); if ( doDep.length()>0 && doDep.toUpperCase().charAt(0)=='F' ) { MutablePropertyDataSet mpds= DataSetOps.makePropertiesMutable(data); mpds.putProperty( QDataSet.DEPEND_0, null ); mpds.putProperty( QDataSet.DEPEND_1, null ); mpds.putProperty( QDataSet.BUNDLE_1, null ); data= mpds; } URISplit split= URISplit.parse(uri); java.util.Map params= URISplit.parseParams(split.params); ByteBuffer result; switch (data.rank()) { case 2: result= formatRank2( data, mon, params ); break; case 1: result= formatRank1( data, mon, params ); break; default: throw new IllegalArgumentException("rank not supported"); } File outFile= new File( split.resourceUri ); try (WritableByteChannel channel = Channels.newChannel( new FileOutputStream( outFile ) )) { channel.write(result); } } @Override public boolean canFormat(QDataSet ds) { return ds.rank()<3 && ( ! ( ds.rank()==0 || SemanticOps.isJoin(ds) ) ); } @Override public String getDescription() { return "Binary Table"; } }