/** * CleanFile -- read a Granite file; generate a new one that forces all * data values in the file to a specified min/max range. * All values < min are set to min; all > max are set to max * Arguments: xfdlfile - input data set * outNameBase - a string to be used as the prefix for the * 2 output files; .bin and .xfdl * -min val - minimum allowed value (optional) * -max val - max allowed value (optional) * * * 23 Sept 14 derived from SubFileFloats * rdb * ------------------ * History */ import edu.unh.sdb.common.*; import edu.unh.sdb.datasource.*; import java.io.*; import java.nio.*; import java.util.*; public class CleanFile { //----------------- class variables ----------------------------- static String inName = null; static String baseName = null; static float minVal = Float.MIN_VALUE; static float maxVal = Float.MAX_VALUE; static int numMinClamp = 0; static int numMaxClamp = 0; static float minOver = Float.POSITIVE_INFINITY; static float maxOver = Float.NEGATIVE_INFINITY; static float minUnder = Float.POSITIVE_INFINITY; static float maxUnder = Float.NEGATIVE_INFINITY; static boolean clampValues = false; static boolean outputLE = false; public static void main(String arg[]) throws FileNotFoundException, IOException { readArgs( arg ); DataSource dataSource = DataSource.create( "input", inName ); dataSource.activate(); System.err.println( "Converting data source " + inName + "\n" + " in bounds " + dataSource.getBounds () ); DataBlock db = getData( dataSource ); System.err.println( " to float, out bounds " + db.getBounds() ); writeFile( db, baseName ); if ( numMinClamp > 0 ) { System.err.println( "minClamps: " + numMinClamp + " from " + minUnder + " to " + maxUnder ); } if ( numMaxClamp > 0 ) { System.err.println( "maxClamps: " + numMaxClamp + " from " + minOver + " to " + maxOver ); } } //------------------- 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 )); 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(); } //----------------- 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(); if ( clampValues ) { // clamp values < min and greater than max for ( int i = 0; i < data.length; i++ ) { if ( data[ i ] < minVal ) { numMinClamp++; if ( data[ i ] > maxUnder ) maxUnder = data[ i ]; if ( data[ i ] < minUnder ) minUnder = data[ i ]; data[i] = minVal; } else if ( data[ i ] > maxVal ) { numMaxClamp++; if ( data[ i ] > maxOver ) maxOver = data[ i ]; if ( data[ i ] < minOver ) minOver = data[ i ]; data[i] = maxVal; } } } fb.put( data ); byte[] bbData = bb.array(); if ( outputLE ) swapBytes( bbData ); out.write( bbData ); } //----------------- swapBytes ----------------------------------------- /** * */ static void swapBytes( byte[] data ) { byte temp; for ( int i = 0; i < data.length; i += 4 ) { temp = data[ i + 3 ]; data[ i + 3 ] = data[ i ]; data[ i ] = temp; temp = data[ i + 2 ]; data[ i + 2 ] = data[ i + 1 ]; data[ i + 1 ] = temp; } } //---------------------- 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 CleanFile infdl outPrefix [-min v1] [-max v2]" ); out.println( " infdl - xfdl file describing the input DataSource" ); out.println( " outPrefix - prefix for output file names" ); out.println(); out.println( "-le write the binary output data as little endian" ); out.println( "-min, -max: optional values for clamping input values" ); out.println( ""); out.println( "NOTE: output DataSource always float; so min/max"); out.println( " can be used to convert an int/short ds to floats"); out.println( "NOTE: This isn't likely to make sense for multi-attr"); out.println( " data sources; should specify an attribute index."); } //-------------- readArgs -------------------------------- // static void readArgs( String[] args ) { if ( args.length == 0 ) { usage(); System.exit( 0 ); } ArrayList intArgs = new ArrayList(); for ( int iarg = 0; iarg < args.length; iarg++ ) { String sarg = args[ iarg ]; if ( sarg.equalsIgnoreCase( "-le" )) outputLE = true; else if ( sarg.equalsIgnoreCase( "-min" )) { minVal = getArg( args, ++iarg, Float.MIN_VALUE ); clampValues = true; } else if ( sarg.equalsIgnoreCase( "-max" )) { maxVal = getArg( args, ++iarg, Float.MAX_VALUE ); clampValues = true; } else if ( inName == null ) // check for file name inName = args[ iarg ]; else if ( baseName == null ) baseName = args[ iarg ]; else // read bounds arguments intArgs.add( getArg( args, iarg, 0 )); } } //---------------------- getArg( String[], int, int ) ----------------- /** * This is a utility method for accessing one of the command line * string arguments and converting it to an int. It accepts the * entire array of arguments in String form, an integer indicating * which is to be converted to an int and a default value to be * returned if this argument was not on the command line, or if * the specified String is not a valid integer representation. */ public static int getArg( String[ ] args, int which, int defaultVal ) { try { return Integer.parseInt( args[ which ] ); } catch ( ArrayIndexOutOfBoundsException oob ) { // If there is no args[ which ] element, Java "throws" an exception. // This code "catches" the exception and handles it gracefull. // In this case, it is not an error. The parameter is optional // and there is a specified default value that is returned. } catch ( NumberFormatException nfe ) { // If the string is not a valid representation of an integer // (such as 4Qd3), Integer.parseInt throws a NumberFormatException // Again, this code catches the exception, gives an error message // and uses the default value. System.err.println( "Error: improper command line argument " + which + " = " + args[ which ] + ". It should be an integer; using default value: " + defaultVal ); } return defaultVal; } //---------------------- getArg( String[], int, float ) ----------------- /** * float version of getArg */ public static float getArg( String[ ] args, int which, float defaultVal ) { try { return Float.parseFloat( args[ which ] ); } catch ( ArrayIndexOutOfBoundsException oob ) { } catch ( NumberFormatException nfe ) { System.err.println( "Error: improper command line argument " + which + " = " + args[ which ] + ". It should be an float; using default value: " + defaultVal ); } return defaultVal; } //---------------------- getArg( String[], int, String ) ----------------- /** * String version of getArg */ public static String getArg( String[ ] args, int which, String defaultVal ) { try { return args[ which ]; } catch ( ArrayIndexOutOfBoundsException oob ) { } return defaultVal; } }