/** * TransposeSlices -- read a Granite file; generate a new one such that each * slice is transposed. At the present time, this only works if * the slices are square. It could work on rectangular slices * by building a new DataBlock and using option of re-ordering * the indices, but that is more work than I need right now. * * IT ASSUMES DataSource is POINT-ORDERED! * * Arguments: xfdlfile - input data set * outNameBase - a string to be used as the prefix for the * 2 output files; .bin and .xfdl * * 28 Sept 2011 (derived from SubFile.java) * rdb * ------------------ * History */ import edu.unh.sdb.common.*; import edu.unh.sdb.datasource.*; import java.io.*; import java.nio.*; import java.util.*; public class TransposeSlices { //----------------- class variables ----------------------------- static String inName = null; static String baseName = null; public static void main(String arg[]) throws FileNotFoundException, IOException { readArgs( arg ); DataSource dataSource = DataSource.create( "input", inName ); dataSource.activate(); System.err.println( "Transposing data source " + inName + "\n" + " in bounds " + dataSource.getBounds () ); DataBlock db = getData( dataSource ); System.err.println( " to float, out bounds " + db.getBounds() ); writeFile( db, baseName ); } //------------------- getData ------------------------------- private static DataBlock getData( DataSource inDS ) { int dim = inDS.dim(); ISBounds dsb = inDS.getBounds(); DataBlock db = inDS.subblock( dsb ); return db; } //-------------- writeFile ------------------------------------ private static void writeFile( DataBlock block, String base ) throws IOException { ISBounds bnds = block.getBounds(); int lower[] = bnds.copyLowerArray(); int upper[] = bnds.copyUpperArray(); String fileName = base + ".bin"; DataOutputStream out = new DataOutputStream( new FileOutputStream( fileName )); transposeSlices( block ); float data[] = block.getFloats(); writeData( out, data ); out.close(); //------------------------------------------------------- // Now write xfdl file //----------------------------- PrintWriter pw = new PrintWriter( new FileOutputStream( base + ".xfdl" )); pw.println( "" ); pw.println( "" ); pw.println( "" ); /** Granite doesn't seem to handle files with non-zero lower bounds, so following output (which should be ok) doesn't work for ( int i = 0; i < lower.length; i++ ) { pw.println( "" ); } *******************************/ // Instead just always have bounds go from 0 to size-1 for ( int i = 0; i < lower.length; i++ ) { pw.println( "" ); } // Now do the fieldNames and types: RecordDescriptor rd = block.getRecordDescriptor (); String[] fieldNames = rd.getFieldNames (); String[] fieldTypes = rd.getFieldTypes (); for (int i = 0; i < fieldNames.length; i++) pw.println ( " " ); // and finish up pw.println( "" ); pw.close(); } //----------------- transposeSlices ---------------------------------- /** * Write the data to the file. */ static void transposeSlices( DataBlock db ) { ISBounds isb = db.getBounds(); int[] lb = isb.getLowerArray(); int[] ub = isb.getUpperArray(); int nSlices = ub[ 0 ] - lb[ 0 ] + 1; int nRows = ub[ 1 ] - lb[ 1 ] + 1; int nCols = ub[ 2 ] - lb[ 2 ] + 1; if ( nCols != nRows ) { System.err.println( "Can only transpose square slices!" ); System.exit( -1 ); } float[] vals = db.getFloats(); //float[] newVals = new float[ values.length ]; int nAttr = db.getNumAttributes(); int sSize = nRows * nCols * nAttr; int rSize = nCols * nAttr; int cSize = nAttr; float srcVal; for ( int s = 0; s < nSlices; s++ ) { for ( int r = 0; r < nRows; r++ ) { for( int c = r+1; c < nCols; c++ ) { int srcIndex = s * sSize + r * rSize + c * cSize; int dstIndex = s * sSize + c * rSize + r * cSize; for ( int a = 0; a < nAttr; a++ ) { srcVal = vals[ srcIndex + a ]; vals[ srcIndex + a ] = vals[ dstIndex + a ]; vals[ dstIndex + a ] = srcVal; } } } } db.setFloatsByPoint( vals ); } //----------------- writeData --------------------------------------- /** * Write the data to the file. */ static void writeData( DataOutputStream out, float[] data ) throws IOException { ByteBuffer bb = ByteBuffer.allocate( data.length * 4 ); FloatBuffer fb = bb.asFloatBuffer(); fb.put( data ); byte[] bbData = bb.array(); out.write( bbData ); } //---------------------- openDataSource ---------------------------- // a little utility function to read the descriptor file. // private static DataSource openDataSource( String dsName, String fileName ) { DataSource ds = null; try { ds = DataSource.create( dsName, inName ); } catch ( Exception ex ) { System.err.println( "Open error: " + ex.getMessage() ); System.exit( -1 ); } return ds; } //--------------- usage ----------------------------------- static void usage() { PrintStream out = System.out; // should pass in output stream out.println( "Usage: java TransposSlices infdl outPrefix" ); out.println( " infdl - xfdl file describing the input DataSource" ); out.println( " outPrefix - prefix for output file names" ); out.println(); out.println( "NOTES: output DataSource always float"); out.println( " Data must be in point order"); out.println( " Slices must be square!"); } //-------------- readArgs -------------------------------- // static void readArgs( String[] args ) { if ( args.length == 0 ) { usage(); System.exit( 0 ); } for ( int iarg = 0; iarg < args.length; iarg++ ) { String sarg = args[ iarg ]; if ( inName == null ) // check for file name inName = args[ iarg ]; else if ( baseName == null ) baseName = args[ iarg ]; } } }