Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Code Block
package nl.wldelft.util.io;

import nl.wldelft.fews.system.plugin.transformationmodule.function.implementation.stagedischarge.LookupTableOffset;

import java.util.Arrays;

public class FloatArrayUtils {
    // *******  DoubleArrayUtils and FloatArrayUtils should BE THE SAME *********
    // use Intellij replace float, double with preserve case for easy conversion

    public static final float[] EMPTY_ARRAY = new float[0];

    private FloatArrayUtils() {
    }

    public static boolean equals(float[] a, int aPos, int aLength, float[] b, int bPos, int bLength) {
        if (a == null && b == null) return true;
        if (a == null || b == null) return false;

        checkArg("a", a, aPos, aLength);
        checkArg("b", b, bPos, bLength);

        if (aLength != bLength) return false;
        if (a == b && aPos == bPos) return true;

        for (int i = aPos, j = bPos, n = aPos + aLength; i < n; i++, j++) {
            if (a[i] != b[j] && Float.floatToIntBits(a[i]) != Float.floatToIntBits(b[j])) return false;
        }

        return true;
    }

    public static boolean contains(float[] array, float value) {
        return indexOf(array, value) != -1;
    }

    public static boolean containsNaN(float[] array) {
        return indexOfNaN(array) != -1;
    }

    public static boolean containsNonNaN(float[] array) {
        return indexOfNonNaN(array) != -1;
    }

    public static boolean containsInfinite(float[] array) {
        if (array == null) return false;

        for (int i = 0; i < array.length; i++) {
            if (Float.isInfinite(array[i])) return true;
        }

        return false;
    }

    public static int indexOf(float[] array, float value) {
        return indexOf(array, 0, array.length, value);
    }

    public static int indexOf(float[] array, int pos, int length, float value) {
        checkArg("array", array, pos, length);

        if (Float.isNaN(value)) {
            for (int i = pos, n = pos + length; i < n; i++) {
                if (Float.isNaN(array[i])) return i;
            }
        } else {
            for (int i = pos, n = pos + length; i < n; i++) {
                if (array[i] == value) return i;
            }
        }

        return -1;
    }

    public static int indexOfNaN(float[] array) {
        return indexOfNaN(array, 0, array.length);
    }

    public static int indexOfNaN(float[] array, int pos, int length) {
        checkArg("array", array, pos, length);

        for (int i = pos, n = pos + length; i < n; i++) {
            if (Float.isNaN(array[i])) return i;
        }

        return -1;
    }

    public static int indexOfNonNaN(float[] array) {
        return indexOfNonNaN(array, 0, array.length);
    }

    public static int indexOfNonNaN(float[] array, int pos, int length) {
        checkArg("array", array, pos, length);
        for (int i = pos, n = pos + length; i < n; i++) {
            if (!Float.isNaN(array[i])) return i;
        }

        return -1;
    }

    public static int binarySearchClosest(float[] sortedArray, float value) {
        if (sortedArray.length == 0) return -1;
        if (sortedArray.length == 1) return 0;
        int res = Arrays.binarySearch(sortedArray, value);
        if (res >= 0) return res;
        res = -(res + 1);
        if (res == sortedArray.length) return sortedArray.length - 1;
        if (res == 0) return 0;
        float low = sortedArray[res - 1];
        float high = sortedArray[res];
        if (value - low < high - value) return res - 1;
        return res;
    }

    public static int count(float[] array, float value) {
        int res = 0;
        if (Float.isNaN(value)) {
            for (int i = 0; i < array.length; i++) {
                if (Float.isNaN(array[i])) res++;
            }
        } else {
            for (int i = 0; i < array.length; i++) {
                if (array[i] == value) res++;
            }
        }
        return res;
    }

    /**
     * Reverse the order of the values in the array.
     * <p/>
     * [0,1,2,3] -> [3,2,1,0]
     *
     * @param array
     */
    public static void reverseOrder(float[] array) {
        if (array == null)
            throw new IllegalArgumentException("array == null");

        if (array.length == 1) return;

        int halfLength = array.length / 2;
        int lastIndex = array.length - 1;
        for (int i = 0; i < halfLength; i++) {
            float f1 = array[i];
            array[i] = array[lastIndex - i];
            array[lastIndex - i] = f1;
        }

    }

    public static void replace(float[] array, float oldValue, float newValue) {
        if (array == null)
            throw new IllegalArgumentException("array == null");

        if (Float.isNaN(oldValue)) {
            replaceNaN(array, newValue);
            return;
        }

        if (oldValue == newValue) return;
        for (int i = 0; i < array.length; i++) {
            if (array[i] != oldValue) continue;
            array[i] = newValue;
        }
    }


    public static void replaceNaN(float[] array, float newValue) {
        if (array == null)
            throw new IllegalArgumentException("array == null");
        if (Float.floatToRawIntBits(newValue) == Float.floatToIntBits(Float.NaN)) return;
        for (int i = 0; i < array.length; i++) {
            if (!Float.isNaN(array[i])) continue;
            array[i] = newValue;
        }
    }

    public static void replace(float[] array, float[] oldValues, float newValue) {
        if (array == null)
            throw new IllegalArgumentException("array == null");
        if (oldValues == null)
            throw new IllegalArgumentException("oldValues == null");

        for (int i = 0; i < array.length; i++) {
            if (contains(oldValues, array[i])) {
                array[i] = newValue;
            }
        }
    }

    public static void replace(float[] array, float minValue,
                               float maxValue, float newValue) {
        for (int i = 0; i < array.length; i++) {
            if (minValue <= array[i] && array[i] <= maxValue) {
                array[i] = newValue;
            }
        }
    }

    public static float min(float[] array) {
        return min(array, 0, array.length);
    }

    public static float min(float[] array, int pos, int length) {
        float res = Float.POSITIVE_INFINITY;
        for (int i = pos, n = pos + length; i < n; i++) {
            float v = array[i];
            if (v < res) res = v;
        }

        if (res == Float.POSITIVE_INFINITY) return Float.NaN;
        return res;
    }

    public static float max(float[] array) {
        return max(array, 0, array.length);
    }

    public static float max(float[] array, int pos, int length) {
        checkArg("array", array, pos, length);
        float res = Float.NEGATIVE_INFINITY;
        for (int i = pos, n = pos + length; i < n; i++) {
            float v = array[i];
            if (v > res) res = v;
        }
        if (res == Float.NEGATIVE_INFINITY) return Float.NaN;
        return res;
    }

    public static float maxSkipNaN(float[] array) {
        return maxSkipNaN(array, 0, array.length);
    }

    public static float maxSkipNaN(float[] array, int pos, int length) {
        checkArg("array", array, pos, length);
        float res = Float.NEGATIVE_INFINITY;
        for (int i = pos, n = pos + length; i < n; i++) {
            float v = array[i];
            if (Float.isNaN(v)) continue;
            if (v > res) res = v;
        }
        if (res == Float.NEGATIVE_INFINITY) return Float.NaN;
        return res;
    }

    public static float sum(float[] array) {
        return sum(array, 0, array.length);
    }

    public static float sum(float[] array, int pos, int length) {
        checkArg("array", array, pos, length);
        if (length == 0) return 0f;
        float res = array[pos];
        for (int i = pos + 1, n = pos + length; i < n; i++) {
            res += array[i];
        }
        return res;
    }

    public static float sumSkipNaN(float[] array) {
        return sumSkipNaN(array, 0, array.length);
    }

    public static float sumSkipNaN(float[] array, int pos, int length) {
        checkArg("array", array, pos, length);
        if (length == 0) return 0f;
        float res = 0;
        for (int i = pos, n = pos + length; i < n; i++) {
            float v = array[i];
            if (Float.isNaN(v)) continue;
            res += array[i];
        }
        return res;
    }

    public static float mean(float[] array) {
        return mean(array, 0, array.length);
    }

    public static float mean(float[] array, int beginIndex, int length) {
        if (length == 0) return Float.NaN;
        return sum(array, beginIndex, length) / length;
    }

    public static float meanSkipNaN(float[] array) {
        return meanSkipNaN(array, 0, array.length);
    }

    public static float meanSkipNaN(float[] array, int pos, int length) {
        checkArg("array", array, pos, length);
        float res = 0;
        int count = 0;

        for (int i = pos, n = pos + length; i < n; i++) {
            float v = array[i];
            if (Float.isNaN(v)) continue;
            res += v;
            count++;
        }

        if (count == 0) return Float.NaN;

        return res / count;
    }


    public static boolean isAscending(float[] array) {
        return getFirstNonAscendingIndex(array) == -1;
    }

    public static int getFirstNonAscendingIndex(float[] array) {
        if (array.length <= 1) return -1;

        float lastValue = array[0];
        for (int i = 1; i < array.length; i++) {
            float v = array[i];
            if (v <= lastValue) return i;
            lastValue = v;
        }

        return -1;
    }

    public static float[] select(float[] array, int[] indices) {
        if (indices.length == 0) return FloatArrayUtils.EMPTY_ARRAY;

        float[] res = new float[indices.length];

        for (int i = 0; i < res.length; i++) {
            res[i] = array[indices[i]];
        }

        return res;
    }

    public static long getInterpolatedValueY(float[] xs, long[] ys, float x) {
        if (xs == null)
            throw new IllegalArgumentException("xs == null");

        if (ys == null)
            throw new IllegalArgumentException("ys == null");

        if (xs.length != ys.length)
            throw new IllegalArgumentException("xs.length != ys.length");

        assert isAscending(xs);

        int i = Arrays.binarySearch(xs, x);
        if (i >= 0) return ys[i];
        int insertionPoint = -(i + 1);
        if (insertionPoint == 0) return ys[0];
        if (insertionPoint == xs.length) return ys[ys.length - 1];
        float x1 = xs[insertionPoint - 1];
        float x2 = xs[insertionPoint];
        float y1 = ys[insertionPoint - 1];
        float y2 = ys[insertionPoint];
        return (long) (y1 + (x - x1) / (x2 - x1) * (y2 - y1));
    }

    public static float getInterpolatedValueY(float[] xs, float[] ys, float x) {
        return getInterpolatedValueY(xs, ys, x, true);
    }

    /**
     * Lookup x value in array xs and find corresponding y value in ys. Use linear interpolation
     * for calculation of y.
     *
     * @param xs                 X lookup array
     * @param ys                 Y lookup array
     * @param x                  X lookup value
     * @param allowExtrapolation Option to allow conversion of values outside the xs array. When true then values
     *                           are mapped to either the minimum or maximum values in the ys array. When false the values outside the
     *                           xs range are mapped to NAN.
     * @return
     */
    public static float getInterpolatedValueY(float[] xs, float[] ys, float x, boolean allowExtrapolation) {

        if (xs == null)
            throw new IllegalArgumentException("xs == null");

        if (ys == null)
            throw new IllegalArgumentException("ys == null");

        if (xs.length != ys.length)
            throw new IllegalArgumentException("xs.length != ys.length");

        assert isAscending(xs);

        int i = Arrays.binarySearch(xs, x);
        if (i >= 0) return ys[i];
        int insertionPoint = -(i + 1);
        if (insertionPoint == 0) {
            if (allowExtrapolation) return ys[0];
            else return Float.NaN;
        }
        if (insertionPoint == xs.length) {
            if (allowExtrapolation) return ys[ys.length - 1];
            else return Float.NaN;
        }
        float x1 = xs[insertionPoint - 1];
        float x2 = xs[insertionPoint];
        float y1 = ys[insertionPoint - 1];
        float y2 = ys[insertionPoint];
        return y1 + (x - x1) / (x2 - x1) * (y2 - y1);
    }

    public static float interpolate(float[] hs, float[] qs, float h, boolean allowExtrapolation, boolean useLogarithmicInterpolation, boolean searchClosestPoint) {
        return interpolate(hs, qs, h, allowExtrapolation, useLogarithmicInterpolation, searchClosestPoint, LookupTableOffset.getEmptyLookupOffset(), LookupTableOffset.getEmptyLookupOffset());
    }

    /**
     * Looks up the given input value h in the given array hs and returns the corresponding value from the given array qs.
     * The values in the lookup array hs must be in ascending order. Each value hs[n] must have a corresponding value qs[n].
     * If h is between two consecutive values in the lookup array hs, then the corresponding qs values will be interpolated
     * to get a q value for the given h value.
     *
     * Options for interpolation/extrapolation:
     * If useLogarithmicInterpolation is true, then interpolation and extrapolation is logarithmic. Otherwise interpolation
     * and extrapolation is linear.
     * If searchClosestPoint is true, then returns the qs value that corresponds to the hs value that is closest to the input h.
     * If allowExtrapolation is false, then does not extrapolate, but returns the qs value that corresponds to the hs value
     * that is closest to the input h (either the minimum hs value or the maximum hs value).
     *
     * @param hs
     * @param qs
     * @param h
     * @param allowExtrapolation
     * @param useLogarithmicInterpolation
     * @param searchClosestPoint
     * @param hOffset to use this method without offsets, pass in LookupTableOffset.getDummyLookupOffset().
     * @param qOffset to use this method without offsets, pass in LookupTableOffset.getDummyLookupOffset().
     * @return interpolated value.
     */
    public static float interpolate(float[] hs, float[] qs, float h, boolean allowExtrapolation, boolean useLogarithmicInterpolation, boolean searchClosestPoint, LookupTableOffset hOffset, LookupTableOffset qOffset) {

        if (hs == null) throw new IllegalArgumentException("hs == null");

        if (qs == null) throw new IllegalArgumentException("qs == null");

        if (hs.length != qs.length) throw new IllegalArgumentException("hs.length != qs.length");

        int i = Arrays.binarySearch(hs, h);
        if (i >= 0) return qs[i];//h value in hs array, return corresponding qs value.

        //h value not in hs array, so either interpolate or extrapolate to get q value.
        int insertionPoint = -(i + 1);
        double qu = 0;
        double ql = 0;
        double hu = 0;
        double hl = 0;
        double a;
        if (insertionPoint == 0) {
            if (allowExtrapolation) {
                qu = qs[1];
                ql = qs[0];
                hu = hs[1];
                hl = hs[0];
            } else {
                return returnWithOffset(qs[0], qOffset);
            }
        } else if (insertionPoint == hs.length) {
            if (allowExtrapolation) {
                qu = qs[qs.length - 1];
                ql = qs[qs.length - 2];
                hu = hs[qs.length - 1];
                hl = hs[qs.length - 2];
            } else {
                return returnWithOffset(qs[qs.length - 1], qOffset);
            }
        } else {
            //interpolate.
            qu = qs[insertionPoint];
            ql = qs[insertionPoint - 1];
            hu = hs[insertionPoint];
            hl = hs[insertionPoint - 1];
        }
        double h1 = h;

        //aply offsets
        float hoffset = hOffset.getOffset((float) h1);
        float qoffset = qOffset.getOffset((float) hl);

        h1 -= hoffset;
        qu -= qoffset;
        ql -= qoffset;
        hu -= hoffset;
        hl -= hoffset;

        if (useLogarithmicInterpolation) {
            if (hu == 0) hu = 0.0001;
            if (hl == 0) hl = 0.0001;
            if (qu == 0) qu = 0.0001;
            if (ql == 0) ql = 0.0001;
            
            qu = Math.log(qu);
            ql = Math.log(ql);
            hu = Math.log(hu);
            hl = Math.log(hl);
            h1 = Math.log(h1);
        }

        if (searchClosestPoint) {
            if (Math.abs(h - hu) > Math.abs(h - hl)) {
                return returnWithOffset((float) ql, qOffset);
            } else {
                return returnWithOffset((float) qu, qOffset);
            }
        }

        a = (qu - ql) / (hu - hl);
        double result = ql + a * (h1 - hl);
        result = useLogarithmicInterpolation ? Math.exp(result) : result;
        return returnWithOffset((float) result,qOffset);
    }

    private static float returnWithOffset(float value,LookupTableOffset lookupTableOffset) {
        return value + lookupTableOffset.getOffset(value);
    }

    public static ArraySegmentIterator createRangeSegmentIterator(final float[] array, final int pos, final int length, final FloatRange range) {
        checkArg("array", array, pos, length);
        final int startPos = range.indexOfInRange(array, pos, length);
        if (startPos == -1) return ArraySegmentIterator.EMPTY;

        return new ArraySegmentIterator() {
            private int currentPos = startPos;
            private int currentLength = 0;

            @Override
            public int next() {
                if (currentPos == -1) return -1;
                if (currentLength != 0) {
                    currentPos = range.indexOfInRange(array, currentPos + currentLength, pos + length - currentPos - currentLength);
                    if (currentPos == -1) return -1;
                }

                int outOfRangePos = range.indexOfOutOfRange(array, currentPos, pos + length - currentPos);
                if (outOfRangePos == -1) {
                    currentLength = pos + length - currentPos;
                    int res = currentPos;
                    currentPos = -1;
                    return res;
                }
                currentLength = outOfRangePos - currentPos;
                return currentPos;
            }

            @Override
            public int length() {
                return currentLength;
            }
        };
    }

    public static Float[] box(float[] array) {
        if (array == null)
            throw new IllegalArgumentException("array == null");

        Float[] res = new Float[array.length];
        for (int i = 0; i < array.length; i++) {
            res[i] = new Float(array[i]);
        }

        return res;
    }

    public static float[] unbox(Float[] array) {
        if (array == null)
            throw new IllegalArgumentException("array == null");

        float[] res = new float[array.length];
        for (int i = 0; i < array.length; i++) {
            res[i] = array[i].floatValue();
        }

        return res;
    }

    public static float[] unbox(Float[] array, float nullValue) {
        if (array == null)
            throw new IllegalArgumentException("array == null");

        float[] res = new float[array.length];
        for (int i = 0; i < array.length; i++) {
            Float value = array[i];
            res[i] = value == null ? nullValue : value.floatValue();
        }

        return res;
    }

    public static void checkArg(String arrayName, float[] array, int pos, int length) {
        if (array == null)
            throw new IllegalArgumentException(arrayName + " == null");

        if (pos < 0)
            throw new IllegalArgumentException(arrayName + "pos < 0 " + pos + " < 0");

        if (length < 0)
            throw new IllegalArgumentException(arrayName + "length < 0 " + length + " < 0");

        if (pos + length > array.length)
            throw new IllegalArgumentException(arrayName + "pos + " + arrayName + "length > " + arrayName + ".length "
                    + pos + " + " + length + " > " + array.length);
    }

    public static float[] resize(float[] array, int size) {
        if (array == null)
            throw new IllegalArgumentException("array == null");

        if (size < 0)
            throw new IllegalArgumentException("size < 0");

        if (size == 0) return EMPTY_ARRAY;

        int oldSize = array.length;

        if (oldSize == size) return array;

        float[] res = new float[size];
        int preservedSize = size < oldSize ? size : oldSize;
        if (preservedSize > 0) System.arraycopy(array, 0, res, 0, preservedSize);
        return res;
    }

    public static void copy(float[] src, float[] dest) {
        if (src == null)
            throw new IllegalArgumentException("src == null");

        if (dest == null)
util.BinaryUtils;
import nl.wldelft.util.ByteArrayUtils;
import nl.wldelft.util.DateUtils;
import nl.wldelft.util.FloatArrayUtils;
import nl.wldelft.util.IOUtils;
import nl.wldelft.util.NumberType;
import nl.wldelft.util.ShortArrayUtils;
import nl.wldelft.util.TextUtils;
import nl.wldelft.util.coverage.Geometry;
import nl.wldelft.util.coverage.GridUtils;
import nl.wldelft.util.coverage.RegularGridGeometry;
import nl.wldelft.util.geodatum.GeoDatum;
import nl.wldelft.util.geodatum.GeoPoint;
import nl.wldelft.util.geodatum.Wgs1984Point;
import nl.wldelft.util.timeseries.DefaultTimeSeriesHeader;
import nl.wldelft.util.timeseries.TimeSeriesContentHandler;
import org.apache.log4j.Logger;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.nio.ByteOrder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class MosaicRadarTimeSeriesParser implements BinaryParser<TimeSeriesContentHandler> {
    private static final Logger log = Logger.getLogger(MosaicRadarTimeSeriesParser.class);

    private Geometry geometry = null;

    private int nx1 = 0;
    private int ny1 = 0;
    private int nz1 = 0;
    private String projection = null;
    private int scale = 0;
    private int trulat1 = 0;
    private int trulat2 = 0;
    private int trulon = 0;
    private float nwLon = 0.0F;
    private float nwLat = 0.0F;
    private float xyScale = 0.0F;
    private float dx1 = 0.0F;
    private float dy2 = 0.0F;
    private int iBbMode = 0;
    private String varName = null;
    private String varUnit = null;
    private int varScale = 0;
    private int imissing = 0;
    private int nradars = 0;
    private String[] radarNames = null;
    private float dxyScale = 0.0F;


    private int size = 0;

    private long time = Long.MIN_VALUE;

    private float[] values = FloatArrayUtils.EMPTY_ARRAY;
    private byte[] byteBuffer = ByteArrayUtils.EMPTY_ARRAY;
    private short[] shortBuffer = ShortArrayUtils.EMPTY_ARRAY;

    private LittleEndianDataInputStream is = null;
    private TimeSeriesContentHandler contentHandler = null;

    @Override
    public void parse(BufferedInputStream inputStream, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {
        this.contentHandler = contentHandler;
        this.is = new LittleEndianDataInputStream(inputStream);
        parseHeader();
        if (contentHandler.isCurrentTimeSeriesHeaderForCurrentTimeRejected()) return;

        if (values.length != geometry.size()) {
            values = new float[geometry.size()];
            byteBuffer = new byte[geometry.size() * NumberType.INT16_SIZE];
            shortBuffer = new short[geometry.size()];
        }

        if (values.length != geometry.size()) {
            values = new float[geometry.size()];
            byteBuffer throw= new IllegalArgumentException("dest == null");

byte[geometry.size() * NumberType.INT16_SIZE];
           int srcLengthshortBuffer = new src.lengthshort[geometry.size()];
        int dstLength = dest.length;}

        if// (srcLengthread != dstLength)
       all the complete grid at once for optimal performance
     throw new IllegalArgumentException("src.length != dst.length");
 is.readFully(byteBuffer);
        SystemBinaryUtils.arraycopycopy(srcbyteBuffer, 0, dest size * NumberType.INT16_SIZE, shortBuffer, 0, srcLength size, ByteOrder.LITTLE_ENDIAN);

    }

    public static float[] subArray(float[] array, int beginIndex) {
        return subArray(array, beginIndex, array.length);if (is.available() > 0) log.error("Too many bytes available in " + virtualFileName);

    }

    publicfor static float[] subArray(float[] array, int beginIndex, int endIndex(int i = 0; i < values.length; i++) {

            ifshort (arrayshortValue == null) {shortBuffer[i];
            throw new IllegalArgumentException("anArray == null")values[i] = shortValue == imissing ? Float.NaN : shortValue / varScale;
        }


        // content handle expect intthe lengthrows =from endIndextop -to beginIndex;
bottom
        float[] res = new float[length];
GridUtils.reverseOrderRows(values, geometry.getCols(), geometry.getRows());
        SystemcontentHandler.arraycopy(array, beginIndex, res, 0, lengthsetCoverageValues(values);

        return rescontentHandler.applyCurrentFields();
    }

    public static float[] join(float[] array1, float[] array2) {
@SuppressWarnings({"OverlyLongMethod"})
    private void parseHeader() throws IOException {
        DefaultTimeSeriesHeader header = ifnew (array1 == null && array2 == null) return nullDefaultTimeSeriesHeader();

        int year = is.readInt();
        ifint (array1month == null) return array2.clone is.readInt();
        ifint (array2day == null) return array1.cloneis.readInt();

        float[]int reshour = new float[array1.length + array2.length];

is.readInt();
        System.arraycopy(array1, 0, res, 0, array1.lengthint minute = is.readInt();
        System.arraycopy(array2, 0, res, array1.length, array2.lengthint second = is.readInt();

        return resCalendar gmtCalendar = new GregorianCalendar(DateUtils.GMT);
     }

    public static float[] join(float[][] arrays) {   gmtCalendar.set(year, month - 1, day, hour, minute, second);
        if (arrays == null)
contentHandler.setTime(gmtCalendar.getTimeInMillis());

        nx1    throw new IllegalArgumentException("arrays == null"= is.readInt();

        float[] resny1 = new float[countElements(arrays)];
is.readInt();
        intnz1 j = 0is.readInt();

        projection for= IOUtils.readText(int i = 0; i < arrays.length; i++) {
    is, 4).trim();
        scale = is.readInt();
        float[] arraytrulat1 = arrays[i]is.readInt();
        trulat2    if (array == null) continue= is.readInt();
        trulon =   Systemis.arraycopy(array, 0, res, j, array.lengthreadInt();
        nwLon = (float) is.readInt() j += array.length/ (float) scale;
        }

nwLat = (float)      return resis.readInt() / (float) scale;
    }

    publicxyScale static float[][] split(float[] array, int maxArrayLength) {= is.readInt();
        ifint (arraydx1int == nullis.readInt();
        int dy2int   throw new IllegalArgumentException("array == null"= is.readInt();

        if (array.length <dxyScale = maxArrayLength) return new float[][]{array}(float) is.readInt();

        intdx1 arrayCount= = array.length(float) dx1int / maxArrayLengthdxyScale;
        intdy2 restArrayLength= = array.length % maxArrayLength(float) dy2int / dxyScale;
        if (restArrayLength != 0) arrayCount++IOUtils.skipFully(is, 4 * nz1);
        float[][] resiBbMode = new float[arrayCount][]is.readInt();

        for (int i = 0, n = array.length / maxArrayLength; i < n; i++) {
    IOUtils.skipFully(is, 4 * 9);
        IOUtils.skipFully(is, 4);
        float[] subArrayvarName = new float[maxArrayLength]IOUtils.readText(is, 20);

        varUnit =   SystemIOUtils.arraycopyreadText(array, i * maxArrayLength, subArray, 0, maxArrayLength);
    is, 6);

        varScale = is.readInt();
        res[i]imissing = subArrayis.readInt();
        nradars  }
= is.readInt();
        if (restArrayLengthnradars !=> 0) {
            float[] subArrayradarNames = new floatString[restArrayLengthnradars];
            System.arraycopy(array,for (arrayCountint - 1) * maxArrayLength, subArray, 0, restArrayLength);
            res[arrayCount - 1] = subArray;
        }

   i = 0; i < nradars; i++) {
     return res;
    }

    public static floatradarNames[i] = ensureCapacity(float[] array, int minCapacity) {
IOUtils.readText(is, 4).trim();
         if (array == null)}
        }

      throw new IllegalArgumentException("arraysize == null") nx1 * ny1 * nz1;


        if (array.length >= minCapacity) return array;
GeoPoint firstCellCenter = new Wgs1984Point(nwLat - dy2 / 2, nwLon + dx1 / 2);
        int newCapacitygeometry = minCapacity * 3 / 2 + 1;
RegularGridGeometry.create(GeoDatum.WGS_1984, firstCellCenter, dx1, dy2, ny1, nx1);

        if (newCapacity < minCapacity) newCapacity = minCapacity;

    contentHandler.setGeometry(geometry);
        contentHandler.setValueResolution(1.0f / varScale);
    float[] res = new float[newCapacity];
 header.setParameterId(varName);
        Systemheader.arraycopy(array, 0, res, 0, array.length);setUnit(varUnit);
        contentHandler.setTimeSeriesHeader(header);

        return resdebugHeader();
    }


    publicprivate staticvoid int countElements(float[][] arraysdebugHeader() {
        if (arrays == null)
    (!log.isDebugEnabled()) return;
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        throw new IllegalArgumentException("arrays == null"dateFormat.setTimeZone(DateUtils.GMT);

        intList<String> resheader = 0new ArrayList<String>(10);

        for (int i = 0; i < arrays.length; i++) {
       header.add(dateFormat.format(new Date(time)));
        header.add("nx1 = " + nx1);
     float[] array = arrays[i];
     header.add("ny1 = " + ny1);
        if (array == null) continueheader.add("nz1 = " + nz1);
        header.add("size = "  res += array.lengthsize);
        }

    header.add("projection = " + projection);
    return res;
    }

    /**
header.add("scale = " + scale);
      * The java array.clone is very slow header.add("trulat1 = " + trulat1);
     */
    public static float[] copyOf(float[] array) {header.add("trulat2 = " + trulat2);
        return copyOfRange(array, 0, array.lengthheader.add("trulon = " + trulon);
    }

    public static float[] copyOfRange(float[] array, int pos, int length) {header.add("nw_lon = " + nwLon);
        return copyOfRange(array, pos, length, lengthheader.add("nw_lat = " + nwLat);
    }

    public static float[] copyOfRange(float[] array, int pos, int length, int newCapacity) {header.add("xy_scale = " + xyScale);
        if (newCapacityheader.add("dx1 == 0)" return EMPTY_ARRAY+ dx1);
        float[] res = new float[newCapacity]header.add("dy2 = " + dy2);
        arraycopy(array, pos, res, 0, lengthheader.add("i_bb_mode = " + iBbMode);
        return res header.add("varName = " + varName);
    }

    /**
     * 4 times faster than java 6  {@link System#arraycopy(Object, int, Object, int, int)} for small arrays
     */
    public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) {header.add("varUnit = " + varUnit);
        header.add("var_scale = " + varScale);
        header.add("imissing = " + imissing);
        header.add("nradars = " + nradars);
        if (lengthradarNames <!= 10null) {
            for (int i = srcPos, j = destPos, n = srcPos + length = 0; i < nradarNames.length; i++, j++) {
                dest[j] String radarName = srcradarNames[i];
            }
    header.add("radarName = " + radarName);
            }
   else {
    }
        Systemheader.arraycopyadd(src, srcPos, dest, destPos, length);"dxyScale = " + dxyScale);

        }log.debug(TextUtils.join(header, '\n'));
    }
}