nl_tokens: This reports how well different compression schemes would work on the specific data . Should be renamed
pl_tokens: public static void calcScaleOffset ( GribData . Bean bean1 , Formatter f ) { float [ ] data ; try { data = bean1 . readData ( ) ; } catch ( IOException e ) { f . format ( "IOException %s" , e . getMessage ( ) ) ; return ; } int npoints = data . length ; // we always use unsigned packed // "If the packed values are intended to be interpreted as signed/unsigned integers" // http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html int nbits = bean1 . getNBits ( ) ; int width = ( 2 << nbits - 1 ) - 2 ; // unsigned int missing_value = ( 2 << nbits - 1 ) - 1 ; // all ones - reserved for missing value // int width2 = (2 << (nbits-1)) - 1;  // signed f . format ( " nbits = %d%n" , nbits ) ; f . format ( " npoints = %d%n" , npoints ) ; f . format ( " width = %d (0x%s) %n" , width , Long . toHexString ( width ) ) ; f . format ( " scale = %g %n" , bean1 . getScale ( ) ) ; f . format ( " resolution = %g %n" , bean1 . getScale ( ) / 2 ) ; f . format ( " range = %f %n%n" , bean1 . getMaximum ( ) - bean1 . getMinimum ( ) ) ; float dataMin = Float . MAX_VALUE ; float dataMax = - Float . MAX_VALUE ; for ( float fd : data ) { if ( Float . isNaN ( fd ) ) continue ; dataMin = Math . <mask> ( dataMin , fd ) ; dataMax = Math . max ( dataMax , fd ) ; } f . format ( "           actual    computed%n" ) ; f . format ( " dataMin = %8f %8f%n" , dataMin , bean1 . getMinimum ( ) ) ; f . format ( " dataMax = %8f %8f%n" , dataMax , bean1 . getMaximum ( ) ) ; f . format ( " actual range = %f%n" , ( dataMax - dataMin ) ) ; // scale_factor =(dataMax - dataMin) / (2^n - 1) // add_offset = dataMin + 2^(n-1) * scale_factor double scale_factor = ( dataMax - dataMin ) / width ; // float add_offset = dataMin + width2 * scale_factor / 2; // signed double add_offset = dataMin ; // unsigned f . format ( " scale_factor = %g%n" , scale_factor ) ; f . format ( " add_offset = %g%n" , add_offset ) ; // unpacked_data_value = packed_data_value * scale_factor + add_offset // packed_data_value = nint((unpacked_data_value - add_offset) / scale_factor) ByteBuffer bb = ByteBuffer . allocate ( 4 * npoints ) ; IntBuffer intBuffer = bb . asIntBuffer ( ) ; double diffMax = - Double . MAX_VALUE ; double diffTotal = 0 ; double diffTotal2 = 0 ; for ( float fd : data ) { if ( Float . isNaN ( fd ) ) { intBuffer . put ( missing_value ) ; continue ; } // otherwise pack it int packed_data = ( int ) Math . round ( ( fd - add_offset ) / scale_factor ) ; // nint((unpacked_data_value - add_offset) / scale_factor) double unpacked_data = packed_data * scale_factor + add_offset ; double diff = Math . abs ( fd - unpacked_data ) ; if ( diff > scale_factor / 2 ) f . format ( "***   org=%g, packed_data=%d unpacked=%g diff = %g%n" , fd , packed_data , unpacked_data , diff ) ; diffMax = Math . max ( diffMax , diff ) ; diffTotal += diff ; diffTotal2 += diff * diff ; intBuffer . put ( packed_data ) ; } f . format ( "%n max_diff = %g%n" , diffMax ) ; f . format ( " avg_diff = %g%n" , diffTotal / data . length ) ; // Math.sqrt( sumsq/n - avg * avg) double mean = diffTotal / npoints ; double var = ( diffTotal2 / npoints - mean * mean ) ; f . format ( " std_diff = %g%n" , Math . sqrt ( var ) ) ; f . format ( "%nCompression%n" ) ; f . format ( " number of values = %d%n" , npoints ) ; f . format ( " uncompressed as floats = %d%n" , npoints * 4 ) ; int packedBitsLen = npoints * nbits / 8 ; f . format ( " uncompressed packed bits = %d%n" , packedBitsLen ) ; f . format ( " grib data length = %d%n" , bean1 . getDataLength ( ) ) ; f . format ( " grib msg length = %d%n" , bean1 . getMsgLength ( ) ) ; byte [ ] bdata = convertToBytes ( data ) ; byte [ ] scaledData = bb . array ( ) ; //////////////////////////////////////////// f . format ( "%ndeflate (float)%n" ) ; Deflater deflater = new Deflater ( ) ; deflater . setInput ( bdata ) ; deflater . finish ( ) ; int compressedSize = deflater . deflate ( new byte [ 10 * npoints ] ) ; deflater . end ( ) ; f . format ( " compressedSize = %d%n" , compressedSize ) ; f . format ( " ratio floats / size = %f%n" , ( float ) ( npoints * 4 ) / compressedSize ) ; f . format ( " ratio packed bits / size = %f%n" , ( float ) packedBitsLen / compressedSize ) ; f . format ( " ratio size / grib = %f%n" , ( float ) compressedSize / bean1 . getMsgLength ( ) ) ; ///////////////////////////////////////////////////////// f . format ( "%ndeflate (scaled ints)%n" ) ; deflater = new Deflater ( ) ; deflater . setInput ( scaledData ) ; deflater . finish ( ) ; compressedSize = deflater . deflate ( new byte [ 10 * npoints ] ) ; deflater . end ( ) ; f . format ( " compressedSize = %d%n" , compressedSize ) ; f . format ( " ratio floats / size = %f%n" , ( float ) ( npoints * 4 ) / compressedSize ) ; f . format ( " ratio packed bits / size = %f%n" , ( float ) packedBitsLen / compressedSize ) ; f . format ( " ratio size / grib = %f%n" , ( float ) compressedSize / bean1 . getMsgLength ( ) ) ; }