/** * Set the sounding in the table * * @param sounding the sounding * @throws RemoteException Java RMI problem * @throws VisADException problem dissecting data */ private void setSounding(Field sounding) throws VisADException, RemoteException { domainData = null; // domain values Set domain = sounding.getDomainSet(); CoordinateSystem cs = domain.getCoordinateSystem(); float[][] domSamples = domain.getSamples(false); if ((cs != null)) { float[][] domFloats = Set.copyFloats(domSamples); // Must convert from the default coordinate domain system to // the domain coordinate system of the sounding. String fromUnit = sounding.getDomainUnits()[0].toString(); String toUnit = cs.getCoordinateSystemUnits()[0].toString(); if (!fromUnit.equals(toUnit) && SimpleUnit.isCompatible(fromUnit, toUnit)) { float conversionFactor = (float) SimpleUnit.getConversionFactor(fromUnit, toUnit); for (int i = 0; i < domFloats.length; i++) { for (int j = 0; j < domFloats[i].length; j++) { domFloats[i][j] = domFloats[i][j] * conversionFactor; } } } float[][] refData = cs.toReference(domFloats); domainData = new float[][] {domSamples[0], refData[0]}; } // range values RealType[] rangeComps = ((FunctionType) sounding.getType()).getRealComponents(); rangeData = sounding.getFloats(false); // wind if (rangeComps.length > 2) { transformWinds = (showUAndV && !haveUV) || (!showUAndV && haveUV); if (!transformWinds) { for (int i = 2; i < 4; i++) { columnNames[numDomainCols + i] = makeColumnName(rangeComps[i], rangeComps[i].getDefaultUnit()); } } else { RealTupleType refType = windTransform.getReference(); Unit[] refUnits = windTransform.getReferenceUnits(); for (int i = 0; i < 2; i++) { columnNames[numDomainCols + i + 2] = makeColumnName((RealType) refType.getComponent(i), refUnits[i]); } float[][] newVals = windTransform.toReference(Set.copyFloats(new float[][] {rangeData[2], rangeData[3]})); rangeData[2] = newVals[0]; rangeData[3] = newVals[1]; } } sorter.setTableModel(model); }
/** * Converts a time-series of grid-relative winds to a time-series of true (or absolute) winds. The * U and V components of true wind are {@link WesterlyWind} and {@link SoutherlyWind}, * respectively. The domain of the input {@link visad.Field} must be a temporal {@link * visad.Gridded1DSet} or a {@link visad.SingletonSet}. The range values of the input {@link * visad.Field} must be {@link visad.FlatField}s. The domains of the range {@link * visad.FlatField}s must have a manifold dimension of two or greater and they must have a * reference system which contains {@link visad.RealType#Latitude} and {@link * visad.RealType#Longitude}. The number of components in the range of the {@link * visad.FlatField}s must be two. Both components must have units convertible with {@link * #DEFAULT_SPEED_UNIT}. The first and second components are assumed to be the wind components in * the direction of increasing first and second manifold dimension indexes, respectively. The * domains of the {@link visad.FlatField}s must be equal. The {@link visad.Field} returned by this * method has the same domain as the input {@link visad.Field}. The range values of the returned * {@link visad.Field} are {@link visad.FlatField}s that have the same domain as the input {@link * visad.FlatField}s. The {@link visad.MathType} of the range of the returned {@link * visad.FlatField}s will be <code>CartesianHorizontalWind.getEarthVectorType()</code>. * * @param rel The time-series of grid-relative wind. * @return The time-series of true wind corresponding to the input. * @throws NullPointerException if <code>rel</code> is <code>null</code>. * @throws IllegalArgumentException if the input field doesn't have a time-series domain, or if * the range values aren't {@link visad.FlatField} with the same domain, or if the domain of * the {@link visad.FlatField}s doesn't have a transformation to latitude and longitude, or if * the domain is irregular or has too few points, or if the {@link visad.FlatField}s don't * have two and only two components in their range, or if the default units of the {@link * visad.FlatField}s range aren't equal. * @throws VisADException if a VisAD failure occurs. * @throws RemoteException if a Java RMI failure occurs. * @see CartesianHorizontalWind */ public static Field timeSeriesCartesianHorizontalWind(Field rel) throws VisADException, RemoteException { FunctionType outerFuncType = (FunctionType) rel.getType(); RealTupleType outerDomType = outerFuncType.getDomain(); if (!(RealType.Time.equalsExceptNameButUnits(outerDomType) || !RealType.TimeInterval.equalsExceptNameButUnits(outerDomType))) { throw new IllegalArgumentException(outerDomType.toString()); } MathType innerFuncType = outerFuncType.getRange(); if (!(innerFuncType instanceof FunctionType)) { throw new IllegalArgumentException(innerFuncType.toString()); } Field innerField = (Field) rel.getSample(0); Set innerDom = innerField.getDomainSet(); if (innerDom instanceof SingletonSet) { return rel; } else if (innerDom instanceof GriddedSet) { int[] lengths = ((GriddedSet) innerDom).getLengths(); if ((lengths[0] == 1) && (lengths[1] == 1)) { return rel; } } // account for null units, assume m/sec Unit[] rangeUnits = innerField.getDefaultRangeUnits(); if ((rangeUnits == null) || (rangeUnits[0] == null) || rangeUnits[0].isDimensionless()) { rangeUnits = CartesianHorizontalWind.getEarthVectorType().getDefaultUnits(); } FunctionType innerType = new FunctionType( ((SetType) innerDom.getType()).getDomain(), CartesianHorizontalWind.getEarthVectorType()); FlatField uvField = new FlatField(innerType, innerDom, (CoordinateSystem) null, (Set[]) null, rangeUnits); Field result = new FieldImpl(new FunctionType(outerDomType, uvField.getType()), rel.getDomainSet()); // System.out.println("making rHatField"); Field rHatField = (doNewCode ? hatFieldNew(innerDom, 0) : hatFieldOld(innerDom, 0)); // System.out.println("making sHatField"); Field sHatField = (doNewCode ? hatFieldNew(innerDom, 1) : hatFieldOld(innerDom, 1)); float[][] rHats = rHatField.getFloats(false); // ucar.unidata.util.Misc.printArray("rHats[0]", rHats[0]); // ucar.unidata.util.Misc.printArray("rHats[1]", rHats[1]); // System.out.println("\n"); float[][] sHats = sHatField.getFloats(false); // ucar.unidata.util.Misc.printArray("sHats[0]", sHats[0]); // ucar.unidata.util.Misc.printArray("sHats[1]", sHats[1]); // System.out.println("\n"); float[] us = new float[innerDom.getLength()]; float[] vs = new float[us.length]; for (int i = 0, n = rel.getLength(); i < n; i++) { if (i > 0) { innerField = (Field) rel.getSample(i); Set dom = innerField.getDomainSet(); if (!innerDom.equals(dom)) { // System.out.println("new domain"); innerDom = dom; rHatField = (doNewCode ? hatFieldNew(innerDom, 0) : hatFieldOld(innerDom, 0)); sHatField = (doNewCode ? hatFieldNew(innerDom, 1) : hatFieldOld(innerDom, 1)); rHats = rHatField.getFloats(false); sHats = sHatField.getFloats(false); /* throw new IllegalArgumentException("template=" + innerDom.toString() + "; domain=" + dom.toString()); */ } uvField = new FlatField(innerType, innerDom, (CoordinateSystem) null, (Set[]) null, rangeUnits); us = new float[innerDom.getLength()]; vs = new float[us.length]; } float[][] rsWinds = innerField.getFloats(false); float[] rWinds = rsWinds[0]; float[] sWinds = rsWinds[1]; // ucar.unidata.util.Misc.printArray("rWinds", rWinds); // System.out.println("\n"); // ucar.unidata.util.Misc.printArray("sWinds", sWinds); // System.out.println("\n"); for (int j = 0; j < us.length; j++) { us[j] = rWinds[j] * rHats[0][j] + sWinds[j] * sHats[0][j]; vs[j] = rWinds[j] * rHats[1][j] + sWinds[j] * sHats[1][j]; } // ucar.unidata.util.Misc.printArray("us", us); // System.out.println("\n"); // ucar.unidata.util.Misc.printArray("vs", vs); // System.out.println("\n"); uvField.setSamples(new float[][] {us, vs}, false); result.setSample(i, uvField, false); } return result; }
/** * Computes the output Level of Free Convection (LFC) from an (AirPressure -> MassicVolume) * buoyancy profile. * * @param datums The input data in the same order as during construction: <code>datums[0] * </code> is the input buoyancy profile. * @return The pressure at the LFC of the buoyancy profile. * @throws ClassCastException if an input data reference has the wrong type of data object. * @throws TypeException if a VisAD data object has the wrong type. * @throws VisADException if a VisAD failure occurs. * @throws RemoteException if a Java RMI failure occurs. * @throws IllegalArgumentException if the profile is not ascending. */ protected Data compute(Data[] datums) throws TypeException, VisADException, RemoteException { Field buoyProfile = (Field) datums[0]; Real lfc = noData; // default return value if (buoyProfile != null) { FunctionType funcType = (FunctionType) buoyProfile.getType(); RealTupleType domainType = funcType.getDomain(); if (!Pressure.getRealType().equalsExceptNameButUnits(domainType)) { throw new TypeException(domainType.toString()); } MathType rangeType = funcType.getRange(); Util.vetType(MassicVolume.getRealType(), buoyProfile); Set domainSet = buoyProfile.getDomainSet(); double[] pressures = domainSet.getDoubles()[0]; float[] buoys = buoyProfile.getFloats()[0]; if (pressures.length > 1) { int lastI = pressures.length - 1; boolean ascending = pressures[0] >= pressures[lastI]; Unit presUnit = domainSet.getSetUnits()[0]; int i; if (ascending) { /* * For a level of free convection to exist, the lower * buoyancy must be negative. */ for (i = 0; (i < buoys.length) && (buoys[i] >= 0); i++) ; /* * To find the level of free convection, ascend to * positive buoyancy. */ while ((++i < buoys.length) && (buoys[i] <= 0)) ; if (i < buoys.length) { lfc = interpolatePres(pressures[i], buoys[i], pressures[i - 1], buoys[i - 1], presUnit); } } else { /* * For a level of free convection to exist, the lower * buoyancy must be negative. */ for (i = lastI; (i >= 0) && (buoys[i] >= 0); i--) ; /* * To find the level of free convection, ascend to * positive buoyancy. */ while ((--i >= 0) && (buoys[i] <= 0)) ; if (i >= 0) { lfc = interpolatePres(pressures[i], buoys[i], pressures[i + 1], buoys[i + 1], presUnit); } } } } return lfc; }
/** * Computes the output property. A {@link java.beans.PropertyChangeEvent} is fired for the output * property if it differs from the previous value. * * @throws VisADException if a VisAD failure occurs. * @throws RemoteException if a Java RMI exception occurs. */ void clock() throws VisADException, RemoteException { Set domainSet = buoyProfile.getDomainSet(); Real oldLfc; Real newLfc; double[] pressures = domainSet.getDoubles()[0]; float[] buoys = buoyProfile.getFloats()[0]; /* Eliminate non-finite pressures and buoyancies. */ int n = 0; for (int i = 0; i < pressures.length; i++) { if ((pressures[i] != pressures[i]) || (buoys[i] != buoys[i])) { n++; } } if (n > 0) { double[] tmpPres = new double[pressures.length - n]; float[] tmpBuoy = new float[tmpPres.length]; n = 0; for (int i = 0; i < pressures.length; i++) { if ((pressures[i] != pressures[i]) || (buoys[i] != buoys[i])) { continue; } tmpPres[n] = pressures[i]; tmpBuoy[n] = buoys[i]; n++; } pressures = tmpPres; buoys = tmpBuoy; } if (pressures.length <= 1) { newLfc = missingLfc; } else { Unit presUnit = domainSet.getSetUnits()[0]; boolean ascending = pressures[0] > pressures[1]; if (!ascending) { /* * The profile is descending. Make the temporary value arrays * ascending. */ for (int i = 0, j = pressures.length; i < pressures.length / 2; i++) { --j; double pres = pressures[i]; pressures[i] = pressures[j]; pressures[j] = pres; float buoy = buoys[i]; buoys[i] = buoys[j]; buoys[j] = buoy; } } /* * Descend from the top to positive buoyancy. */ int i = buoys.length; while ((--i >= 0) && (buoys[i] <= 0)) ; if (i < 0) { /* * There is no positively buoyant region. */ newLfc = missingLfc; } else { /* * Descend to first non-positive buoyant region. */ while ((--i >= 0) && (buoys[i] > 0)) ; if (i < 0) { /* * There is no non-positive buoyant region. */ newLfc = missingLfc; } else { /* * Interpolate the LFC. */ double pressure = pressures[i + 1] / Math.exp( buoys[i + 1] * (Math.log(pressures[i] / pressures[i + 1]) / (buoys[i] - buoys[i + 1]))); newLfc = new Real((RealType) missingLfc.getType(), pressure, presUnit); } } } synchronized (this) { oldLfc = lfc; lfc = newLfc; } firePropertyChange(OUTPUT_PROPERTY_NAME, oldLfc, newLfc); }