package edu.colostate.vchill; import edu.colostate.vchill.chill.ChillFieldInfo; import edu.colostate.vchill.chill.ChillMomentFieldScale; /** * Utility methods for calculating rain rate * * @author Jochen Deyke * @version 2006-03-15 */ public class RainUtil { public static final ChillMomentFieldScale scale = new ChillMomentFieldScale(ChillFieldInfo.RCOMP, java.awt.event.KeyEvent.VK_C, "mm/h", 1, 1, 0); /** * private default constructor prevents instantiation */ private RainUtil() { } public static double[] calculateRK40(final double[] dataKDP) { double[] dataRK40 = new double[dataKDP.length]; for (int gate = 0; gate < dataKDP.length; ++gate) { dataRK40[gate] = 40.5 * Math.pow(dataKDP[gate], 0.85); } return dataRK40; } public static double[] calculateRK50(final double[] dataKDP) { double[] dataRK50 = new double[dataKDP.length]; for (int gate = 0; gate < dataKDP.length; ++gate) { dataRK50[gate] = 50.7 * Math.pow(dataKDP[gate], 0.85); } return dataRK50; } public static double[] calculateRKZdr(final double[] dataKDP, final double[] dataZDR) { double[] dataRKZdr = new double[dataKDP.length]; for (int gate = 0; gate < dataKDP.length; ++gate) { dataRKZdr[gate] = 90.8 * Math.pow(dataKDP[gate], 0.93) * Math.pow(10, -0.169 * dataZDR[gate]); } return dataRKZdr; } public static double[] calculateRZZdr(final double[] dataZ, final double[] dataZDR) { double[] dataRZZdr = new double[dataZ.length]; for (int gate = 0; gate < dataZ.length; ++gate) { double gateZ = Math.pow(10, dataZ[gate] / 10); // -> linear dataRZZdr[gate] = 6.7e-3 * Math.pow(gateZ, 0.927) * Math.pow(10, -0.3433 * dataZDR[gate]); } return dataRZZdr; } public static double[] calculateRZ(final double[] dataZ) { double[] dataRZ = new double[dataZ.length]; for (int gate = 0; gate < dataZ.length; ++gate) { double gateZ = dataZ[gate]; if (gateZ > 53) gateZ = 53; //threshold gateZ = Math.pow(10, gateZ / 10); // -> linear dataRZ[gate] = Math.pow(gateZ / 300, 1 / 1.4); } return dataRZ; } public static double[] calculateCompositeRain(final double[] kdp, final double[] dbz, final double[] zdr) { double[] rk40 = RainUtil.calculateRK40(kdp); double[] rk50 = RainUtil.calculateRK50(kdp); double[] rkzdr = RainUtil.calculateRKZdr(kdp, zdr); double[] rzzdr = RainUtil.calculateRZZdr(dbz, zdr); double[] rz = RainUtil.calculateRZ(dbz); double[] rain = new double[kdp.length]; for (int i = 0; i < rain.length; ++i) { double kdpThresh = 0; double sum = kdp[i] > kdpThresh ? rk40[i] + rk50[i] + rkzdr[i] : 0; int count = kdp[i] > kdpThresh ? 3 : 0; sum += rzzdr[i] + rz[i]; count += 2; double avg = sum / count; double stdDev = Math.sqrt(( kdp[i] > kdpThresh ? ( Math.pow(rk40[i] - avg, 2) + Math.pow(rk50[i] - avg, 2) + Math.pow(rkzdr[i] - avg, 2) ) : 0 + Math.pow(rzzdr[i] - avg, 2) + Math.pow(rz[i] - avg, 2)) / count); sum = 0; count = 0; if (kdp[i] > kdpThresh) { if (Math.abs(rk40[i] - avg) < 1.5 * stdDev) { sum += rk40[i]; ++count; } if (Math.abs(rk50[i] - avg) < 1.5 * stdDev) { sum += rk50[i]; ++count; } if (Math.abs(rkzdr[i] - avg) < 1.5 * stdDev) { sum += rkzdr[i]; ++count; } } if (Math.abs(rzzdr[i] - avg) < 1.5 * stdDev) { sum += rzzdr[i]; ++count; } if (Math.abs(rz[i] - avg) < 1.5 * stdDev) { sum += rz[i]; ++count; } //if (i % 100 == 0) System.out.println("count = " + count); rain[i] = count > 0 ? sum / count : 0; } return rain; } }