Issue #2260 Switch poessounding to NSharp.

Change-Id: Ib1d067727ab6db11c20de308dce34d6752e79e78

Former-commit-id: 4e83b721a46cea5af56fd2444ba4bf22813604e9
This commit is contained in:
Ben Steffensmeier 2013-08-15 16:28:50 -05:00
parent 32a0b19a38
commit 74b0b57f4b
14 changed files with 650 additions and 287 deletions

View file

@ -23,7 +23,12 @@ Require-Bundle: org.eclipse.core.runtime,
com.raytheon.uf.common.topo;bundle-version="1.12.1174",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.uf.viz.d2d.ui;bundle-version="1.12.1174",
com.raytheon.viz.core.graphing;bundle-version="1.12.1174"
com.raytheon.viz.core.graphing;bundle-version="1.12.1174",
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
com.raytheon.viz.pointdata;bundle-version="1.12.1174",
javax.measure;bundle-version="1.0.0",
com.raytheon.uf.common.sounding;bundle-version="1.12.1174",
com.raytheon.uf.common.wxmath;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.uf.viz.d2d.nsharp,

View file

@ -1,5 +1,6 @@
com.raytheon.uf.viz.d2d.nsharp.rsc.BufruaNSharpResourceData
com.raytheon.uf.viz.d2d.nsharp.rsc.GribNSharpResourceData
com.raytheon.uf.viz.d2d.nsharp.rsc.MdlSndNSharpResourceData
com.raytheon.uf.viz.d2d.nsharp.rsc.PoesSndNSharpResourceData
com.raytheon.uf.viz.d2d.nsharp.display.D2DNSharpDescriptor
com.raytheon.uf.viz.d2d.nsharp.display.D2DNSharpDisplay

View file

@ -0,0 +1,228 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.d2d.nsharp;
import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer;
import javax.measure.Measure;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Length;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import com.raytheon.uf.common.sounding.SoundingLayer;
import com.raytheon.uf.common.wxmath.Dewpoint;
import com.raytheon.uf.common.wxmath.PToZsa;
import com.raytheon.uf.common.wxmath.RelativeHumidity;
import com.raytheon.uf.common.wxmath.ZToPsa;
/**
* Builder for conveniently making NcSoundingLayers with the correct units.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 14, 2013 2260 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class SoundingLayerBuilder {
private static final Unit<Pressure> PRESSURE_UNIT = SI.HECTO(SI.PASCAL);
private static final Unit<Length> HEIGHT_UNIT = SI.METER;
private static final Unit<Temperature> TEMPERATURE_UNIT = SI.CELSIUS;
private static final Unit<Temperature> DEWPOINT_UNIT = SI.CELSIUS;
private static final Unit<Pressure> NC_PRESSURE_UNIT = SI.HECTO(SI.PASCAL);
private static final Unit<Length> NC_HEIGHT_UNIT = SI.METER;
private static final Unit<Temperature> NC_TEMPERATURE_UNIT = SI.CELSIUS;
private static final Unit<Temperature> NC_DEWPOINT_UNIT = SI.CELSIUS;
private static final Unit<Dimensionless> NC_RELATIVE_HUMIDITY_UNIT = NonSI.PERCENT;
private static final Unit<Dimensionless> NC_SPECIFIC_HUMIDITY_UNIT = SI.KILOGRAM
.divide(SI.KILOGRAM).asType(Dimensionless.class);
private Measure<?, Pressure> pressure;
private Measure<?, Length> height;
private Measure<?, Temperature> temperature;
private Measure<?, Temperature> dewpoint;
private Measure<?, Dimensionless> relativeHumidity;
private Measure<?, Dimensionless> specificHumidity;
public SoundingLayerBuilder addPressure(Measure<?, Pressure> pressure) {
this.pressure = pressure;
return this;
}
public SoundingLayerBuilder addPressure(double pressure, Unit<Pressure> unit) {
this.pressure = Measure.valueOf(pressure, unit);
return this;
}
public SoundingLayerBuilder addPressure(float pressure, Unit<Pressure> unit) {
this.pressure = Measure.valueOf(pressure, unit);
return this;
}
public SoundingLayerBuilder addHeight(Measure<?, Length> height) {
this.height = height;
return this;
}
public SoundingLayerBuilder addHeight(double height, Unit<Length> unit) {
this.height = Measure.valueOf(height, unit);
return this;
}
public SoundingLayerBuilder addTemperature(
Measure<?, Temperature> temperature) {
this.temperature = temperature;
return this;
}
public SoundingLayerBuilder addTemperature(double temperature,
Unit<Temperature> unit) {
this.temperature = Measure.valueOf(temperature, unit);
return this;
}
public SoundingLayerBuilder addDewpoint(Measure<?, Temperature> dewpoint) {
this.dewpoint = dewpoint;
return this;
}
public SoundingLayerBuilder addDewpoint(double dewpoint,
Unit<Temperature> unit) {
this.dewpoint = Measure.valueOf(dewpoint, unit);
return this;
}
public SoundingLayerBuilder addSpecificHumidity(
Measure<?, Dimensionless> specificHumidity) {
this.specificHumidity = specificHumidity;
return this;
}
public SoundingLayerBuilder addSpecificHumidity(double specificHumidity,
Unit<Dimensionless> unit) {
this.specificHumidity = Measure.valueOf(specificHumidity, unit);
return this;
}
public SoundingLayerBuilder addRelativeHumidity(
Measure<?, Dimensionless> relativeHumidity) {
this.relativeHumidity = relativeHumidity;
return this;
}
public SoundingLayerBuilder addRelativeHumidity(double relativeHumidity,
Unit<Dimensionless> unit) {
this.specificHumidity = Measure.valueOf(relativeHumidity, unit);
return this;
}
public NcSoundingLayer toNcSoundingLayer() {
NcSoundingLayer layer = new NcSoundingLayer();
if (pressure != null) {
layer.setPressure(pressure.floatValue(NC_PRESSURE_UNIT));
} else if (height != null) {
layer.setPressure(ZToPsa.ztopsa(height.floatValue(SI.METER)));
}
if (height != null) {
layer.setGeoHeight(height.floatValue(NC_HEIGHT_UNIT));
} else if (pressure != null) {
layer.setGeoHeight(PToZsa.ptozsa(pressure.floatValue(SI
.HECTO(SI.PASCAL))));
}
if (temperature != null) {
layer.setTemperature(temperature.floatValue(NC_TEMPERATURE_UNIT));
}
if (dewpoint != null) {
layer.setDewpoint(dewpoint.floatValue(NC_DEWPOINT_UNIT));
} else if (specificHumidity != null && pressure != null) {
Measure<?, Temperature> dewpoint = Dewpoint.calculate(pressure,
specificHumidity);
layer.setDewpoint(dewpoint.floatValue(NC_DEWPOINT_UNIT));
}
if (relativeHumidity != null) {
layer.setRelativeHumidity(relativeHumidity
.floatValue(NC_RELATIVE_HUMIDITY_UNIT));
} else {
Measure<?, Dimensionless> relativeHumidity = RelativeHumidity
.calculate(pressure, temperature, specificHumidity);
layer.setRelativeHumidity(relativeHumidity
.floatValue(NC_RELATIVE_HUMIDITY_UNIT));
}
if (specificHumidity != null) {
layer.setSpecHumidity(specificHumidity
.floatValue(NC_SPECIFIC_HUMIDITY_UNIT));
}
return layer;
}
public SoundingLayer toSoundingLayer() {
SoundingLayer layer = new SoundingLayer();
if (pressure != null) {
layer.setPressure(pressure.floatValue(PRESSURE_UNIT));
} else if (height != null) {
layer.setPressure(ZToPsa.ztopsa(height.floatValue(SI.METER)));
}
if (height != null) {
layer.setGeoHeight(height.floatValue(HEIGHT_UNIT));
} else if (pressure != null) {
layer.setGeoHeight(PToZsa.ptozsa(pressure.floatValue(SI
.HECTO(SI.PASCAL))));
}
if (temperature != null) {
layer.setTemperature(temperature.floatValue(TEMPERATURE_UNIT));
}
if (dewpoint != null) {
layer.setDewpoint(dewpoint.floatValue(DEWPOINT_UNIT));
} else if (specificHumidity != null && pressure != null) {
Measure<?, Temperature> dewpoint = Dewpoint.calculate(pressure,
specificHumidity);
layer.setDewpoint(dewpoint.floatValue(DEWPOINT_UNIT));
}
return layer;
}
}

View file

@ -0,0 +1,161 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.d2d.nsharp.rsc;
import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingCube;
import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingCube.QueryStatus;
import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer;
import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile;
import gov.noaa.nws.ncep.ui.nsharp.NsharpStationInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
import javax.measure.unit.Unit;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.pointdata.PointDataContainer;
import com.raytheon.uf.common.pointdata.PointDataView;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.d2d.nsharp.SoundingLayerBuilder;
import com.raytheon.viz.pointdata.PointDataRequest;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Provides sounding data to nsharp from poes sounding satellite data.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 14, 2013 2260 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class PoesSndNSharpResourceData extends D2DNSharpResourceData {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(PoesSndNSharpResourceData.class);
private static final String NUM_LEVELS = "numLevels";
private static final String PRESSURE = "pressure";
private static final String TEMPERATURE = "temperature";
private static final String SPEC_HUM = "mixingRatio";
private static final String LONGITUDE = "location.longitude";
private static final String LATITUDE = "location.latitude";
private static final String[] PARAMETERS = { NUM_LEVELS, PRESSURE,
SPEC_HUM, TEMPERATURE };
public PoesSndNSharpResourceData() {
super("POES");
}
@Override
protected void preparePointInfo() throws VizException {
if (coordinate == null || pointName == null) {
DbQueryRequest request = new DbQueryRequest();
request.setConstraints(getMetadataMap());
request.addFields(new String[] { LONGITUDE, LATITUDE });
request.setDistinct(true);
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
for (Map<String, Object> result : response.getResults()) {
if (coordinate == null) {
coordinate = new Coordinate();
coordinate.x = (Double) result.get(LONGITUDE);
coordinate.y = (Double) result.get(LATITUDE);
}
}
}
}
@Override
protected NcSoundingCube getSoundingCube(NsharpStationInfo stnInfo) {
DataTime time = new DataTime(stnInfo.getReftime());
try {
PointDataContainer pdc = PointDataRequest
.requestPointDataAllLevels(time, "goes", PARAMETERS, null,
getMetadataMap());
PointDataView pdv = pdc.readRandom(0);
int numLevels = pdv.getInt(NUM_LEVELS);
Number[] pressure = pdv.getNumberAllLevels(PRESSURE);
Unit<Pressure> pressureUnit = pdv.getUnit(PRESSURE).asType(
Pressure.class);
Number[] temperature = pdv.getNumberAllLevels(TEMPERATURE);
Unit<Temperature> temperatureUnit = pdv.getUnit(TEMPERATURE)
.asType(Temperature.class);
Number[] specHumidity = pdv.getNumberAllLevels(SPEC_HUM);
Unit<Dimensionless> specHumidityUnit = pdv.getUnit(SPEC_HUM)
.asType(Dimensionless.class);
List<NcSoundingLayer> layers = new ArrayList<NcSoundingLayer>(
numLevels);
for (int i = 0; i < numLevels; i += 1) {
SoundingLayerBuilder builder = new SoundingLayerBuilder();
builder.addPressure(pressure[i].doubleValue(), pressureUnit);
builder.addTemperature(temperature[i].doubleValue(),
temperatureUnit);
builder.addSpecificHumidity(specHumidity[i].doubleValue(),
specHumidityUnit);
layers.add(builder.toNcSoundingLayer());
}
NcSoundingProfile profile = new NcSoundingProfile();
profile.setSoundingLyLst(layers);
NcSoundingCube cube = new NcSoundingCube(Arrays.asList(profile));
cube.setRtnStatus(QueryStatus.OK);
return cube;
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
}
return null;
}
}

View file

@ -27,8 +27,10 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.SI;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Length;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
import javax.measure.unit.Unit;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@ -36,7 +38,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import com.raytheon.uf.common.dataplugin.npp.crimss.CrimssRecord;
import com.raytheon.uf.common.pointdata.PointDataView;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.npp.sounding.math.NPPSoundingCalculations;
import com.raytheon.uf.viz.d2d.nsharp.SoundingLayerBuilder;
import com.raytheon.uf.viz.npp.sounding.rsc.AbstractNPPNSharpResourceData;
/**
@ -48,7 +50,8 @@ import com.raytheon.uf.viz.npp.sounding.rsc.AbstractNPPNSharpResourceData;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 5, 2011 bsteffen Initial creation
* Dec 05, 2011 bsteffen Initial creation
* Aug 15, 2013 2260 bsteffen Switch poessounding to NSharp.
*
* </pre>
*
@ -93,121 +96,67 @@ public class CrimssNSharpResourceData extends AbstractNPPNSharpResourceData {
private static NcSoundingLayer getSurfacePressureLayer(PointDataView pdv) {
float surfacePressure = pdv.getFloat(CrimssRecord.PDV_SURFACE_PRESSURE);
Unit<?> surfacePressureUnit = pdv
.getUnit(CrimssRecord.PDV_SURFACE_PRESSURE);
if (PRESSURE_UNIT.isCompatible(surfacePressureUnit)) {
UnitConverter converter = surfacePressureUnit
.getConverterTo(PRESSURE_UNIT);
surfacePressure = (float) converter.convert(surfacePressure);
}
return new NcSoundingLayer(surfacePressure, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING);
Unit<Pressure> surfacePressureUnit = pdv.getUnit(
CrimssRecord.PDV_SURFACE_PRESSURE).asType(Pressure.class);
SoundingLayerBuilder builder = new SoundingLayerBuilder();
builder.addPressure(surfacePressure, surfacePressureUnit);
return builder.toNcSoundingLayer();
}
private static List<NcSoundingLayer> getHeightLayers(PointDataView pdv) {
List<NcSoundingLayer> layers = new ArrayList<NcSoundingLayer>();
UnitConverter heightConverter = UnitConverter.IDENTITY;
Unit<?> heightUnit = pdv.getUnit(CrimssRecord.PDV_ALTITUDE);
if (HEIGHT_UNIT.isCompatible(heightUnit)) {
heightConverter = heightUnit.getConverterTo(HEIGHT_UNIT);
}
UnitConverter pressureConverter = UnitConverter.IDENTITY;
Unit<?> pressureUnit = pdv.getUnit(CrimssRecord.PDV_P_ALTITUDE);
if (PRESSURE_UNIT.isCompatible(pressureUnit)) {
pressureConverter = pressureUnit.getConverterTo(PRESSURE_UNIT);
}
Unit<Length> heightUnit = pdv.getUnit(CrimssRecord.PDV_ALTITUDE)
.asType(Length.class);
Unit<Pressure> pressureUnit = pdv.getUnit(CrimssRecord.PDV_P_ALTITUDE)
.asType(Pressure.class);
Number[] altitudeArray = pdv
.getNumberAllLevels(CrimssRecord.PDV_ALTITUDE);
Number[] pressureArray = pdv
.getNumberAllLevels(CrimssRecord.PDV_P_ALTITUDE);
for (int j = 0; j < altitudeArray.length; j++) {
float altitude = altitudeArray[j].floatValue();
altitude = (float) heightConverter.convert(altitude);
float pressure = pressureArray[j].floatValue();
pressure = (float) pressureConverter.convert(pressure);
NcSoundingLayer layer = new NcSoundingLayer(pressure, altitude,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING);
layers.add(layer);
SoundingLayerBuilder builder = new SoundingLayerBuilder();
builder.addPressure(pressureArray[j].doubleValue(), pressureUnit);
builder.addHeight(altitudeArray[j].doubleValue(), heightUnit);
layers.add(builder.toNcSoundingLayer());
}
return layers;
}
private static List<NcSoundingLayer> getTemperatureLayers(PointDataView pdv) {
List<NcSoundingLayer> layers = new ArrayList<NcSoundingLayer>();
UnitConverter temperatureConverter = UnitConverter.IDENTITY;
Unit<?> temperatureUnit = pdv.getUnit(CrimssRecord.PDV_TEMPERATURE);
if (TEMPERATURE_UNIT.isCompatible(temperatureUnit)) {
temperatureConverter = temperatureUnit
.getConverterTo(TEMPERATURE_UNIT);
}
UnitConverter pressureConverter = UnitConverter.IDENTITY;
Unit<?> pressureUnit = pdv.getUnit(CrimssRecord.PDV_P_TEMPERATURE);
if (PRESSURE_UNIT.isCompatible(pressureUnit)) {
pressureConverter = pressureUnit.getConverterTo(PRESSURE_UNIT);
}
Unit<Temperature> temperatureUnit = pdv.getUnit(
CrimssRecord.PDV_TEMPERATURE).asType(Temperature.class);
Unit<Pressure> pressureUnit = pdv.getUnit(
CrimssRecord.PDV_P_TEMPERATURE).asType(Pressure.class);
Number[] temperatureArray = pdv
.getNumberAllLevels(CrimssRecord.PDV_TEMPERATURE);
Number[] pressureArray = pdv
.getNumberAllLevels(CrimssRecord.PDV_P_TEMPERATURE);
for (int j = 0; j < temperatureArray.length; j++) {
float temperature = temperatureArray[j].floatValue();
temperature = (float) temperatureConverter.convert(temperature);
float pressure = pressureArray[j].floatValue();
pressure = (float) pressureConverter.convert(pressure);
NcSoundingLayer layer = new NcSoundingLayer(pressure,
NcSoundingLayer.MISSING, temperature,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING);
layers.add(layer);
SoundingLayerBuilder builder = new SoundingLayerBuilder();
builder.addPressure(pressureArray[j].doubleValue(), pressureUnit);
builder.addTemperature(temperatureArray[j].doubleValue(),
temperatureUnit);
layers.add(builder.toNcSoundingLayer());
}
return layers;
}
private static List<NcSoundingLayer> getDewpointLayers(PointDataView pdv) {
List<NcSoundingLayer> layers = new ArrayList<NcSoundingLayer>();
UnitConverter h2oConverter = UnitConverter.IDENTITY;
Unit<?> h2oUnit = pdv.getUnit(CrimssRecord.PDV_H2O);
if (H2O_UNIT.isCompatible(h2oUnit)) {
h2oConverter = h2oUnit.getConverterTo(H2O_UNIT);
}
UnitConverter dewpointConverter = UnitConverter.IDENTITY;
Unit<?> dewpointUnit = SI.KELVIN;
if (DEWPOINT_UNIT.isCompatible(dewpointUnit)) {
dewpointConverter = dewpointUnit.getConverterTo(DEWPOINT_UNIT);
}
UnitConverter pressureConverter = UnitConverter.IDENTITY;
Unit<?> pressureUnit = pdv.getUnit(CrimssRecord.PDV_P_H2O);
if (PRESSURE_UNIT.isCompatible(pressureUnit)) {
pressureConverter = pressureUnit.getConverterTo(PRESSURE_UNIT);
}
Unit<Dimensionless> h2oUnit = pdv.getUnit(CrimssRecord.PDV_H2O).asType(
Dimensionless.class);
Unit<Pressure> pressureUnit = pdv.getUnit(CrimssRecord.PDV_P_H2O)
.asType(Pressure.class);
Number[] h2oArray = pdv.getNumberAllLevels(CrimssRecord.PDV_H2O);
Number[] pressureArray = pdv.getNumberAllLevels(CrimssRecord.PDV_P_H2O);
for (int j = 0; j < h2oArray.length; j++) {
float pressure = pressureArray[j].floatValue();
pressure = (float) pressureConverter.convert(pressure);
float h2o = h2oArray[j].floatValue();
float dpt = NPPSoundingCalculations.convertH2OtoDewpoint(h2o,
pressure);
dpt = (float) dewpointConverter.convert(dpt);
NcSoundingLayer layer = new NcSoundingLayer(pressure,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
(float) dpt, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING, h2o,
NcSoundingLayer.MISSING);
layers.add(layer);
SoundingLayerBuilder builder = new SoundingLayerBuilder();
builder.addPressure(pressureArray[j].doubleValue(), pressureUnit);
builder.addSpecificHumidity(h2oArray[j].doubleValue(), h2oUnit);
layers.add(builder.toNcSoundingLayer());
}
return layers;
}

View file

@ -24,17 +24,17 @@ import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer;
import java.util.ArrayList;
import java.util.List;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.SI;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
import javax.measure.unit.Unit;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import com.raytheon.edex.meteolibrary.Meteolibrary;
import com.raytheon.uf.common.dataplugin.npp.nucaps.NucapsRecord;
import com.raytheon.uf.common.pointdata.PointDataView;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.npp.sounding.math.NPPSoundingCalculations;
import com.raytheon.uf.viz.d2d.nsharp.SoundingLayerBuilder;
import com.raytheon.uf.viz.npp.sounding.rsc.AbstractNPPNSharpResourceData;
/**
@ -47,6 +47,7 @@ import com.raytheon.uf.viz.npp.sounding.rsc.AbstractNPPNSharpResourceData;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 15, 2013 mschenke Initial creation
* Aug 15, 2013 2260 bsteffen Switch poessounding to NSharp.
*
* </pre>
*
@ -78,21 +79,17 @@ public class NucapsNSharpResourceData extends AbstractNPPNSharpResourceData {
protected List<NcSoundingLayer> getSoundingLayers(PointDataView pdv)
throws VizException {
Number[] pressures = pdv.getNumberAllLevels(NucapsRecord.PDV_PRESSURE);
UnitConverter pressureConverter = getConverter(
pdv.getUnit(NucapsRecord.PDV_PRESSURE), PRESSURE_UNIT);
Unit<Pressure> pressureUnit = pdv.getUnit(NucapsRecord.PDV_PRESSURE)
.asType(Pressure.class);
Number[] temperatures = pdv
.getNumberAllLevels(NucapsRecord.PDV_TEMPERATURE);
UnitConverter temperatureConverter = getConverter(
pdv.getUnit(NucapsRecord.PDV_TEMPERATURE), TEMPERATURE_UNIT);
UnitConverter temperatureCalcConverter = getConverter(
pdv.getUnit(NucapsRecord.PDV_TEMPERATURE),
TEMPERATURE_CALC_UNIT);
Unit<Temperature> temperatureUnit = pdv.getUnit(
NucapsRecord.PDV_TEMPERATURE).asType(Temperature.class);
Number[] wvMixingRatios = pdv
.getNumberAllLevels(NucapsRecord.PDV_WATER_VAPOR_MIXING_RATIO);
UnitConverter wvMixingRatioConverter = getConverter(
pdv.getUnit(NucapsRecord.PDV_WATER_VAPOR_MIXING_RATIO),
H2O_UNIT);
UnitConverter dewPointConverter = getConverter(SI.KELVIN, SI.CELSIUS);
Unit<Dimensionless> wvMixingRatioUnit = pdv.getUnit(
NucapsRecord.PDV_WATER_VAPOR_MIXING_RATIO).asType(
Dimensionless.class);
if (pressures.length != temperatures.length
|| pressures.length != wvMixingRatios.length) {
@ -105,41 +102,20 @@ public class NucapsNSharpResourceData extends AbstractNPPNSharpResourceData {
float surfacePressure = pdv.getFloat(NucapsRecord.PDV_SURFACE_PRESSURE);
for (int i = 0; i < length; ++i) {
int idx = i;
float pressure = (float) pressureConverter.convert(pressures[idx]
.doubleValue());
double pressure = pressures[idx].doubleValue();
if (pressure <= surfacePressure) {
// Don't add entries where pressure indicates below ground
float gh = Meteolibrary.ptozsa(new float[] { pressure }, 0);
Number temperature = temperatures[idx];
float h20 = (float) wvMixingRatioConverter
.convert(wvMixingRatios[idx].doubleValue());
float dewpoint = NPPSoundingCalculations.convertH2OtoDewpoint(
h20, pressure);
float rh = NPPSoundingCalculations
.convertH20ToRelativeHumidity(h20,
(float) temperatureCalcConverter
.convert(temperature.doubleValue()),
pressure);
soundingLayers.add(new NcSoundingLayer(pressure, gh,
(float) temperatureConverter.convert(temperature
.doubleValue()), (float) dewPointConverter
.convert(dewpoint), NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING, h20,
rh));
SoundingLayerBuilder builder = new SoundingLayerBuilder();
builder.addPressure(pressure, pressureUnit);
builder.addTemperature(temperatures[idx].doubleValue(),
temperatureUnit);
builder.addSpecificHumidity(wvMixingRatios[idx].doubleValue(),
wvMixingRatioUnit);
soundingLayers.add(builder.toNcSoundingLayer());
}
}
return soundingLayers;
}
private UnitConverter getConverter(Unit<?> fromUnit, Unit<?> toUnit)
throws VizException {
if (fromUnit.isCompatible(toUnit)) {
return fromUnit.getConverterTo(toUnit);
}
throw new VizException("Unable to convert " + fromUnit + " to "
+ toUnit);
}
}

View file

@ -24,12 +24,13 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.measure.converter.UnitConverter;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
import javax.measure.unit.Unit;
import org.geotools.referencing.GeodeticCalculator;
import com.raytheon.edex.meteolibrary.Meteolibrary;
import com.raytheon.uf.common.dataplugin.npp.nucaps.NucapsRecord;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.pointdata.PointDataContainer;
@ -43,8 +44,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.d2d.nsharp.SoundingLayerBuilder;
import com.raytheon.uf.viz.npp.NPPTimeUtility;
import com.raytheon.uf.viz.npp.sounding.math.NPPSoundingCalculations;
import com.raytheon.uf.viz.sounding.providers.AbstractVerticalSoundingProvider;
import com.raytheon.viz.core.map.GeoUtil;
import com.raytheon.viz.pointdata.PointDataRequest;
@ -61,7 +62,8 @@ import com.vividsolutions.jts.index.strtree.STRtree;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 25, 2013 2190 mschenke Initial creation
* Jul 25, 2013 2190 mschenke Initial creation
* Aug 15, 2013 2260 bsteffen Switch poessounding to NSharp.
*
* </pre>
*
@ -117,58 +119,41 @@ public class NucapsSoundingProvider extends
// Get pressure values
Number[] pressures = pdv
.getNumberAllLevels(NucapsRecord.PDV_PRESSURE);
Unit<?> pressureUnit = pdv.getUnit(NucapsRecord.PDV_PRESSURE);
UnitConverter dataToSLPressureUnit = pressureUnit
.getConverterTo(SoundingLayer.DATA_TYPE.PRESSURE
.getUnit());
Unit<Pressure> pressureUnit = pdv.getUnit(
NucapsRecord.PDV_PRESSURE).asType(Pressure.class);
// Get temperature values
Number[] temperatures = pdv
.getNumberAllLevels(NucapsRecord.PDV_TEMPERATURE);
Unit<?> tempUnit = pdv.getUnit(NucapsRecord.PDV_TEMPERATURE);
UnitConverter dataToSLTempUnit = tempUnit
.getConverterTo(SoundingLayer.DATA_TYPE.TEMPERATURE
.getUnit());
Unit<Temperature> tempUnit = pdv.getUnit(
NucapsRecord.PDV_TEMPERATURE).asType(Temperature.class);
// Water-vapor mixing ratios
Number[] wvMixingRatios = pdv
.getNumberAllLevels(NucapsRecord.PDV_WATER_VAPOR_MIXING_RATIO);
Unit<?> wvUnit = pdv
.getUnit(NucapsRecord.PDV_WATER_VAPOR_MIXING_RATIO);
UnitConverter wvUnitConverter = wvUnit
.getConverterTo(NPPSoundingCalculations.H2O_UNIT);
Unit<Dimensionless> wvUnit = pdv.getUnit(
NucapsRecord.PDV_WATER_VAPOR_MIXING_RATIO).asType(
Dimensionless.class);
if (pressures.length == temperatures.length) {
int length = pressures.length;
List<SoundingLayer> layers = new ArrayList<SoundingLayer>(
length);
float surfacePressure = (float) dataToSLPressureUnit
.convert(pdv
.getFloat(NucapsRecord.PDV_SURFACE_PRESSURE));
float surfacePressure = pdv
.getFloat(NucapsRecord.PDV_SURFACE_PRESSURE);
for (int idx = 0; idx < length; ++idx) {
float pressure = (float) dataToSLPressureUnit
.convert(pressures[idx].doubleValue());
double pressure = pressures[idx].doubleValue();
// Don't add entries where pressure below surface
if (pressure <= surfacePressure) {
// Pressure to height
float gh = Meteolibrary.ptozsa(
new float[] { (float) pressure }, 0);
// Temperature
float temperature = (float) dataToSLTempUnit
.convert(temperatures[idx].doubleValue());
// Water vapor mixing ratio
float h20 = (float) wvUnitConverter
.convert(wvMixingRatios[idx].doubleValue());
// Calculate dewpoint and RH from pressure and h20
float dewpoint = NPPSoundingCalculations
.convertH2OtoDewpoint(h20, pressure);
SoundingLayerBuilder builder = new SoundingLayerBuilder();
builder.addPressure(pressure, pressureUnit);
builder.addTemperature(
temperatures[idx].doubleValue(), tempUnit);
builder.addSpecificHumidity(
wvMixingRatios[idx].doubleValue(), wvUnit);
layers.add(new SoundingLayer(pressure, gh,
temperature, dewpoint,
SoundingLayer.MISSING,
SoundingLayer.MISSING,
SoundingLayer.MISSING));
layers.add(builder.toSoundingLayer());
}
}
sounding.addLayers(layers);

View file

@ -25,5 +25,4 @@ Require-Bundle: org.eclipse.core.runtime,
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Import-Package: gov.noaa.nws.ncep.edex.common.sounding
Export-Package: com.raytheon.uf.viz.npp.sounding.math,
com.raytheon.uf.viz.npp.sounding.rsc
Export-Package: com.raytheon.uf.viz.npp.sounding.rsc

View file

@ -1,97 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.npp.sounding.math;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
/**
* Common NPP Sounding calculations
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 26, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class NPPSoundingCalculations {
public static final Unit<?> PRESSURE_UNIT = SI.HECTO(SI.PASCAL);
public static final Unit<?> HEIGHT_UNIT = SI.METER;
public static final Unit<?> TEMPERATURE_UNIT = SI.CELSIUS;
public static final Unit<?> TEMPERATURE_CALC_UNIT = SI.KELVIN;
public static final Unit<?> H2O_UNIT = SI.GRAM.divide(SI.KILOGRAM);
public static final Unit<?> DEWPOINT_UNIT = SI.CELSIUS;
/**
* convert h2o in g/kg and pressure in hPa to dewpoint in kelvin.
*
* @param h2o
* @param pressure
* @return
*/
public static float convertH2OtoDewpoint(float h2o, float pressure) {
double eee = pressure * h2o / (622.0 + 0.378 * h2o);
double b = 26.66082 - Math.log(eee);
return (float) ((b - Math.sqrt(b * b - 223.1986)) / 0.0182758048);
}
/**
* convert h2o in g/kg and pressure in hPa to relative humidity.
*
* @param h20
* @param temperature
* @param pressure
* @return
*/
public static float convertH20ToRelativeHumidity(float h20,
float temperature, float pressure) {
double a = 22.05565;
double b = 0.0091379024;
double c = 6106.396;
double epsilonx1k = 622.0;
double shxDenom = h20 * 0.378;
shxDenom += epsilonx1k;
double tDenom = -b * temperature;
tDenom += a;
tDenom -= c / temperature;
double RH = pressure * h20;
RH /= shxDenom;
RH /= Math.exp(tDenom);
return (float) RH;
}
}

View file

@ -34,7 +34,6 @@ import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.measure.unit.Unit;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@ -48,7 +47,6 @@ import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.d2d.nsharp.rsc.D2DNSharpResourceData;
import com.raytheon.uf.viz.npp.sounding.Activator;
import com.raytheon.uf.viz.npp.sounding.math.NPPSoundingCalculations;
import com.raytheon.viz.pointdata.PointDataRequest;
import com.vividsolutions.jts.geom.Coordinate;
@ -62,7 +60,9 @@ import com.vividsolutions.jts.geom.Coordinate;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 14, 2013 mschenke Initial creation
* Aug 2, 2013 2190 mschenke Moved common npp sounding calculations to utility class
* Aug 02, 2013 2190 mschenke Moved common npp sounding calculations to
* utility class
* Aug 15, 2013 2260 bsteffen Switch poessounding to NSharp.
*
* </pre>
*
@ -108,18 +108,6 @@ public abstract class AbstractNPPNSharpResourceData extends
}
}
protected static final Unit<?> PRESSURE_UNIT = NPPSoundingCalculations.PRESSURE_UNIT;
protected static final Unit<?> HEIGHT_UNIT = NPPSoundingCalculations.HEIGHT_UNIT;
protected static final Unit<?> TEMPERATURE_UNIT = NPPSoundingCalculations.TEMPERATURE_UNIT;
protected static final Unit<?> TEMPERATURE_CALC_UNIT = NPPSoundingCalculations.TEMPERATURE_CALC_UNIT;
protected static final Unit<?> H2O_UNIT = NPPSoundingCalculations.H2O_UNIT;
protected static final Unit<?> DEWPOINT_UNIT = NPPSoundingCalculations.DEWPOINT_UNIT;
private final String plugin;
private final String[] parameters;

View file

@ -48,6 +48,7 @@ import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
import com.raytheon.uf.viz.core.rsc.ResourceType;
import com.raytheon.uf.viz.d2d.nsharp.rsc.BufruaNSharpResourceData;
import com.raytheon.uf.viz.d2d.nsharp.rsc.MdlSndNSharpResourceData;
import com.raytheon.uf.viz.d2d.nsharp.rsc.PoesSndNSharpResourceData;
import com.raytheon.uf.viz.objectiveanalysis.rsc.OAResourceData;
import com.raytheon.uf.viz.points.PointsDataManager;
import com.raytheon.uf.viz.xy.crosssection.rsc.CrossSectionResourceData;
@ -76,6 +77,7 @@ import com.vividsolutions.jts.geom.LineString;
* work without dataURI.
* Aug 15, 2013 2258 bsteffen Convert profiler sounding to var height
* with hodo.
* Aug 15, 2013 2260 bsteffen Switch poessounding to NSharp.
*
* </pre>
*
@ -493,10 +495,13 @@ public class PointDataCatalog extends AbstractInventoryDataCatalog {
return new BufruaNSharpResourceData();
} else if (catalogEntry.getSelectedData().getSourcesKey()
.equals("modelsoundingETA")) {
return resourceData = new MdlSndNSharpResourceData("NAMSND");
return new MdlSndNSharpResourceData("NAMSND");
} else if (catalogEntry.getSelectedData().getSourcesKey()
.equals("modelsoundingGFS")) {
return resourceData = new MdlSndNSharpResourceData("GFSSND");
return new MdlSndNSharpResourceData("GFSSND");
} else if (catalogEntry.getSelectedData().getSourcesKey()
.equals("poessounding")) {
return new PoesSndNSharpResourceData();
} else if (catalogEntry.getSelectedData().getSourcesKey()
.equals("profiler")) {
VarHeightResourceData vhData = new VarHeightResourceData();

View file

@ -6,3 +6,4 @@ Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: com.raytheon.uf.common.wxmath
Require-Bundle: javax.measure;bundle-version="1.0.0"

View file

@ -0,0 +1,72 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.wxmath;
import javax.measure.Measure;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
/**
* Contains calculations for calculating dewpoint from pressure and specific
* humidity.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 14, 2013 2260 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class Dewpoint {
public static final Unit<Pressure> PRESSURE_UNIT = SI.HECTO(SI.PASCAL);
public static final Unit<Dimensionless> SPECIFIC_HUMIDITY_UNIT = SI.GRAM
.divide(SI.KILOGRAM).asType(Dimensionless.class);
public static final Unit<Temperature> DEWPOINT_UNIT = SI.KELVIN;
public static Measure<?, Temperature> calculate(Measure<?, Pressure> pressure,
Measure<?, Dimensionless> specificHumidity) {
double pressureVal = pressure.doubleValue(PRESSURE_UNIT);
double specHumVal = specificHumidity
.doubleValue(SPECIFIC_HUMIDITY_UNIT);
double dewpointVal = calculate(pressureVal, specHumVal);
return Measure.valueOf(dewpointVal,
DEWPOINT_UNIT);
}
public static double calculate(double pressure, double specificHumidity) {
double eee = pressure * specificHumidity
/ (622.0 + 0.378 * specificHumidity);
double b = 26.66082 - Math.log(eee);
return ((b - Math.sqrt(b * b - 223.1986)) / 0.0182758048);
}
}

View file

@ -0,0 +1,90 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.wxmath;
import javax.measure.Measure;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Temperature;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
/**
* Contains calculations for calculating relative humidity from pressure,
* temperature, and specific humidity.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 14, 2013 2260 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class RelativeHumidity {
public static final Unit<Pressure> PRESSURE_UNIT = SI.HECTO(SI.PASCAL);
public static final Unit<Temperature> TEMPERATURE_UNIT = SI.KELVIN;
public static final Unit<Dimensionless> SPECIFIC_HUMIDITY_UNIT = SI.GRAM
.divide(SI.KILOGRAM).asType(Dimensionless.class);
public static final Unit<Dimensionless> RELATIVE_HUMIDITY_UNIT = NonSI.PERCENT;
public static Measure<?, Dimensionless> calculate(
Measure<?, Pressure> pressure, Measure<?, Temperature> temperature,
Measure<?, Dimensionless> specificHumidity) {
double pressureVal = pressure.doubleValue(PRESSURE_UNIT);
double tempVal = temperature.doubleValue(TEMPERATURE_UNIT);
double specHumVal = specificHumidity
.doubleValue(SPECIFIC_HUMIDITY_UNIT);
double relHumVal = calculate(pressureVal, tempVal, specHumVal);
return Measure.valueOf(relHumVal, RELATIVE_HUMIDITY_UNIT);
}
public static double calculate(double pressure, double temperature,
double specificHumidity) {
double a = 22.05565;
double b = 0.0091379024;
double c = 6106.396;
double epsilonx1k = 622.0;
double shxDenom = specificHumidity * 0.378;
shxDenom += epsilonx1k;
double tDenom = -b * temperature;
tDenom += a;
tDenom -= c / temperature;
double RH = pressure * specificHumidity;
RH /= shxDenom;
RH /= Math.exp(tDenom);
return RH;
}
}