Issue #2190 Refactored Popup SkewT and cloud height sampling to create clearer separation of functionality and implemented NUCAPS sounding source.

Amend: Fixed println, added uncustomization of displays to interface, fixed font issue
Amend: Fixed comments and switched to TimeUtil for common constants for time

Change-Id: I92b49a59848ee4a8f61205ab21f5de2e0c260525

Former-commit-id: 00aaabcbe2b7a66c63de3196cc68f57ccb4664a5
This commit is contained in:
Max Schenkelberg 2013-08-02 16:30:12 -05:00
parent e692cc245b
commit 474429aaee
88 changed files with 4392 additions and 2392 deletions

View file

@ -231,10 +231,6 @@
<param name="feature"
value="com.raytheon.viz.satellite.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.d2d.skewt.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.ncep.core.feature" />
@ -267,18 +263,10 @@
<param name="feature"
value="com.raytheon.uf.viz.d2d.nsharp.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.viz.volumebrowser.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.archive.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.d2d.gfe.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.dat.feature" />
@ -311,6 +299,18 @@
<param name="feature"
value="com.raytheon.uf.viz.npp.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.d2d.skewt.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.viz.volumebrowser.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.d2d.gfe.feature" />
</antcall>
<antcall target="p2.build.repo">
<param name="feature"
value="com.raytheon.uf.viz.collaboration.feature" />

View file

@ -11,24 +11,17 @@ Require-Bundle: org.eclipse.ui;bundle-version="3.8.2",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.uf.common.status;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
com.raytheon.uf.common.dataquery;bundle-version="1.0.0",
com.raytheon.uf.common.datastorage;bundle-version="1.12.1174",
com.raytheon.uf.common.sounding;bundle-version="1.12.1174",
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin.grid;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin.satellite;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin.bufrua;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin.grid;bundle-version="1.0.0",
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.raytheon.uf.viz.d2d.core;bundle-version="1.12.1174",
com.raytheon.viz.skewt;bundle-version="1.12.1174",
javax.measure;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.uf.viz.cloudheight,
com.raytheon.uf.viz.cloudheight.data,
com.raytheon.uf.viz.cloudheight.rsc,
com.raytheon.uf.viz.cloudheight.ui
com.raytheon.uf.viz.cloudheight.rsc
Import-Package: com.raytheon.viz.core.map

View file

@ -1 +1 @@
com.raytheon.uf.viz.cloudheight.rsc.PopupSkewTResourceData
com.raytheon.uf.viz.cloudheight.rsc.CloudHeightResourceData

View file

@ -2,5 +2,4 @@ source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
localization/,\
plugin.xml
localization/

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bundle xmlns:ns2="group" xmlns:ns3="http://www.example.org/productType">
<displayList>
<displays xsi:type="d2DMapRenderableDisplay" scale="CONUS" density="1.0" magnification="1.0" zoomLevel="1.0" mapCenter="-96.867249 40.47502100000001 0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<descriptor xsi:type="mapDescriptor">
<resource>
<loadProperties/>
<properties renderingOrderId="LOWEST" isSystemResource="false" isBlinking="false" isMapLayer="false" isHoverOn="false" isVisible="true">
<pdProps maxDisplayWidth="100000000" minDisplayWidth="0"/>
</properties>
<resourceData xsi:type="popupSkewTResourceData"/>
</resource>
</descriptor>
</displays>
</displayList>
</bundle>

View file

@ -18,14 +18,8 @@
See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for
further_licensing_information.
-->
<cloudHeightData nx="25" ny="25" maxTimeoutSecGrid=".25"
maxTimeoutSecRaob=".1" maxMouseDistanceDeg="5.0" displayOption="PEAK">
<sources>
<source name="NONE" type="NONE" displayName="No Sampling"/>
<source name="ETA" type="MODEL" displayName="NAM"/>
<source name="GFS212" type="MODEL" displayName="GFS212"/>
<source name="RUC" type="MODEL" displayName="RUC"/>
<source name="Laps" type="MODEL" displayName="Laps"/>
<source name="Raob" type="RAOB" displayName="From Raobs"/>
</sources>
<cloudHeightData>
<nx>25</nx>
<ny>25</ny>
<displayOption>PEAK</displayOption>
</cloudHeightData>

View file

@ -1,522 +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.cloudheight;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.SI;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.opengis.metadata.spatial.PixelOrientation;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.dataplugin.satellite.units.ir.IRPixel;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.sounding.VerticalSounding;
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.cloudheight.data.CloudHeightData;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource.SourceType;
import com.raytheon.uf.viz.cloudheight.impl.CloudHeightCalculatorPorted;
import com.raytheon.uf.viz.cloudheight.impl.CloudHeightCalculatorPorted.CloudHeightResult;
import com.raytheon.uf.viz.cloudheight.impl.ModelCloudHeightSourceImplementation;
import com.raytheon.uf.viz.cloudheight.impl.RaobCloudHeightSourceImplementation;
import com.raytheon.uf.viz.cloudheight.rsc.PopupSkewTResource;
import com.raytheon.uf.viz.cloudheight.ui.CloudHeightRightClickAction;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
import com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.ICloudHeightAlgorithm;
import com.raytheon.viz.core.map.GeoUtil;
import com.raytheon.viz.skewt.ui.PopupSkewTDialog;
import com.vividsolutions.jts.geom.Coordinate;
/**
* A1 ported cloud height algorithm
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 18, 2011 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CloudHeightAlgorithm implements ICloudHeightAlgorithm {
// TODO: Common place for string
public static final String RAW_VALUE = "rawValue";
public static final VerticalSounding LOADING = new VerticalSounding();
private static final CloudHeightData algorithmData = CloudHeightData
.getCloudHeightData();
private static final float MISSING = -999999.0f;
// TODO: Look into purging data (forwarding remove(DataTime))?
public static interface ICloudHeightSourceImplementation {
public DataTime[] getDataTimes();
public VerticalSounding createSounding(Coordinate latLon,
DataTime rscTime);
}
/** Sounding source implementation map */
private Map<SoundingSource, ICloudHeightSourceImplementation> implMap = new HashMap<SoundingSource, CloudHeightAlgorithm.ICloudHeightSourceImplementation>();
/** Currently selected source */
private SoundingSource currentSource;
/** Whether skewT is selected or not */
private boolean skewT = false;
/** Pop up skewT dialog */
private PopupSkewTDialog dialog;
/**
* If we have sampled and they selected skewT in menu, we should open the
* dialog (A1 behavior)
*/
private boolean hasSampled = false;
/**
*
*/
public CloudHeightAlgorithm() {
// Create an implementation for each sounding source
for (SoundingSource source : algorithmData.getSources()) {
ICloudHeightSourceImplementation impl = null;
if (source.getType() == SourceType.MODEL) {
impl = new ModelCloudHeightSourceImplementation(source);
} else if (source.getType() == SourceType.RAOB) {
impl = new RaobCloudHeightSourceImplementation(source);
}
implMap.put(source, impl);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.
* ICloudHeightAlgorithm
* #addContextMenuItems(com.raytheon.uf.viz.core.drawables.IDescriptor,
* org.eclipse.jface.action.IMenuManager, int, int)
*/
@Override
public void addContextMenuItems(IDescriptor descriptor,
IMenuManager manager, int x, int y) {
manager.add(new CloudHeightRightClickAction(descriptor, this));
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.
* ICloudHeightAlgorithm
* #inspect(com.raytheon.uf.viz.core.drawables.IDescriptor,
* com.raytheon.uf.common.time.DataTime,
* com.vividsolutions.jts.geom.Coordinate)
*/
@Override
public String inspect(AbstractVizResource<?, ?> reqRsc, Coordinate latLon) {
IDescriptor descriptor = reqRsc.getDescriptor();
ICloudHeightSourceImplementation impl = getCurrentImplementation();
if (impl == null) {
// No implementation for the source
return null;
}
hasSampled = true;
if (skewT) {
showDialog();
}
FramesInfo currInfo = descriptor.getFramesInfo();
// Get all valid contributors to cloud height that provide temp
List<AbstractVizResource<?, ?>> resources = getValidContributors(
new ArrayList<AbstractVizResource<?, ?>>(),
descriptor.getResourceList());
float[] temps = null;
AbstractVizResource<?, ?> usedRsc = null;
for (AbstractVizResource<?, ?> rsc : resources) {
DataTime timeForRsc = currInfo.getTimeForResource(rsc);
if (timeForRsc != null) {
try {
Map<String, Object> interMap = rsc
.interrogate(new ReferencedCoordinate(latLon));
if (interMap != null
&& interMap.get(RAW_VALUE) instanceof Double
&& interMap.containsKey(ISpatialObject.class
.toString())) {
temps = extractTemps(latLon, rsc, interMap, rsc
.getCapability(ColorMapCapability.class)
.getColorMapParameters());
boolean good = true;
for (int i = 0; i < temps.length; ++i) {
if (temps[i] == MISSING) {
good = false;
}
}
if (good) {
usedRsc = rsc;
break;
}
}
} catch (VizException e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error interrogating resource", e);
}
}
}
if (temps != null && temps[0] != MISSING) {
float cloudTemp = temps[0];
float coldestCloudTemp = temps[1];
float predCloudTemp = temps[2];
float warmestCloudTemp = temps[3];
Float otherTempToUse = null;
switch (algorithmData.getDisplayOption()) {
case LOW: {
otherTempToUse = warmestCloudTemp;
break;
}
case PEAK: {
otherTempToUse = coldestCloudTemp;
break;
}
case PREDOMINANT: {
otherTempToUse = predCloudTemp;
break;
}
}
String status = "";
float height = -1, otherHeight = -1;
VerticalSounding sounding = impl.createSounding(latLon,
descriptor.getTimeForResource(usedRsc));
if (sounding == null) {
if (currentSource.getType() == SourceType.RAOB) {
return "NO RAOB DATA";
} else if (currentSource.getType() == SourceType.MODEL) {
sounding = new VerticalSounding();
sounding.setStationId("CLIMO");
sounding.setName(GeoUtil.formatCoordinate(latLon));
int day = Calendar.getInstance().get(Calendar.DAY_OF_YEAR);
// This will populate the sounding
height = CloudHeightCalculatorPorted
.getCloudHeightClimo(cloudTemp + 273.0f,
(float) latLon.y, day, sounding);
if (otherTempToUse != null) {
// Here we just want the height
otherHeight = CloudHeightCalculatorPorted
.getCloudHeightClimo(otherTempToUse + 273.0f,
(float) latLon.y, day, null);
}
}
} else if (sounding != LOADING) {
float[] muParcelTrajectory = PopupSkewTDialog
.derivemuParcelTrajectory(sounding);
CloudHeightResult result = CloudHeightCalculatorPorted
.getCloudHeightGrid((float) (cloudTemp + 273.0),
sounding, currentSource, muParcelTrajectory);
status = result.status;
height = result.value;
if (otherTempToUse != null) {
result = CloudHeightCalculatorPorted.getCloudHeightGrid(
otherTempToUse + 273.0f, sounding, currentSource,
muParcelTrajectory);
otherHeight = result.value;
}
} else {
reqRsc.issueRefresh();
return null;
}
if (height < 0 || Float.isNaN(height)) {
if (currentSource.getType() == SourceType.RAOB) {
return "NO RAOB DATA";
} else if (currentSource.getType() == SourceType.MODEL) {
return "NO CLIMO DATA";
}
}
int heightInHundredsFt = ((int) (height * 3.28 / 100 + .5) * 100);
String rval = "" + heightInHundredsFt;
if (otherHeight >= 0) {
int otherHeightInHundredsFt = ((int) (otherHeight * 3.28 / 100 + .5) * 100);
rval += "/" + otherHeightInHundredsFt;
}
if (dialog != null) {
setSounding(sounding);
plotHeight(height, cloudTemp);
}
return rval
+ String.format(" feet (%s %s)", sounding.getStationId(),
status);
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.
* ICloudHeightAlgorithm
* #isEnabled(com.raytheon.uf.viz.core.drawables.IDescriptor)
*/
@Override
public boolean isEnabled(IDescriptor descriptor) {
return getValidContributors(new ArrayList<AbstractVizResource<?, ?>>(),
descriptor.getResourceList()).size() > 0
|| descriptor.getResourceList()
.getResourcesByType(PopupSkewTResource.class).size() > 0;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.
* ICloudHeightAlgorithm#getDataTimes()
*/
@Override
public DataTime[] getDataTimes() {
ICloudHeightSourceImplementation impl = implMap.get(currentSource);
if (impl != null) {
return impl.getDataTimes();
}
return new DataTime[0];
}
/**
* Returns the first valid ICloudHeightContributor on the descriptor
*
* @param descriptor
* @return
*/
private List<AbstractVizResource<?, ?>> getValidContributors(
List<AbstractVizResource<?, ?>> resources, ResourceList list) {
for (ResourcePair rp : list) {
AbstractVizResource<?, ?> rsc = rp.getResource();
if (rsc != null && rp.getProperties().isVisible()
&& rsc.hasCapability(ColorMapCapability.class)) {
ColorMapParameters params = rsc.getCapability(
ColorMapCapability.class).getColorMapParameters();
if (params != null
&& SI.CELSIUS.equals(params.getDisplayUnit())
&& params.getDataUnit() instanceof IRPixel) {
resources.add(rsc);
}
}
}
List<AbstractVizResource<?, ?>> groups = list
.getResourcesByType(IResourceGroup.class);
for (AbstractVizResource<?, ?> group : groups) {
if (group.getProperties().isVisible()) {
getValidContributors(resources,
((IResourceGroup) group).getResourceList());
}
}
return resources;
}
public ICloudHeightSourceImplementation getCurrentImplementation() {
return implMap.get(currentSource);
}
public SoundingSource getCurrentSource() {
return currentSource;
}
public void setCurrentSource(SoundingSource currentSource) {
this.currentSource = currentSource;
}
public boolean isSkewT() {
return skewT;
}
public void setSkewT(boolean skewT) {
this.skewT = skewT;
if (skewT) {
showDialog();
} else {
hideDialog();
}
}
public synchronized void hideDialog() {
if (dialog != null) {
dialog.close();
dialog = null;
}
}
public synchronized void showDialog() {
if (dialog == null) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell();
dialog = new PopupSkewTDialog(shell);
dialog.addListener(SWT.Close, new Listener() {
@Override
public void handleEvent(Event event) {
skewT = false;
}
});
}
if (dialog.isOpen() == false && hasSampled) {
dialog.open();
}
}
public void setSounding(VerticalSounding sounding) {
if (dialog != null) {
dialog.setSounding(sounding);
}
}
public void plotHeight(float height, float temp) {
if (dialog != null) {
dialog.plotHeight(height, temp);
}
}
private float[] extractTemps(Coordinate latLon,
AbstractVizResource<?, ?> rsc, Map<String, Object> interMap,
ColorMapParameters params) {
// Method loosely ported from SatPVImageDepict.C::interogate
ISpatialObject so = (ISpatialObject) interMap.get(ISpatialObject.class
.toString());
UnitConverter dataToDisplay = params.getDataToDisplayConverter();
UnitConverter displayToData = params.getDisplayToDataConverter();
float[] temps = new float[] { MISSING, MISSING, MISSING, MISSING };
Coordinate c = MapUtil.latLonToGridCoordinate(latLon,
PixelOrientation.CENTER, so);
int x = (int) Math.round(c.x);
int y = (int) Math.round(c.y);
int nx = so.getNx();
int ny = so.getNy();
if (x < 0 || x >= nx || y < 0 || y >= ny) {
return temps;
}
Double displayVal = (Double) interMap.get(RAW_VALUE);
byte tmp = (byte) displayToData.convert(displayVal);
if (tmp == 0) {
return temps;
}
temps[0] = displayVal.floatValue();
byte[] elements = new byte[6400];
int numElements = 0;
int i, j, ii, jj;
int yStart = -(int) (algorithmData.getNy() / 2);
int yEnd = (int) algorithmData.getNy() / 2;
int xStart = -(int) (algorithmData.getNx() / 2);
int xEnd = (int) algorithmData.getNx() / 2;
for (j = yStart; j < yEnd; j++) {
jj = y + j;
if (jj < 0 || jj >= ny) {
continue;
}
for (i = xStart; i < xEnd; i++) {
ii = x + i;
if (ii >= 0 && ii < nx) {
latLon = MapUtil.gridCoordinateToLatLon(new Coordinate(ii,
jj), PixelOrientation.CENTER, so);
try {
interMap = rsc.interrogate(new ReferencedCoordinate(
latLon));
if (interMap.get(RAW_VALUE) instanceof Double) {
elements[numElements++] = (byte) displayToData
.convert((Double) interMap.get(RAW_VALUE));
}
} catch (VizException e) {
// ignore
}
}
}
}
int[] calculated = new int[3];
CloudHeightCalculatorPorted.findHighPredLowBrightness(elements,
numElements, calculated);
temps[1] = (float) dataToDisplay.convert(calculated[0]);
temps[2] = (float) dataToDisplay.convert(calculated[1]);
temps[3] = (float) dataToDisplay.convert(calculated[2]);
return temps;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.
* ICloudHeightAlgorithm#dispose()
*/
@Override
public void dispose() {
hideDialog();
}
}

View file

@ -24,9 +24,7 @@ import java.io.File;
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.localization.PathManagerFactory;
@ -44,6 +42,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 16, 2009 mschenke Initial creation
* Jul 25, 2013 2190 mschenke Moved sounding configurations into popup skewt plugin
*
* </pre>
*
@ -64,31 +63,17 @@ public class CloudHeightData implements ISerializableObject {
private static CloudHeightData theData = null;
@XmlAccessorType(XmlAccessType.NONE)
public static enum DisplayOption {
NONE, PEAK, PREDOMINANT, LOW;
}
@XmlAttribute
@XmlElement
private float nx;
@XmlAttribute
@XmlElement
private float ny;
@XmlAttribute
private float maxTimeoutSecGrid;
@XmlAttribute
private float maxTimeoutSecRaob;
@XmlAttribute
private float maxMouseDistanceDeg;
@XmlElementWrapper(name = "sources")
@XmlElement(name = "source")
private SoundingSource[] sources;
@XmlAttribute
@XmlElement
private DisplayOption displayOption;
public static synchronized CloudHeightData getCloudHeightData() {
@ -108,12 +93,8 @@ public class CloudHeightData implements ISerializableObject {
CloudHeightData serializedData = JAXB.unmarshal(dataFile,
CloudHeightData.class);
theData.displayOption = serializedData.displayOption;
theData.maxMouseDistanceDeg = serializedData.maxMouseDistanceDeg;
theData.maxTimeoutSecGrid = serializedData.maxTimeoutSecGrid;
theData.maxTimeoutSecRaob = serializedData.maxTimeoutSecRaob;
theData.nx = serializedData.nx;
theData.ny = serializedData.ny;
theData.sources = serializedData.sources;
if ((int) Math.floor(theData.getNx() * theData.getNy()) > 6400) {
statusHandler
.handle(Priority.VERBOSE,
@ -143,38 +124,6 @@ public class CloudHeightData implements ISerializableObject {
this.ny = ny;
}
public float getMaxTimeoutSecGrid() {
return maxTimeoutSecGrid;
}
public void setMaxTimeoutSecGrid(float maxTimeoutSecGrid) {
this.maxTimeoutSecGrid = maxTimeoutSecGrid;
}
public float getMaxTimeoutSecRaob() {
return maxTimeoutSecRaob;
}
public void setMaxTimeoutSecRaob(float maxTimeoutSecRaob) {
this.maxTimeoutSecRaob = maxTimeoutSecRaob;
}
public float getMaxMouseDistanceDeg() {
return maxMouseDistanceDeg;
}
public void setMaxMouseDistanceDeg(float maxMouseDistanceDeg) {
this.maxMouseDistanceDeg = maxMouseDistanceDeg;
}
public SoundingSource[] getSources() {
return sources;
}
public void setSources(SoundingSource[] sources) {
this.sources = sources;
}
public DisplayOption getDisplayOption() {
return displayOption;
}

View file

@ -1,124 +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.cloudheight.data;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import com.raytheon.uf.common.serialization.ISerializableObject;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 16, 2009 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class SoundingSource implements ISerializableObject {
@XmlAccessorType(XmlAccessType.NONE)
public static enum SourceType {
NONE, MODEL, RAOB
}
@XmlAttribute
private String name;
@XmlAttribute
private SourceType type;
@XmlAttribute
private String displayName;
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SourceType getType() {
return type;
}
public void setType(SourceType type) {
this.type = type;
}
@Override
public String toString() {
return getDisplayName();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((displayName == null) ? 0 : displayName.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SoundingSource other = (SoundingSource) obj;
if (displayName == null) {
if (other.displayName != null)
return false;
} else if (!displayName.equals(other.displayName))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (type != other.type)
return false;
return true;
}
}

View file

@ -1,197 +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.cloudheight.impl;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.sounding.VerticalSounding;
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.cloudheight.CloudHeightAlgorithm;
import com.raytheon.uf.viz.cloudheight.CloudHeightAlgorithm.ICloudHeightSourceImplementation;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Abstract class for cloud height sounding implementation. Provides async PDO
* requesting
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 19, 2011 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public abstract class AbstractCloudHeightSourceImpl implements
ICloudHeightSourceImplementation {
private DataTime[] ourTimes;
private Map<DataTime, PluginDataObject[]> pdoMap = new HashMap<DataTime, PluginDataObject[]>();
protected final AbstractRequestableResourceData resourceData;
protected final SoundingSource source;
private Job requestJob;
private long timeInterval;
protected AbstractCloudHeightSourceImpl(SoundingSource source) {
this.source = source;
resourceData = new AbstractRequestableResourceData() {
@Override
protected AbstractVizResource<?, ?> constructResource(
LoadProperties loadProperties, PluginDataObject[] objects)
throws VizException {
// No resource
return null;
}
};
resourceData.setMetadataMap(constructMetadataMap());
timeInterval = getValidTimeInterval();
}
protected abstract HashMap<String, RequestConstraint> constructMetadataMap();
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.CloudHeightAlgorithm.
* ICloudHeightSourceImplementation#getDataTimes()
*/
@Override
public final DataTime[] getDataTimes() {
try {
DataTime[] ourTimes = resourceData.getAvailableTimes();
Arrays.sort(ourTimes);
this.ourTimes = ourTimes;
return ourTimes;
} catch (VizException e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error requesting grib data times", e);
}
return new DataTime[0];
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.CloudHeightAlgorithm.
* ICloudHeightSourceImplementation
* #createSounding(com.vividsolutions.jts.geom.Coordinate,
* com.raytheon.uf.common.time.DataTime)
*/
@Override
public final VerticalSounding createSounding(Coordinate latLon,
DataTime rscTime) {
DataTime[] ourTimes = this.ourTimes;
if (rscTime == null || ourTimes == null || ourTimes.length == 0) {
return null;
}
// TODO: Can we do this on a
// Find best time to use, from A1 SatPVImageDepict
DataTime[] timeToUse = new DataTime[1];
long minDiff = Long.MAX_VALUE;
for (DataTime dt : ourTimes) {
long diff = Math.abs(rscTime.getMatchValid() - dt.getMatchValid());
if (diff < minDiff && diff <= timeInterval) {
minDiff = diff;
timeToUse[0] = dt;
} else if (diff == minDiff
&& dt.getMatchRef() > timeToUse[0].getMatchRef()) {
minDiff = diff;
timeToUse[0] = dt;
}
}
final DataTime time = timeToUse[0];
if (time == null) {
return null;
}
PluginDataObject[] pdos = pdoMap.get(time);
if (pdos == null && time != null) {
if (requestJob == null) {
requestJob = new Job("Requesting " + source.getName() + " Data") {
@Override
protected IStatus run(IProgressMonitor monitor) {
long t0 = System.currentTimeMillis();
try {
PluginDataObject[] reqPdos = resourceData
.getLatestPluginDataObjects(
new DataTime[] { time },
new DataTime[0]);
pdoMap.put(time, reqPdos);
} catch (VizException e) {
// Avoid error every time
pdoMap.put(time, new PluginDataObject[0]);
UFStatus.getHandler()
.handle(Priority.PROBLEM,
"Error requesting metadata for grib sounding",
e);
}
System.out.println("Time to request pdos: "
+ (System.currentTimeMillis() - t0) + "ms");
requestJob = null;
return Status.OK_STATUS;
}
};
requestJob.schedule();
} else {
return CloudHeightAlgorithm.LOADING;
}
}
if (pdos != null && pdos.length > 0) {
return createSoundingInternal(latLon, time, pdos);
}
return null;
}
protected abstract VerticalSounding createSoundingInternal(
Coordinate latLon, DataTime time, PluginDataObject[] pdos);
protected abstract long getValidTimeInterval();
}

View file

@ -25,6 +25,10 @@ import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import javax.measure.quantity.Temperature;
import javax.measure.unit.Unit;
import com.raytheon.uf.common.dataplugin.satellite.units.SatelliteUnits;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.sounding.SoundingLayer;
import com.raytheon.uf.common.sounding.VerticalSounding;
@ -32,8 +36,6 @@ 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.viz.cloudheight.data.CloudHeightData;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource.SourceType;
/**
* Cloud height calculations ported from HH_Grid.C and HH_Climo.C
@ -44,7 +46,7 @@ import com.raytheon.uf.viz.cloudheight.data.SoundingSource.SourceType;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 16, 2009 mschenke Initial creation
*
* Jul 25, 2013 2190 mschenke Genericized algorithm for more sources and non-byte data
* </pre>
*
* @author mschenke
@ -55,11 +57,13 @@ public class CloudHeightCalculatorPorted {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(CloudHeightCalculatorPorted.class);
public static Unit<Temperature> ALGORITHM_UNIT = SatelliteUnits.IR_PIXEL;
public static class CloudHeightResult {
public float value;
public String status = "";
}
private static class Record {
@ -76,8 +80,7 @@ public class CloudHeightCalculatorPorted {
private static Record[][] SoundingJul = new Record[5][4];
public static CloudHeightResult getCloudHeightGrid(float cloudTemp,
VerticalSounding sounding, SoundingSource source,
float[] parcelTrajectory) {
VerticalSounding sounding, float[] parcelTrajectory) {
CloudHeightResult result = new CloudHeightResult();
result.status = "S";
int count = sounding.size();
@ -88,7 +91,10 @@ public class CloudHeightCalculatorPorted {
boolean dwptDrying = false;
float dd1, dd2, dd3, dz, d2x;
float d2xparam;
// Split difference between RAOB/MODEL, not sure where numbers came from
// and would have no idea what to set it for nucaps so splitting the
// difference between grid and raob seems to provide good results
float d2xparam = 0.000245f;
float P2, P1, T2, T1, Z2, Z1, pres, presCloud = 99999.0f;
float Tenv500, Tparcel, Tparcel500, presTrajL, presTrajU;
float presEL;
@ -99,12 +105,6 @@ public class CloudHeightCalculatorPorted {
return result;
}
if (source.getType() == SourceType.RAOB) {
d2xparam = .0005f;
} else {
d2xparam = 1e-5f;
}
warmestTemp = 0;
coldestTemp = 999;
coldestTempSub = count - 1;
@ -436,9 +436,17 @@ public class CloudHeightCalculatorPorted {
return height;
}
public static void findHighPredLowBrightness(byte[] elements,
int numElements, int[] values) {
int highest = 0, pred = 0, lowest = 255;
/**
* Finds the high, predominate, and low brightness values in elements and
* stores in values. Units are that of {@link #ALGORITHM_UNIT}
*
* @param elements
* @param numElements
* @param values
*/
public static void findHighPredLowBrightness(double[] elements,
int numElements, double[] values) {
int highest = Integer.MIN_VALUE, pred = 0, lowest = Integer.MAX_VALUE;
int i, j;
int[] freq = new int[256];
int[] smoothFreq = new int[256];
@ -449,12 +457,15 @@ public class CloudHeightCalculatorPorted {
smoothFreq[i] = 0;
}
for (i = 0; i < numElements; i++) {
if (unsignByte(elements[i]) != 0) {
freq[unsignByte(elements[i])]++;
if (unsignByte(elements[i]) > highest)
highest = unsignByte(elements[i]);
if (unsignByte(elements[i]) < lowest)
lowest = unsignByte(elements[i]);
if (Double.isNaN(elements[i]) == false) {
int value = (int) elements[i];
freq[value] += 1;
if (value < lowest) {
lowest = value;
}
if (value > highest) {
highest = value;
}
}
}

View file

@ -1,281 +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.cloudheight.impl;
import java.awt.Point;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfo;
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoLookup;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.PointUtil;
import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation;
import com.raytheon.uf.common.sounding.SoundingLayer;
import com.raytheon.uf.common.sounding.VerticalSounding;
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.cloudheight.CloudHeightAlgorithm;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource;
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
import com.raytheon.viz.core.map.GeoUtil;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Grid model cloud height sounding implementation
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 18, 2011 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class ModelCloudHeightSourceImplementation extends
AbstractCloudHeightSourceImpl {
private static final String PARAM_TEMP = "T";
private static final String PARAM_DEWPOINT = "DpT";
private static final String PARAM_HEIGHT = "GH";
private Map<DataTime, VerticalSounding[]> soundingMap = new HashMap<DataTime, VerticalSounding[]>();
private Job hdf5Job = null;
public ModelCloudHeightSourceImplementation(SoundingSource source) {
super(source);
}
/**
* Create a sounding at the grid index, given the pdos to use
*
* @param index
* @param objects
* @param derived
* @return
*/
private VerticalSounding createSounding(int index,
List<PluginDataObject> objects) {
Map<Double, SoundingLayer> layerMap = new HashMap<Double, SoundingLayer>();
for (PluginDataObject pdo : objects) {
float[] data = (float[]) pdo.getMessageData();
if (data != null) {
Double level = ((GridRecord) pdo).getLevel().getLevelonevalue();
SoundingLayer layer = layerMap.get(level);
if (layer == null) {
layer = new SoundingLayer();
layer.setPressure(level.floatValue());
layerMap.put(level, layer);
}
float val = data[index];
String param = ((GridRecord) pdo).getParameter()
.getAbbreviation();
if (PARAM_TEMP.equals(param)) {
layer.setTemperature(val);
} else if (PARAM_HEIGHT.equals(param)) {
layer.setGeoHeight(val);
} else if (PARAM_DEWPOINT.equals(param)) {
layer.setDewpoint(val);
}
}
}
VerticalSounding sounding = new VerticalSounding();
sounding.setStationId(source.getName());
sounding.setDataTime(objects.get(0).getDataTime());
for (SoundingLayer layer : layerMap.values()) {
sounding.addLayer(layer);
}
return sounding;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.AbstractCloudHeightSourceImpl#
* constructMetadataMap()
*/
@Override
protected HashMap<String, RequestConstraint> constructMetadataMap() {
HashMap<String, RequestConstraint> requestMap = new HashMap<String, RequestConstraint>();
requestMap.put(GridConstants.PLUGIN_NAME, new RequestConstraint(
GridConstants.GRID));
requestMap.put(GridConstants.DATASET_ID,
new RequestConstraint(source.getName()));
RequestConstraint params = new RequestConstraint();
params.setConstraintType(ConstraintType.IN);
params.addToConstraintValueList(PARAM_TEMP);
params.addToConstraintValueList(PARAM_HEIGHT);
params.addToConstraintValueList(PARAM_DEWPOINT);
requestMap.put(GridConstants.PARAMETER_ABBREVIATION, params);
requestMap.put(GridConstants.MASTER_LEVEL_NAME, new RequestConstraint(
"MB"));
requestMap.put(GridConstants.LEVEL_TWO,
new RequestConstraint(Level.getInvalidLevelValueAsString()));
return requestMap;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.AbstractCloudHeightSourceImpl#
* createSoundingInternal(com.vividsolutions.jts.geom.Coordinate,
* com.raytheon.uf.common.time.DataTime)
*/
@Override
protected synchronized VerticalSounding createSoundingInternal(
Coordinate latLon, final DataTime time,
final PluginDataObject[] pdos) {
GridRecord pdo = (GridRecord) pdos[0];
final ISpatialObject spatial = pdo.getSpatialObject();
Point p = null;
try {
p = PointUtil.determineIndex(latLon, spatial.getCrs(),
MapUtil.getGridGeometry(spatial));
} catch (Exception e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error determining index into grib record", e);
}
if (p == null || p.y < 0 || p.y >= spatial.getNy() || p.x < 0
|| p.x >= spatial.getNx()) {
return null;
}
int index = p.y * spatial.getNx() + p.x;
VerticalSounding[] sounding = soundingMap.get(time);
if (sounding == null) {
if (hdf5Job == null) {
hdf5Job = new Job("Requesting " + source.getName() + " Data") {
@Override
protected IStatus run(IProgressMonitor monitor) {
long t0 = System.currentTimeMillis();
try {
DataCubeContainer.getDataRecords(
Arrays.asList(pdos), Request.ALL, null);
} catch (VizDataCubeException e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error requesting model data for sounding",
e);
}
for (PluginDataObject gr : pdos) {
Object messageData = gr.getMessageData();
IDataRecord record = null;
if (messageData instanceof IDataRecord[]) {
IDataRecord[] records = (IDataRecord[]) messageData;
if (records.length > 0) {
record = records[0];
}
} else if (messageData instanceof IDataRecord) {
record = (IDataRecord) messageData;
}
if (record != null) {
gr.setMessageData(((FloatDataRecord) record)
.getFloatData());
}
}
VerticalSounding[] loadedSounding = new VerticalSounding[spatial
.getNx() * spatial.getNy()];
soundingMap.put(time, loadedSounding);
System.out
.println("Time to request grib sounding data: "
+ (System.currentTimeMillis() - t0)
+ "ms");
hdf5Job = null;
return Status.OK_STATUS;
}
};
hdf5Job.schedule();
return CloudHeightAlgorithm.LOADING;
} else {
return CloudHeightAlgorithm.LOADING;
}
}
VerticalSounding vs = sounding[index];
if (vs == null) {
vs = createSounding(index, Arrays.asList(pdos));
SurfaceObsLocation loc = new SurfaceObsLocation();
loc.setStationId(vs.getStationId());
loc.setLatitude(latLon.y);
loc.setLongitude(latLon.x);
vs.setSpatialInfo(loc);
vs.setName(GeoUtil.formatCoordinate(latLon));
sounding[index] = vs;
}
return vs;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.impl.AbstractCloudHeightSourceImpl#
* getValidTimeInterval
* (com.raytheon.uf.common.dataplugin.PluginDataObject[])
*/
@Override
protected long getValidTimeInterval() {
DatasetInfo gm = DatasetInfoLookup.getInstance().getInfo(
source.getName());
// TODO: Why is Laps null?
int dt = gm != null ? gm.getDt() : 1;
// Convert hours to millis, from A1 SatPVImageDepict.C
return ((dt * 3600 * 1000L) * 3) / 2;
}
}

View file

@ -0,0 +1,583 @@
/**
* 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.cloudheight.rsc;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.measure.Measure;
import javax.measure.converter.UnitConverter;
import javax.measure.quantity.Temperature;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.eclipse.swt.graphics.RGB;
import org.opengis.metadata.spatial.PixelOrientation;
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.sounding.WxMath;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
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.cloudheight.data.CloudHeightData;
import com.raytheon.uf.viz.cloudheight.data.CloudHeightData.DisplayOption;
import com.raytheon.uf.viz.cloudheight.impl.CloudHeightCalculatorPorted;
import com.raytheon.uf.viz.cloudheight.impl.CloudHeightCalculatorPorted.CloudHeightResult;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapDescriptor;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability;
import com.raytheon.viz.core.map.GeoUtil;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Cloud height resource, uses an {@link IVerticalSoundingProvider} to obtain a
* sounding for calculating the height of a satellite temperature reading
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 18, 2011 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CloudHeightResource extends
AbstractVizResource<CloudHeightResourceData, IMapDescriptor> {
/** String id to look for satellite-provided data values */
public static final String SATELLITE_DATA_INTERROGATE_ID = "satelliteDataValue";
/** String id for specifying the cloud top height based on the sat reading */
public static final String HEIGHT_INTERROGATE_ID = "height";
/** String id for specifying the temperature associated with the height */
public static final String DATA_VALUE_INTERROGATE_ID = "dataValue";
private static final CloudHeightData algorithmData = CloudHeightData
.getCloudHeightData();
private static final Unit<Temperature> TEMP_UNIT = SI.CELSIUS;
private UnitConverter tempToK = TEMP_UNIT.getConverterTo(SI.KELVIN);
/** Provider used to provide the sounding for the calculation */
private IVerticalSoundingProvider soundingProvider;
/** Sounding used to calculate the cloud-height */
private VerticalSounding sounding;
/** Temperature cloud-height was calculated for */
private Measure<?, ?> temperature;
/** Height of the temperature value */
private Measure<?, ?> cloudHeight;
/**
* The cloud-height calculated based on {@link DisplayOption}, may be null
* if {@link DisplayOption#NONE} is set
*/
private Measure<?, ?> modeCloudHeight;
/** Status returned from the cloud height calculator */
private String cloudHeightStatus;
/** The location the cloud-height was calculated for */
private Coordinate cloudHeightLocation;
/**
* @param resourceData
* @param loadProperties
*/
protected CloudHeightResource(CloudHeightResourceData resourceData,
LoadProperties loadProperties) {
super(resourceData, loadProperties);
getCapability(ColorableCapability.class).setColor(
new RGB(255, 255, 255));
}
@Override
public String getName() {
return "Cloud Height";
}
@Override
public synchronized String inspect(ReferencedCoordinate coord)
throws VizException {
// Ensure cloud height is computed for this coordinate
computeCloudHeightParameters(coord);
if (sounding == null) {
return null;
} else if (sounding.size() == 0 || cloudHeight == null) {
return "NO "
+ String.valueOf(soundingProvider.getSoundingSource())
.toUpperCase() + " DATA";
}
// Convert cloudHeight to feet and rount to nearest hundreds place
int heightInFeet = ((int) (getDataValue(cloudHeight, NonSI.FOOT) / 100 + 0.5) * 100);
String heightStr = String.valueOf(heightInFeet);
if (modeCloudHeight != null) {
int otherHeightInFeet = ((int) (getDataValue(modeCloudHeight,
NonSI.FOOT) / 100 + 0.5) * 100);
if (otherHeightInFeet >= 0) {
heightStr += "/" + otherHeightInFeet;
}
}
return String.format("%s feet (%s %s)", heightStr, sounding
.getStationId(), cloudHeightStatus != null ? cloudHeightStatus
: "");
}
/**
* Attempts to extract a numeric data value from a {@link Measure} object
* converting it into desiredUnit before returning. {@link Double#NaN} will
* be returned if non-numeric measure or units are not compatible
*
* @param measure
* @param desiredUnit
* @return
*/
private double getDataValue(Measure<?, ?> measure, Unit<?> desiredUnit) {
if (desiredUnit.isCompatible(measure.getUnit())) {
Object measuredObject = measure.getValue();
if (measuredObject instanceof Number) {
return measure.getUnit().getConverterTo(desiredUnit)
.convert(((Number) measuredObject).doubleValue());
}
}
return Double.NaN;
}
@Override
public synchronized Map<String, Object> interrogate(
ReferencedCoordinate coord) throws VizException {
// Ensure cloud height is computed for this resource
computeCloudHeightParameters(coord);
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put(HEIGHT_INTERROGATE_ID, cloudHeight);
dataMap.put(DATA_VALUE_INTERROGATE_ID, temperature);
dataMap.put(DataTime.class.toString(),
sounding != null ? sounding.getDataTime() : null);
return dataMap;
}
private void computeCloudHeightParameters(ReferencedCoordinate coord) {
Coordinate location = null;
Measure<?, ?> cloudHeight = null;
Measure<?, ?> modeCloudHeight = null;
Measure<?, ?> temperature = null;
String cloudHeightStatus = null;
VerticalSounding sounding = null;
IVerticalSoundingProvider provider = null;
// Get coordinate as lat/lon
try {
location = coord.asLatLon();
} catch (Exception e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error converting sample coordinate", e);
}
// Get the provider to use
for (IVerticalSoundingProvider vsp : descriptor.getResourceList()
.getResourcesByTypeAsType(IVerticalSoundingProvider.class)) {
if (vsp.getSoundingSource() != null) {
provider = vsp;
}
}
// Ensure valid provider/location
if (provider != null && location != null) {
if (cloudHeightLocation != null
&& cloudHeightLocation.equals(location)
&& provider == soundingProvider
&& provider.getSoundingSource().equals(
soundingProvider.getSoundingSource())) {
// Don't compute for same point/source
return;
}
FramesInfo currInfo = descriptor.getFramesInfo();
// Get contributing resource
AbstractVizResource<?, ?> contributingResource = null;
float cloudTemp = Float.NaN;
Float otherTempToUse = null;
List<AbstractVizResource<?, ?>> contributors = getValidContributors(
new ArrayList<AbstractVizResource<?, ?>>(),
descriptor.getResourceList());
Collections.reverse(contributors);
for (AbstractVizResource<?, ?> resource : contributors) {
float[] temps = getTemperaturesForResource(resource, currInfo,
location);
if (temps != null) {
contributingResource = resource;
cloudTemp = temps[0];
switch (algorithmData.getDisplayOption()) {
case PEAK:
otherTempToUse = temps[1];
break;
case PREDOMINANT:
otherTempToUse = temps[2];
break;
case LOW:
otherTempToUse = temps[3];
break;
default:
otherTempToUse = null;
break;
}
break;
}
}
if (contributingResource != null) {
// We have valid temperature contributing resource
// Get a sounding for time of contributing resource
sounding = provider.getSounding(
currInfo.getTimeForResource(contributingResource),
location);
if (sounding != null) {
// Sounding found, calculate height of temps
float height = -1, otherHeight = -1;
if (sounding.size() == 0
&& GridConstants.PLUGIN_NAME.equals(provider
.getSoundingSource())) {
// Compute CLIMO VerticalSounding
sounding = new VerticalSounding();
sounding.setStationId("CLIMO");
sounding.setName(GeoUtil.formatCoordinate(location));
int day = Calendar.getInstance().get(
Calendar.DAY_OF_YEAR);
// Populates the sounding
height = CloudHeightCalculatorPorted
.getCloudHeightClimo(
(float) tempToK.convert(cloudTemp),
(float) location.y, day, sounding);
if (otherTempToUse != null) {
// Just calculates the height
otherHeight = CloudHeightCalculatorPorted
.getCloudHeightClimo((float) tempToK
.convert(otherTempToUse),
(float) location.y, day, null);
}
} else if (sounding.size() > 0) {
// use sounding to compute heights
float[] muParcelTrajectory = WxMath
.derivemuParcelTrajectory(sounding);
CloudHeightResult result = CloudHeightCalculatorPorted
.getCloudHeightGrid(
(float) tempToK.convert(cloudTemp),
sounding, muParcelTrajectory);
cloudHeightStatus = result.status;
height = result.value;
if (otherTempToUse != null) {
result = CloudHeightCalculatorPorted
.getCloudHeightGrid((float) tempToK
.convert(otherTempToUse), sounding,
muParcelTrajectory);
otherHeight = result.value;
}
}
if (height >= 0) {
cloudHeight = Measure.valueOf(height, SI.METER);
if (otherHeight >= 0) {
modeCloudHeight = Measure.valueOf(otherHeight,
SI.METER);
}
temperature = Measure.valueOf(cloudTemp, TEMP_UNIT);
}
}
}
}
// Assign newly calculated fields
this.soundingProvider = provider;
this.sounding = sounding;
this.cloudHeight = cloudHeight;
this.modeCloudHeight = modeCloudHeight;
this.temperature = temperature;
this.cloudHeightStatus = cloudHeightStatus;
this.cloudHeightLocation = location;
}
/**
* Returns all resources that have a data unit compatible with
* {@link #TEMP_UNIT} in their {@link ColorMapParameters}.
*
* @param descriptor
* @return
*/
private static List<AbstractVizResource<?, ?>> getValidContributors(
List<AbstractVizResource<?, ?>> resources, ResourceList list) {
for (ResourcePair rp : list) {
if (rp.getProperties().isVisible()
&& isValidContributor(rp.getResource())) {
resources.add(rp.getResource());
}
}
List<AbstractVizResource<?, ?>> groups = list
.getResourcesByType(IResourceGroup.class);
for (AbstractVizResource<?, ?> group : groups) {
if (group.getProperties().isVisible()) {
getValidContributors(resources,
((IResourceGroup) group).getResourceList());
}
}
return resources;
}
public static boolean isValidContributor(AbstractVizResource<?, ?> rsc) {
if (rsc != null && rsc.hasCapability(ColorMapCapability.class)) {
ColorMapParameters params = rsc.getCapability(
ColorMapCapability.class).getColorMapParameters();
if (params != null && params.getDataUnit() != null
&& TEMP_UNIT.isCompatible(params.getDataUnit())) {
return true;
}
}
return false;
}
/**
* Gets the cloud temp, predominate, peak, and low temps for the resource or
* null if not valid temperatures
*
* @param resource
* @param currInfo
* @param location
* @return
*/
private float[] getTemperaturesForResource(
AbstractVizResource<?, ?> resource, FramesInfo currInfo,
Coordinate location) {
float[] temps = null;
// Ensure resource has time at this frame
DataTime timeForRsc = currInfo.getTimeForResource(resource);
if (timeForRsc != null) {
try {
// Verify resource provides expected objects from
// interrogate
Map<String, Object> interMap = resource
.interrogate(new ReferencedCoordinate(location));
if (interMap != null
&& interMap.get(SATELLITE_DATA_INTERROGATE_ID) instanceof Measure
&& interMap
.containsKey(ISpatialObject.class.toString())) {
// Extract temperature values from the resource
float[] rscTemps = extractTemps(location, resource,
(ISpatialObject) interMap.get(ISpatialObject.class
.toString()));
boolean good = true;
for (int i = 0; i < rscTemps.length; ++i) {
if (Float.isNaN(rscTemps[i])) {
good = false;
}
}
if (good) {
temps = rscTemps;
}
}
} catch (VizException e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error interrogating resource", e);
}
}
return temps;
}
private float[] extractTemps(Coordinate latLon,
AbstractVizResource<?, ?> rsc, ISpatialObject spatialObject) {
// Method loosely ported from SatPVImageDepict.C::interogate
float[] temps = new float[] { Float.NaN, Float.NaN, Float.NaN,
Float.NaN };
Coordinate c = MapUtil.latLonToGridCoordinate(latLon,
PixelOrientation.CENTER, spatialObject);
int x = (int) c.x;
int y = (int) c.y;
int nx = spatialObject.getNx();
int ny = spatialObject.getNy();
if (x < 0 || x >= nx || y < 0 || y >= ny) {
return temps;
}
double temp = getTemperature(rsc, latLon);
if (Double.isNaN(temp)) {
return temps;
}
double[] elements = new double[6400];
int numElements = 0;
int i, j, ii, jj;
int yStart = -(int) (algorithmData.getNy() / 2);
int yEnd = (int) algorithmData.getNy() / 2;
int xStart = -(int) (algorithmData.getNx() / 2);
int xEnd = (int) algorithmData.getNx() / 2;
for (j = yStart; j < yEnd; j++) {
jj = y + j;
if (jj < 0 || jj >= ny) {
continue;
}
for (i = xStart; i < xEnd; i++) {
ii = x + i;
if (ii >= 0 && ii < nx) {
elements[numElements++] = getTemperature(rsc,
spatialObject, ii, jj);
}
}
}
UnitConverter converter = CloudHeightCalculatorPorted.ALGORITHM_UNIT
.getConverterTo(TEMP_UNIT);
double[] calculated = new double[3];
CloudHeightCalculatorPorted.findHighPredLowBrightness(elements,
numElements, calculated);
temps[0] = (float) converter.convert(temp);
temps[1] = (float) converter.convert(calculated[0]);
temps[2] = (float) converter.convert(calculated[1]);
temps[3] = (float) converter.convert(calculated[2]);
return temps;
}
/**
* Interrogates the resource at the spatial object's gridX,gridY location
* and reads out the temperature value converting to
* {@link CloudHeightCalculatorPorted#ALGORITHM_UNIT}
*
* @param resource
* @param spatialObject
* @param gridX
* @param gridY
* @return
*/
private double getTemperature(AbstractVizResource<?, ?> resource,
ISpatialObject spatialObject, int gridX, int gridY) {
Coordinate latLon = MapUtil.gridCoordinateToLatLon(new Coordinate(
gridX, gridY), PixelOrientation.CENTER, spatialObject);
return getTemperature(resource, latLon);
}
/**
* Interrogates the resource at the specified lat/lon location and reads out
* the temperature value converting to
* {@link CloudHeightCalculatorPorted#ALGORITHM_UNIT}
*
* @param resource
* @param spatialObject
* @param gridX
* @param gridY
* @return
*/
private double getTemperature(AbstractVizResource<?, ?> resource,
Coordinate latLon) {
double temperature = Double.NaN;
try {
Map<String, Object> dataMap = resource
.interrogate(new ReferencedCoordinate(latLon));
Object obj = dataMap.get(SATELLITE_DATA_INTERROGATE_ID);
if (obj instanceof Measure) {
temperature = getDataValue((Measure<?, ?>) obj,
CloudHeightCalculatorPorted.ALGORITHM_UNIT);
}
} catch (VizException e) {
// Ignore
}
return temperature;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#disposeInternal()
*/
@Override
protected void disposeInternal() {
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#paintInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#initInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget)
*/
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
}
}

View file

@ -20,22 +20,21 @@
package com.raytheon.uf.viz.cloudheight.rsc;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
import com.raytheon.uf.viz.core.exception.NoDataAvailableException;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
/**
* TODO Add Description
* Cloud height resource data, constructs {@link CloudHeightResource}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 5, 2010 mschenke Initial creation
* Jul 18, 2011 2190 mschenke Initial creation
*
* </pre>
*
@ -43,26 +42,43 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
* @version 1.0
*/
public class PopupSkewTResourceData extends AbstractResourceData {
public class CloudHeightResourceData extends AbstractResourceData {
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#construct(com.raytheon
* .uf.viz.core.rsc.LoadProperties,
* com.raytheon.uf.viz.core.drawables.IDescriptor)
*/
@Override
public AbstractVizResource<?, ?> construct(LoadProperties loadProperties,
IDescriptor descriptor) throws VizException {
FramesInfo fi = descriptor.getFramesInfo();
if (fi.getFrameTimes() == null || fi.getFrameTimes().length == 0) {
throw new NoDataAvailableException(getClass());
}
return new PopupSkewTResource(this, loadProperties);
}
@Override
public boolean equals(Object obj) {
return (obj instanceof PopupSkewTResourceData);
return new CloudHeightResource(this, loadProperties);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#update(java.lang.Object
* )
*/
@Override
public void update(Object updateData) {
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
return true;
}
}

View file

@ -1,195 +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.cloudheight.rsc;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.cloudheight.CloudHeightAlgorithm;
import com.raytheon.uf.viz.cloudheight.CloudHeightAlgorithm.ICloudHeightSourceImplementation;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResource;
import com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.ICloudHeightAlgorithm;
import com.vividsolutions.jts.geom.Coordinate;
/**
* TODO Add Description
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 5, 2010 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class PopupSkewTResource extends
AbstractVizResource<PopupSkewTResourceData, MapDescriptor> {
private CloudHeightAlgorithm algorithm;
private CloudHeightResource resource;
protected PopupSkewTResource(PopupSkewTResourceData resourceData,
LoadProperties loadProperties) {
super(resourceData, loadProperties);
}
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
List<CloudHeightResource> chr = descriptor.getResourceList()
.getResourcesByTypeAsType(CloudHeightResource.class);
if (chr.size() > 0) {
resource = chr.get(0);
ICloudHeightAlgorithm alg = resource.getAlgorithm();
if (alg instanceof CloudHeightAlgorithm) {
algorithm = (CloudHeightAlgorithm) alg;
}
}
if (algorithm == null) {
descriptor.getResourceList().removeRsc(this);
throw new VizException("Could not initialize " + getName()
+ ", no CloudHeightAlgorithm found");
}
}
@Override
public String getName() {
String name = "Radar Popup SkewT";
DataTime cur = getCurrentTime();
if (cur != null) {
name += " " + cur.getLegendString();
}
return name;
}
private DataTime getCurrentTime() {
FramesInfo info = descriptor.getFramesInfo();
DataTime[] frameTimes = info.getFrameTimes();
if (frameTimes != null) {
int idx = info.getFrameIndex();
if (idx > -1 && idx < frameTimes.length) {
return frameTimes[idx];
}
}
return null;
}
@Override
public String inspect(ReferencedCoordinate coord) throws VizException {
ICloudHeightSourceImplementation impl = algorithm
.getCurrentImplementation();
if (impl != null) {
algorithm.setSkewT(true);
Coordinate latLon = null;
try {
latLon = coord.asLatLon();
} catch (Exception e) {
}
Float msl = getMSL(coord, descriptor.getResourceList());
if (msl != null && latLon != null) {
VerticalSounding vs = impl.createSounding(latLon,
getCurrentTime());
if (vs != null) {
if (vs != CloudHeightAlgorithm.LOADING) {
algorithm.setSounding(vs);
algorithm.plotHeight(msl, 1e37f);
} else {
issueRefresh();
}
}
}
}
return "_";
}
/**
* Recursively search for msl by interrogating the resources on the list
*
* @param coord
* @param list
* @return
* @throws VizException
*/
private Float getMSL(ReferencedCoordinate coord, ResourceList list)
throws VizException {
Float msl = null;
for (ResourcePair rp : list) {
AbstractVizResource<?, ?> r = rp.getResource();
if (r != null && rp.getProperties().isVisible()) {
Map<String, Object> interrogatedVals = r.interrogate(coord);
if (interrogatedVals != null) {
Object val = interrogatedVals.get("msl");
if (val != null) {
try {
msl = Float.parseFloat(String.valueOf(val));
return msl;
} catch (Throwable t) {
;
}
}
}
if (r instanceof IResourceGroup) {
msl = getMSL(coord, ((IResourceGroup) r).getResourceList());
if (msl != null) {
return msl;
}
}
}
}
return null;
}
@Override
protected void disposeInternal() {
if (algorithm != null) {
algorithm.dispose();
}
}
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
}
}

View file

@ -45,9 +45,9 @@ public abstract class AbstractAWTFont implements IFont {
protected Font font;
protected boolean scaleFont;
protected boolean scaleFont = true;
protected boolean smoothing;
protected boolean smoothing = true;
protected AbstractAWTFont(String fontName, float fontSize, Style[] styles) {
this(new Font(fontName, toAwtStyle(styles), (int) fontSize));

View file

@ -6,51 +6,23 @@ Bundle-Version: 1.12.1174.qualifier
Bundle-Activator: com.raytheon.uf.viz.d2d.core.Activator
Bundle-Vendor: RAYTHEON
Require-Bundle: org.eclipse.core.runtime,
org.apache.commons.lang;bundle-version="2.3.0",
org.apache.commons.collections;bundle-version="3.2.0",
org.eclipse.core.commands,
com.raytheon.uf.viz.core,
org.eclipse.ui,
org.geotools;bundle-version="2.6.4",
com.raytheon.viz.core;bundle-version="1.12.1130",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin;bundle-version="1.12.1174",
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.viz.core.rsc;bundle-version="1.0.0",
com.raytheon.uf.viz.core.maps;bundle-version="1.12.1174",
com.raytheon.uf.common.colormap;bundle-version="1.12.1174"
com.raytheon.viz.ui;bundle-version="1.12.1174",
org.apache.commons.lang;bundle-version="2.3.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Import-Package: com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.geospatial,
com.raytheon.uf.common.localization,
com.raytheon.uf.common.serialization,
com.raytheon.uf.common.serialization.adapters,
com.raytheon.uf.common.serialization.annotations,
com.raytheon.uf.common.serialization.thrift,
com.raytheon.uf.common.status,
com.raytheon.uf.common.time,
com.raytheon.uf.common.time.adapter,
com.raytheon.uf.common.time.util,
com.raytheon.uf.viz.core,
com.raytheon.uf.viz.core.catalog,
com.raytheon.uf.viz.core.comm,
com.raytheon.uf.viz.core.datastructure,
com.raytheon.uf.viz.core.drawables,
com.raytheon.uf.viz.core.exception,
com.raytheon.uf.viz.core.map,
com.raytheon.uf.viz.core.rsc,
com.raytheon.uf.viz.core.rsc.capabilities,
com.raytheon.uf.viz.core.rsc.hdf5,
com.raytheon.uf.viz.core.rsc.legend,
com.raytheon.uf.viz.core.rsc.sampling,
com.raytheon.uf.viz.core.status,
com.raytheon.viz.core,
com.raytheon.viz.core.drawables,
com.raytheon.viz.core.map,
com.raytheon.viz.core.rsc,
org.eclipse.swt.graphics,
org.opengis.referencing.crs
Export-Package: com.raytheon.uf.viz.d2d.core,
com.raytheon.uf.viz.d2d.core.legend,
com.raytheon.uf.viz.d2d.core.map,
com.raytheon.uf.viz.d2d.core.sampling,
com.raytheon.uf.viz.d2d.core.time
Import-Package: com.raytheon.viz.core.imagery,
com.raytheon.viz.core.rsc

View file

@ -1,4 +1,3 @@
com.raytheon.uf.viz.d2d.core.map.D2DMapRenderableDisplay
com.raytheon.uf.viz.d2d.core.time.D2DTimeMatcher
com.raytheon.uf.viz.d2d.core.D2DLoadProperties
com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData

View file

@ -41,14 +41,12 @@ import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.maps.scales.MapScaleRenderableDisplay;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
import com.raytheon.uf.viz.core.rsc.RenderingOrderFactory.ResourceOrder;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.ResourceList.AddListener;
import com.raytheon.uf.viz.core.rsc.capabilities.DensityCapability;
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
import com.raytheon.uf.viz.d2d.core.D2DProperties;
import com.raytheon.uf.viz.d2d.core.ID2DRenderableDisplay;
import com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData;
import com.raytheon.uf.viz.d2d.core.time.D2DTimeMatcher;
import com.raytheon.viz.core.imagery.ImageCombiner;
@ -74,8 +72,6 @@ import com.raytheon.viz.core.imagery.ImageCombiner;
public class D2DMapRenderableDisplay extends MapScaleRenderableDisplay
implements ID2DRenderableDisplay {
private static final CloudHeightResourceData cloudHeightData = new CloudHeightResourceData();
/** The magnification */
@XmlAttribute
protected double magnification = ((Double) VizGlobalsManager
@ -299,12 +295,6 @@ public class D2DMapRenderableDisplay extends MapScaleRenderableDisplay
// Add scale listeners
resourceList.addPostAddListener(getScaleListener());
resourceList.addPostRemoveListener(getScaleListener());
// Add cloud height resource data
ResourcePair rp = ResourcePair
.constructSystemResourcePair(cloudHeightData);
rp.getProperties().setRenderingOrder(ResourceOrder.LOWEST);
resourceList.add(rp);
}
/**

View file

@ -1,149 +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.d2d.core.sampling;
import java.util.ArrayList;
import org.eclipse.jface.action.IMenuManager;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.IMapDescriptor;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.d2d.core.sampling.CloudHeightResourceData.ICloudHeightAlgorithm;
import com.raytheon.viz.ui.cmenu.IContextMenuContributor;
/**
* Cloud height resource, uses the ICloudHeightAlgorithm to compute and sample
* cloud height
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 18, 2011 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CloudHeightResource extends
AbstractVizResource<CloudHeightResourceData, IMapDescriptor> implements
IContextMenuContributor {
private ICloudHeightAlgorithm algorithm;
/**
* @param resourceData
* @param loadProperties
*/
protected CloudHeightResource(CloudHeightResourceData resourceData,
LoadProperties loadProperties) {
super(resourceData, loadProperties);
algorithm = resourceData.getAlgorithm();
dataTimes = new ArrayList<DataTime>();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.ui.cmenu.IContextMenuContributor#addContextMenuItems
* (org.eclipse.jface.action.IMenuManager, int, int)
*/
@Override
public void addContextMenuItems(IMenuManager menuManager, int x, int y) {
if (algorithm.isEnabled(descriptor)) {
algorithm.addContextMenuItems(descriptor, menuManager, x, y);
}
}
@Override
public String inspect(ReferencedCoordinate coord) throws VizException {
try {
if (algorithm.isEnabled(descriptor)) {
return algorithm.inspect(this, coord.asLatLon());
}
} catch (Exception e) {
CloudHeightResourceData.handler.handle(Priority.PROBLEM,
"Error converting coordinate to lat/lon", e);
}
return null;
}
@Override
public DataTime[] getDataTimes() {
return algorithm.getDataTimes();
}
@Override
public String getName() {
return "Cloud Height";
}
public ICloudHeightAlgorithm getAlgorithm() {
return algorithm;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#disposeInternal()
*/
@Override
protected void disposeInternal() {
algorithm.dispose();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#paintInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#initInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget)
*/
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
}
}

View file

@ -1,229 +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.d2d.core.sampling;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IMenuManager;
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.drawables.IDescriptor;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.vividsolutions.jts.geom.Coordinate;
/**
* D2D Cloud height resource data, uses extension point to look up algorithm for
* computing cloud height
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 18, 2011 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class CloudHeightResourceData extends AbstractResourceData {
protected static final IUFStatusHandler handler = UFStatus
.getHandler(CloudHeightResourceData.class);
private static final String CLOUD_HEIGHT_EXTENSION_ID = "com.raytheon.uf.viz.d2d.core.cloudHeightAlgorithm";
public static interface ICloudHeightAlgorithm {
/**
* Add any context menu items used to control the algorithm, only called
* if isEnabled(...) returned true
*
* @param descriptor
* @param manager
* @param x
* @param y
*/
public void addContextMenuItems(IDescriptor descriptor,
IMenuManager manager, int x, int y);
/**
* Get the cloud height algorithm string for the time and point on the
* descriptor. Only called if isEnabled(...) returned true
*
* @param descriptor
* @param time
* @param latLon
* @return
*/
public String inspect(AbstractVizResource<?, ?> reqRsc,
Coordinate latLon);
public boolean isEnabled(IDescriptor descriptor);
public DataTime[] getDataTimes();
public void dispose();
}
private static ICloudHeightAlgorithm DEFAULT_ALGORITHM = new ICloudHeightAlgorithm() {
@Override
public void addContextMenuItems(IDescriptor descriptor,
IMenuManager manager, int x, int y) {
}
@Override
public String inspect(AbstractVizResource<?, ?> reqRsc,
Coordinate latLon) {
return null;
}
@Override
public boolean isEnabled(IDescriptor descriptor) {
return false;
}
@Override
public DataTime[] getDataTimes() {
return new DataTime[0];
}
@Override
public void dispose() {
}
};
private static IConfigurationElement elementToUse = null;
/**
*
*/
public CloudHeightResourceData() {
}
public ICloudHeightAlgorithm getAlgorithm() {
IConfigurationElement elementToUse = getElementToUse();
ICloudHeightAlgorithm algorithm = null;
try {
algorithm = (ICloudHeightAlgorithm) (elementToUse != null ? elementToUse
.createExecutableExtension("class") : DEFAULT_ALGORITHM);
} catch (CoreException e) {
handler.handle(Priority.PROBLEM,
"Error creating ICloudHeightAlgorithm object", e);
}
if (algorithm == null) {
algorithm = DEFAULT_ALGORITHM;
}
return algorithm;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#construct(com.raytheon
* .uf.viz.core.rsc.LoadProperties,
* com.raytheon.uf.viz.core.drawables.IDescriptor)
*/
@Override
public AbstractVizResource<?, ?> construct(LoadProperties loadProperties,
IDescriptor descriptor) throws VizException {
return new CloudHeightResource(this, loadProperties);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#update(java.lang.Object
* )
*/
@Override
public void update(Object updateData) {
}
private static IConfigurationElement getElementToUse() {
if (elementToUse == null) {
try {
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry
.getExtensionPoint(CLOUD_HEIGHT_EXTENSION_ID);
if (point == null) {
throw new VizException(
"Could not find cloud height algorithm extension point");
}
for (IConfigurationElement element : point
.getConfigurationElements()) {
try {
ICloudHeightAlgorithm algorithm = (ICloudHeightAlgorithm) element
.createExecutableExtension("class");
if (algorithm != null) {
elementToUse = element;
break;
}
} catch (CoreException e) {
handler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
} catch (Throwable t) {
handler.handle(Priority.PROBLEM, t.getLocalizedMessage(), t);
}
}
return elementToUse;
}
@Override
public int hashCode() {
return 173;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
return true;
}
}

View file

@ -27,6 +27,7 @@
<import feature="com.raytheon.uf.viz.displays.feature" version="1.0.0.qualifier"/>
<import feature="com.raytheon.uf.viz.cots.feature" version="1.0.0.qualifier"/>
<import feature="com.raytheon.viz.satellite.feature" version="1.0.0.qualifier"/>
<import feature="com.raytheon.uf.viz.npp.feature" version="1.0.0.qualifier"/>
</requires>
<plugin
@ -41,4 +42,18 @@
install-size="0"
version="0.0.0"/>
<plugin
id="com.raytheon.uf.viz.ui.popupskewt"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.viz.d2d.ui.popupskewt"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.viz.d2d.ui.popupskewt</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,18 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: D2D Popup SkewT
Bundle-SymbolicName: com.raytheon.uf.viz.d2d.ui.popupskewt;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.raytheon.uf.viz.d2d.ui.popupskewt.Activator
Bundle-Vendor: RAYTHEON
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.raytheon.uf.viz.cloudheight;bundle-version="1.12.1174",
com.raytheon.uf.viz.ui.popupskewt;bundle-version="1.0.0",
com.raytheon.viz.satellite;bundle-version="1.12.1174",
com.raytheon.uf.viz.npp.viirs;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Import-Package: com.raytheon.viz.core

View file

@ -0,0 +1,6 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.xml,\
localization/

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bundle xmlns:ns2="group" xmlns:ns3="http://www.example.org/productType">
<displayList>
<displays xsi:type="mapRenderableDisplay" zoomLevel="1.0" mapCenter="-96.867249 40.47502100000001 0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<descriptor xsi:type="mapDescriptor">
<resource>
<loadProperties/>
<properties renderingOrderId="LOWEST" isSystemResource="false" isBlinking="false" isMapLayer="false" isHoverOn="false" isVisible="true">
<pdProps maxDisplayWidth="100000000" minDisplayWidth="0"/>
</properties>
<resourceData xsi:type="popupSkewTResourceData">
<resourceName>Radar Popup SkewT</resourceName>
<contextMenuName>Sample Cloud Heights/Radar Skew T</contextMenuName>
</resourceData>
</resource>
</descriptor>
</displays>
</displayList>
</bundle>

View file

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
<!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.

View file

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
<!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.
@ -19,7 +18,7 @@
further_licensing_information.
-->
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contribute xsi:type="bundleItem" file="bundles/popupSkewTBundle.xml"
<contribute xsi:type="bundleItem" file="bundles/popupSkewT/popupSkewTBundle.xml"
menuText="Popup SkewT" id="popupSkewT" timeQuery="false">
</contribute>
</menuTemplate>

View file

@ -20,12 +20,6 @@
-->
<?eclipse version="3.3"?>
<plugin>
<extension
point="com.raytheon.uf.viz.d2d.core.cloudHeightAlgorithm">
<algorithm
class="com.raytheon.uf.viz.cloudheight.CloudHeightAlgorithm">
</algorithm>
</extension>
<extension
point="com.raytheon.uf.viz.localization.localizationpath">
<path
@ -36,4 +30,11 @@
recursive="true">
</path>
</extension>
<extension
point="com.raytheon.viz.ui.displayCustomizer">
<displayCustomizer
customizer="com.raytheon.uf.viz.d2d.ui.popupskewt.D2DPopupSkewTDisplayCustomizer"
perspective="D2D">
</displayCustomizer>
</extension>
</plugin>

View file

@ -0,0 +1,62 @@
package com.raytheon.uf.viz.d2d.ui.popupskewt;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends AbstractUIPlugin {
public static final IUFStatusHandler statusHandler = UFStatus
.getHandler(Activator.class);
// The plug-in ID
public static final String PLUGIN_ID = "com.raytheon.uf.viz.d2d.ui.popupskewt"; //$NON-NLS-1$
// The shared instance
private static Activator plugin;
/**
* The constructor
*/
public Activator() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
* )
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
* )
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static Activator getDefault() {
return plugin;
}
}

View file

@ -0,0 +1,265 @@
/**
* 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.ui.popupskewt;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.raytheon.uf.viz.cloudheight.rsc.CloudHeightResource;
import com.raytheon.uf.viz.cloudheight.rsc.CloudHeightResourceData;
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IRenderableDisplay;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource.ResourceStatus;
import com.raytheon.uf.viz.core.rsc.IInitListener;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.ResourceList.AddListener;
import com.raytheon.uf.viz.core.rsc.ResourceList.RemoveListener;
import com.raytheon.uf.viz.npp.viirs.rsc.VIIRSResourceData;
import com.raytheon.uf.viz.ui.popupskewt.rsc.PopupSkewTResource;
import com.raytheon.uf.viz.ui.popupskewt.rsc.PopupSkewTResourceData;
import com.raytheon.viz.satellite.rsc.SatBlendedResourceData;
import com.raytheon.viz.satellite.rsc.SatResourceData;
import com.raytheon.viz.ui.perspectives.IRenderableDisplayCustomizer;
/**
* Customizes the {@link IRenderableDisplay} by adding the
* {@link CloudHeightResource} and {@link PopupSkewTResource} as system
* resources
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 31, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class D2DPopupSkewTDisplayCustomizer implements
IRenderableDisplayCustomizer {
private static final String RESOURCE_NAME = "Radar Popup SkewT";
private static final String CONTEXT_MENU_NAME = "Sample Cloud Heights/Radar Skew T";
private static Set<Class<?>> COMPATIBLE_CLASSES = new HashSet<Class<?>>();
static {
COMPATIBLE_CLASSES.add(SatResourceData.class);
COMPATIBLE_CLASSES.add(SatBlendedResourceData.class);
COMPATIBLE_CLASSES.add(VIIRSResourceData.class);
}
/** List of listeners we have for renderable displays */
private List<D2DPopupSkewTResourceListener> listeners = new ArrayList<D2DPopupSkewTResourceListener>();
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.perspectives.IRenderableDisplayCustomizer#
* customizeDisplay(com.raytheon.uf.viz.core.drawables.IRenderableDisplay)
*/
@Override
public synchronized void customizeDisplay(IRenderableDisplay display) {
boolean add = true;
for (D2DPopupSkewTResourceListener listener : listeners) {
if (display == listener.getDisplay()) {
add = false;
break;
}
}
if (add) {
listeners.add(new D2DPopupSkewTResourceListener(display));
}
}
@Override
public void uncustomizeDisplay(IRenderableDisplay display) {
D2DPopupSkewTResourceListener toRemove = null;
for (D2DPopupSkewTResourceListener listener : listeners) {
if (listener.getDisplay() == display) {
toRemove = listener;
break;
}
}
if (toRemove != null) {
toRemove.dispose();
listeners.remove(toRemove);
}
}
private static class D2DPopupSkewTResourceListener implements AddListener,
RemoveListener, IInitListener {
private IRenderableDisplay display;
private boolean resourcesAdded = false;
private ResourcePair popupSkewTResource;
private ResourcePair cloudHeightResource;
public D2DPopupSkewTResourceListener(IRenderableDisplay display) {
this.display = display;
IDescriptor descriptor = display.getDescriptor();
ResourceList list = descriptor.getResourceList();
if (hasCompatibleResource(list)) {
addResources(descriptor);
}
list.addPostAddListener(this);
list.addPostRemoveListener(this);
}
public void dispose() {
ResourceList list = display.getDescriptor().getResourceList();
list.removePostAddListener(this);
list.removePostRemoveListener(this);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.ResourceList.RemoveListener#notifyRemove
* (com.raytheon.uf.viz.core.drawables.ResourcePair)
*/
@Override
public synchronized void notifyRemove(ResourcePair rp)
throws VizException {
if (resourcesAdded) {
if (rp.getResource() != null) {
rp.getResource().unregisterListener(this);
}
if (isCompatibleResource(rp)) {
IDescriptor descriptor = display.getDescriptor();
if (hasCompatibleResource(descriptor.getResourceList()) == false) {
removeResources(descriptor);
}
}
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.ResourceList.AddListener#notifyAdd(com
* .raytheon .uf.viz.core.drawables.ResourcePair)
*/
@Override
public synchronized void notifyAdd(ResourcePair rp) throws VizException {
if (!resourcesAdded) {
AbstractVizResource<?, ?> rsc = rp.getResource();
if (rsc != null) {
rsc.registerListener(this);
if (rsc.getStatus() == ResourceStatus.INITIALIZED
&& isCompatibleResource(rp)) {
addResources(display.getDescriptor());
}
}
}
}
private boolean hasCompatibleResource(ResourceList list) {
for (ResourcePair rp : list) {
if (isCompatibleResource(rp)) {
return true;
}
}
return false;
}
private boolean isCompatibleResource(ResourcePair rp) {
return COMPATIBLE_CLASSES.contains(rp.getResourceData().getClass())
&& CloudHeightResource.isValidContributor(rp.getResource());
}
private synchronized void addResources(IDescriptor descriptor) {
if (!resourcesAdded) {
ResourceList list = descriptor.getResourceList();
cloudHeightResource = constructCloudHeightResource();
list.add(cloudHeightResource);
popupSkewTResource = constructPopupSkewTResource();
list.add(popupSkewTResource);
list.instantiateResources(descriptor, true);
resourcesAdded = true;
}
}
private synchronized void removeResources(IDescriptor descriptor) {
if (resourcesAdded) {
if (cloudHeightResource != null) {
descriptor.getResourceList().remove(cloudHeightResource);
cloudHeightResource = null;
}
if (popupSkewTResource != null) {
descriptor.getResourceList().remove(popupSkewTResource);
popupSkewTResource = null;
}
resourcesAdded = false;
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.IInitListener#inited(com.raytheon.uf
* .viz.core.rsc.AbstractVizResource)
*/
@Override
public synchronized void inited(AbstractVizResource<?, ?> rsc) {
if (!resourcesAdded && CloudHeightResource.isValidContributor(rsc)) {
addResources(rsc.getDescriptor());
}
}
public IRenderableDisplay getDisplay() {
return display;
}
}
private static ResourcePair constructCloudHeightResource() {
return ResourcePair
.constructSystemResourcePair(new CloudHeightResourceData());
}
private static ResourcePair constructPopupSkewTResource() {
PopupSkewTResourceData prd = new PopupSkewTResourceData();
prd.setContextMenuName(CONTEXT_MENU_NAME);
prd.setResourceName(RESOURCE_NAME);
prd.setSystem(true);
return ResourcePair.constructSystemResourcePair(prd);
}
}

View file

@ -5,73 +5,8 @@ Bundle-SymbolicName: com.raytheon.uf.viz.d2d.ui;singleton:=true
Bundle-Version: 1.12.1174.qualifier
Bundle-Activator: com.raytheon.uf.viz.d2d.ui.Activator
Bundle-Vendor: RAYTHEON
Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core
Require-Bundle: org.eclipse.core.runtime,
org.geotools,
org.eclipse.swt,
org.eclipse.jface,
javax.measure,
org.eclipse.ui,
com.raytheon.uf.common.status;bundle-version="1.11.1",
com.raytheon.uf.viz.core;bundle-version="1.10.13",
com.raytheon.edex.meteolib;bundle-version="1.11.17",
com.raytheon.uf.viz.xy;bundle-version="1.0.0",
org.eclipse.core.expressions,
com.raytheon.uf.viz.core.maps;bundle-version="1.0.0",
com.raytheon.viz.core;bundle-version="1.12.1130",
com.raytheon.uf.viz.core.rsc;bundle-version="1.0.0",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.raytheon.uf.viz.points;bundle-version="1.0.0",
com.raytheon.uf.common.colormap;bundle-version="1.12.1174"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Import-Package: com.raytheon.uf.common.geospatial,
com.raytheon.uf.common.localization,
com.raytheon.uf.common.serialization,
com.raytheon.uf.common.serialization.adapters,
com.raytheon.uf.common.serialization.annotations,
com.raytheon.uf.common.serialization.thrift,
com.raytheon.uf.common.time,
com.raytheon.uf.viz.core,
com.raytheon.uf.viz.core.comm,
com.raytheon.uf.viz.core.datastructure,
com.raytheon.uf.viz.core.drawables,
com.raytheon.uf.viz.core.exception,
com.raytheon.uf.viz.core.rsc,
com.raytheon.uf.viz.core.rsc.capabilities,
com.raytheon.uf.viz.core.rsc.sampling,
com.raytheon.uf.viz.d2d.core,
com.raytheon.uf.viz.d2d.core.legend,
com.raytheon.uf.viz.d2d.core.map,
com.raytheon.uf.viz.d2d.core.sampling,
com.raytheon.uf.viz.d2d.core.time,
com.raytheon.uf.viz.d2d.ui,
com.raytheon.viz.core,
com.raytheon.viz.core.drawables,
com.raytheon.viz.core.graphing,
com.raytheon.viz.core.graphing.xy,
com.raytheon.viz.core.map,
com.raytheon.viz.core.preferences,
com.raytheon.viz.core.rsc,
com.raytheon.viz.core.slice.request,
com.raytheon.viz.ui,
com.raytheon.viz.ui.actions,
com.raytheon.viz.ui.cmenu,
com.raytheon.viz.ui.color,
com.raytheon.viz.ui.dialogs,
com.raytheon.viz.ui.dialogs.colordialog,
com.raytheon.viz.ui.editor,
com.raytheon.viz.ui.input,
com.raytheon.viz.ui.input.preferences,
com.raytheon.viz.ui.keys,
com.raytheon.viz.ui.panes,
com.raytheon.viz.ui.perspectives,
com.raytheon.viz.ui.statusline,
com.raytheon.viz.ui.tools,
org.apache.batik.bridge,
org.apache.batik.dom.svg,
org.apache.batik.gvt,
org.apache.batik.util
Export-Package: com.raytheon.uf.viz.d2d.ui,
com.raytheon.uf.viz.d2d.ui.actions,
com.raytheon.uf.viz.d2d.ui.dialogs,
@ -80,3 +15,16 @@ Export-Package: com.raytheon.uf.viz.d2d.ui,
com.raytheon.uf.viz.d2d.ui.map.actions,
com.raytheon.uf.viz.d2d.ui.perspectives,
com.raytheon.uf.viz.d2d.ui.time.dialogs
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.ui,
com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.uf.common.colormap;bundle-version="1.12.1174",
com.raytheon.uf.common.util;bundle-version="1.12.1174",
com.raytheon.uf.viz.d2d.core;bundle-version="1.12.1174",
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.viz.core.rsc;bundle-version="1.0.0",
com.raytheon.uf.viz.core.maps;bundle-version="1.12.1174",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.raytheon.uf.viz.xy;bundle-version="1.12.1174"
Import-Package: com.raytheon.viz.core.imagery

View file

@ -36,6 +36,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.npp.sounding.rsc.AbstractNPPNSharpResourceData;
/**
@ -197,7 +198,8 @@ public class CrimssNSharpResourceData extends AbstractNPPNSharpResourceData {
float pressure = pressureArray[j].floatValue();
pressure = (float) pressureConverter.convert(pressure);
float h2o = h2oArray[j].floatValue();
float dpt = convertH2OtoDewpoint(h2o, pressure);
float dpt = NPPSoundingCalculations.convertH2OtoDewpoint(h2o,
pressure);
dpt = (float) dewpointConverter.convert(dpt);
NcSoundingLayer layer = new NcSoundingLayer(pressure,
NcSoundingLayer.MISSING, NcSoundingLayer.MISSING,

View file

@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: NUCAPS Viz Plugin
Bundle-SymbolicName: com.raytheon.uf.viz.npp.nucaps
Bundle-SymbolicName: com.raytheon.uf.viz.npp.nucaps;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.raytheon.uf.viz.npp.nucaps.Activator
Bundle-Vendor: RAYTHEON
@ -20,7 +20,9 @@ Require-Bundle: org.eclipse.core.runtime,
com.raytheon.uf.viz.d2d.nsharp;bundle-version="1.0.0",
gov.noaa.nws.ncep.ui.nsharp;bundle-version="1.0.0",
javax.measure;bundle-version="1.0.0",
meteolib.jni;bundle-version="1.0.0"
meteolib.jni;bundle-version="1.0.0",
com.raytheon.uf.viz.sounding;bundle-version="1.12.1174"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Import-Package: gov.noaa.nws.ncep.edex.common.sounding
Import-Package: com.raytheon.viz.core.map,
gov.noaa.nws.ncep.edex.common.sounding

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<?eclipse version="3.2"?>
<plugin>
<extension
point="com.raytheon.uf.viz.sounding.verticalSoundingProvider">
<verticalSoundingProvider
class="com.raytheon.uf.viz.npp.nucaps.provider.NucapsSoundingProvider"
type="nucaps">
</verticalSoundingProvider>
</extension>
</plugin>

View file

@ -34,6 +34,7 @@ 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.npp.sounding.rsc.AbstractNPPNSharpResourceData;
/**
@ -112,10 +113,13 @@ public class NucapsNSharpResourceData extends AbstractNPPNSharpResourceData {
Number temperature = temperatures[idx];
float h20 = (float) wvMixingRatioConverter
.convert(wvMixingRatios[idx].doubleValue());
float dewpoint = convertH2OtoDewpoint(h20, pressure);
float rh = convertH20ToRelativeHumidity(h20,
(float) temperatureCalcConverter.convert(temperature
.doubleValue()), pressure);
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

View file

@ -0,0 +1,284 @@
/**
* 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.nucaps.provider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.measure.converter.UnitConverter;
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;
import com.raytheon.uf.common.pointdata.PointDataView;
import com.raytheon.uf.common.sounding.SoundingLayer;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
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.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.exception.VizException;
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;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.index.strtree.STRtree;
/**
* NUCAPS implementation of {@link IVerticalSoundingProvider}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 25, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class NucapsSoundingProvider extends
AbstractVerticalSoundingProvider<STRtree> {
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(NucapsSoundingProvider.class);
private static String[] SOUNDING_PARAMS = {
NucapsRecord.PDV_SURFACE_PRESSURE, NucapsRecord.PDV_PRESSURE,
NucapsRecord.PDV_TEMPERATURE,
NucapsRecord.PDV_WATER_VAPOR_MIXING_RATIO };
private static final double ENVELOPE_DISTANCE_DEG = 1.0;
private static final double MAX_SOUNDING_DISTANCE_METERS = 50 * 1000;
private static final long GROUP_TIMERANGE_MILLIS = 15 * TimeUtil.MILLIS_PER_MINUTE;
private static class NucapsVerticalSounding {
private final PointDataView pdv;
private final Coordinate soundingLocation;
private VerticalSounding sounding;
public NucapsVerticalSounding(PointDataView pdv) {
this.pdv = pdv;
soundingLocation = new Coordinate(
pdv.getFloat(NucapsRecord.LONGITUDE),
pdv.getFloat(NucapsRecord.LATITUDE));
}
public Coordinate getSoundingLocation() {
return soundingLocation;
}
public synchronized VerticalSounding getSounding() {
if (sounding == null) {
VerticalSounding sounding = new VerticalSounding();
sounding.setStationId(NucapsRecord.PLUGIN_NAME);
Coordinate location = getSoundingLocation();
sounding.setName(GeoUtil.formatCoordinate(location));
sounding.setLongitude(location.x);
sounding.setLongitude(location.y);
// 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());
// 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());
// 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);
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));
for (int idx = 0; idx < length; ++idx) {
float pressure = (float) dataToSLPressureUnit
.convert(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);
layers.add(new SoundingLayer(pressure, gh,
temperature, dewpoint,
SoundingLayer.MISSING,
SoundingLayer.MISSING,
SoundingLayer.MISSING));
}
}
sounding.addLayers(layers);
}
this.sounding = sounding;
}
return sounding;
}
}
private GeodeticCalculator gc = new GeodeticCalculator();
@Override
protected void populateBaseConstraints(
Map<String, RequestConstraint> constraints) {
super.populateBaseConstraints(constraints);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider#
* getSoundingSource()
*/
@Override
public String getSoundingSource() {
return NucapsRecord.PLUGIN_NAME;
}
@Override
protected DataTime[] queryForSoundingTimes(
Map<String, RequestConstraint> constraints) {
return NPPTimeUtility.groupTimes(
Arrays.asList(super.queryForSoundingTimes(constraints)),
GROUP_TIMERANGE_MILLIS).toArray(new DataTime[0]);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.sounding.providers.AbstractVerticalSoundingProvider
* #queryForData(java.util.Map, com.raytheon.uf.common.time.DataTime,
* com.vividsolutions.jts.geom.Coordinate)
*/
@Override
protected STRtree queryForData(Map<String, RequestConstraint> constraints,
DataTime time, Coordinate location) {
STRtree tree = new STRtree();
try {
PointDataContainer pdc = PointDataRequest.requestPointData(
time.getValidPeriod(), NucapsRecord.PLUGIN_NAME,
SOUNDING_PARAMS, null, constraints);
int size = pdc.getCurrentSz();
for (int i = 0; i < size; ++i) {
NucapsVerticalSounding sounding = new NucapsVerticalSounding(
pdc.readRandom(i));
Envelope env = buildEnvelope(sounding.getSoundingLocation());
tree.insert(env, sounding);
}
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
}
return tree;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.sounding.providers.AbstractVerticalSoundingProvider
* #createSounding(com.raytheon.uf.common.time.DataTime,
* com.raytheon.uf.common.dataplugin.PluginDataObject[],
* com.vividsolutions.jts.geom.Coordinate)
*/
@Override
protected VerticalSounding createSounding(DataTime time, STRtree tree,
Coordinate location) {
Envelope env = buildEnvelope(location);
List<?> results = tree.query(env);
double minDist = Double.MAX_VALUE;
NucapsVerticalSounding soundingToUse = null;
for (Object result : results) {
NucapsVerticalSounding nucapsSounding = (NucapsVerticalSounding) result;
gc.setStartingGeographicPoint(location.x, location.y);
Coordinate soundingLocation = nucapsSounding.getSoundingLocation();
gc.setDestinationGeographicPoint(soundingLocation.x,
soundingLocation.y);
double distance = gc.getOrthodromicDistance();
if (distance < minDist && distance < MAX_SOUNDING_DISTANCE_METERS) {
minDist = distance;
soundingToUse = nucapsSounding;
}
}
VerticalSounding sounding = null;
if (soundingToUse != null) {
sounding = soundingToUse.getSounding();
}
return sounding;
}
private static Envelope buildEnvelope(Coordinate location) {
double longitude = location.x;
double latitude = location.y;
return new Envelope(new Coordinate(longitude - ENVELOPE_DISTANCE_DEG,
latitude - ENVELOPE_DISTANCE_DEG), new Coordinate(longitude
+ ENVELOPE_DISTANCE_DEG, latitude + ENVELOPE_DISTANCE_DEG));
}
}

View file

@ -25,4 +25,5 @@ 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.rsc
Export-Package: com.raytheon.uf.viz.npp.sounding.math,
com.raytheon.uf.viz.npp.sounding.rsc

View file

@ -0,0 +1,97 @@
/**
* 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.SI;
import javax.measure.unit.Unit;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@ -49,6 +48,7 @@ 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,6 +62,7 @@ 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
*
* </pre>
*
@ -107,17 +108,17 @@ public abstract class AbstractNPPNSharpResourceData extends
}
}
protected static final Unit<?> PRESSURE_UNIT = SI.HECTO(SI.PASCAL);
protected static final Unit<?> PRESSURE_UNIT = NPPSoundingCalculations.PRESSURE_UNIT;
protected static final Unit<?> HEIGHT_UNIT = SI.METER;
protected static final Unit<?> HEIGHT_UNIT = NPPSoundingCalculations.HEIGHT_UNIT;
protected static final Unit<?> TEMPERATURE_UNIT = SI.CELSIUS;
protected static final Unit<?> TEMPERATURE_UNIT = NPPSoundingCalculations.TEMPERATURE_UNIT;
protected static final Unit<?> TEMPERATURE_CALC_UNIT = SI.KELVIN;
protected static final Unit<?> TEMPERATURE_CALC_UNIT = NPPSoundingCalculations.TEMPERATURE_CALC_UNIT;
protected static final Unit<?> H2O_UNIT = SI.GRAM.divide(SI.KILOGRAM);
protected static final Unit<?> H2O_UNIT = NPPSoundingCalculations.H2O_UNIT;
protected static final Unit<?> DEWPOINT_UNIT = SI.CELSIUS;
protected static final Unit<?> DEWPOINT_UNIT = NPPSoundingCalculations.DEWPOINT_UNIT;
private final String plugin;
@ -308,32 +309,4 @@ public abstract class AbstractNPPNSharpResourceData extends
}
}
// convert h2o in g/kg and pressure in hPa to dewpoint in kelvin.
protected 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.
protected 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

@ -28,3 +28,4 @@ Require-Bundle: org.eclipse.ui,
com.raytheon.uf.viz.npp;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.uf.viz.npp.viirs.rsc

View file

@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.measure.Measure;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
@ -93,6 +94,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* ------------ ---------- ----------- --------------------------
* Nov 30, 2011 mschenke Initial creation
* Feb 21, 2012 #30 mschenke Fixed sampling issue
* Aug 2, 2013 #2190 mschenke Switched interrogate to use Measure objects
*
* </pre>
*
@ -107,9 +109,8 @@ public class VIIRSResource extends
protected static final IUFStatusHandler statusHandler = UFStatus
.getHandler(VIIRSResource.class);
public static final String DATA_KEY = "dataValue";
public static final String UNIT_KEY = "unit";
/** String id to look for satellite-provided data values */
public static final String SATELLITE_DATA_INTERROGATE_ID = "satelliteDataValue";
private static final DecimalFormat NUMBER_FORMAT = new DecimalFormat("0.00");
@ -501,17 +502,19 @@ public class VIIRSResource extends
public String inspect(ReferencedCoordinate coord) throws VizException {
Map<String, Object> interMap = interrogate(coord);
double value = Double.NaN;
Number dataVal = (Number) interMap.get(DATA_KEY);
Unit<?> unit = Unit.ONE;
Measure<?, ?> dataVal = (Measure<?, ?>) interMap
.get(SATELLITE_DATA_INTERROGATE_ID);
if (dataVal != null) {
value = dataVal.doubleValue();
value = (Double) dataVal.getValue();
unit = dataVal.getUnit();
}
if (Double.isNaN(value)) {
return "NO DATA";
} else {
String inspectStr = NUMBER_FORMAT.format(value);
Unit<?> unit = (Unit<?>) interMap.get(UNIT_KEY);
if (unit != null && unit != Unit.ONE) {
inspectStr += " " + UnitFormat.getUCUMInstance().format(unit);
inspectStr += " " + unit.toString();
}
return inspectStr;
}
@ -530,7 +533,8 @@ public class VIIRSResource extends
Map<String, Object> interMap = new HashMap<String, Object>();
ColorMapParameters params = getCapability(ColorMapCapability.class)
.getColorMapParameters();
interMap.put(UNIT_KEY, params.getDisplayUnit());
double dataValue = Double.NaN;
Unit<?> dataUnit = params.getDisplayUnit();
double noDataValue = params.getNoDataValue();
Coordinate latLon = null;
try {
@ -560,9 +564,15 @@ public class VIIRSResource extends
}
}
}
interMap.put(DATA_KEY,
params.getDataToDisplayConverter().convert(bestValue));
if (Double.isNaN(bestValue) == false) {
dataValue = params.getDataToDisplayConverter().convert(
bestValue);
}
}
interMap.put(SATELLITE_DATA_INTERROGATE_ID,
Measure.valueOf(dataValue, dataUnit));
return interMap;
}

View file

@ -55,6 +55,7 @@ import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 8, 2013 mschenke Initial creation
* Aug 2, 2013 2190 mschenke Moved time grouping functions to utility class
*
* </pre>
*
@ -198,7 +199,7 @@ public abstract class AbstractNppResourceData extends
prev = curr;
DataTimeIterator<T> iter = new DataTimeIterator<T>(
objects.iterator());
curr = match(iter, prev, groupTimeInMillis);
curr = NPPTimeUtility.match(iter, prev, groupTimeInMillis);
if (curr != null) {
group.add(iter.lastAccesed);
}
@ -217,41 +218,8 @@ public abstract class AbstractNppResourceData extends
* @return
*/
public Collection<DataTime> groupTimes(Collection<DataTime> dataTimes) {
long groupTimeInMillis = groupTimeRangeMinutes * 60 * 1000;
List<DataTime> grouped = new ArrayList<DataTime>(dataTimes.size());
Queue<DataTime> objects = new ArrayDeque<DataTime>(dataTimes);
while (objects.size() > 0) {
DataTime current = objects.remove();
TimeRange prev, curr;
prev = curr = current.getValidPeriod();
while (curr != null) {
prev = curr;
curr = match(objects.iterator(), prev, groupTimeInMillis);
}
grouped.add(new DataTime(prev.getStart().getTime(), prev));
}
return grouped;
}
private TimeRange match(Iterator<DataTime> iter, TimeRange time,
long groupTimeInMillis) {
long startT = time.getStart().getTime();
long endT = time.getEnd().getTime();
while (iter.hasNext()) {
DataTime dt = iter.next();
TimeRange dtRange = dt.getValidPeriod();
long s = dtRange.getStart().getTime();
long e = dtRange.getEnd().getTime();
long startCheck = s - groupTimeInMillis;
long endCheck = e + groupTimeInMillis;
if ((startT <= startCheck && endT >= startCheck)
|| (startCheck <= startT && endCheck >= startT)) {
iter.remove();
return new TimeRange(Math.min(s, startT), Math.max(e, endT));
}
}
return null;
return NPPTimeUtility.groupTimes(dataTimes,
groupTimeRangeMinutes * 60 * 1000);
}
/*

View file

@ -0,0 +1,107 @@
/**
* 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;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
/**
* Class for time based utility functions for NPP data
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 26, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class NPPTimeUtility {
/**
* Group the {@link DataTime} collection based on
* {@link #groupTimeRangeMinutes}
*
* @param dataTimes
* @return
*/
public static Collection<DataTime> groupTimes(
Collection<DataTime> dataTimes, long groupTimeInMillis) {
List<DataTime> grouped = new ArrayList<DataTime>(dataTimes.size());
Queue<DataTime> objects = new ArrayDeque<DataTime>(dataTimes);
while (objects.size() > 0) {
DataTime current = objects.remove();
TimeRange prev, curr;
prev = curr = current.getValidPeriod();
while (curr != null) {
prev = curr;
curr = match(objects.iterator(), prev, groupTimeInMillis);
}
grouped.add(new DataTime(prev.getStart().getTime(), prev));
}
return grouped;
}
/**
* Given a {@link DataTime} iterator and an existing time range, find a
* {@link DataTime} that can included in the range based on
* groupTimeInMillis. That DataTime is then removed from the iterator.
* Returns the new TimeRange or null if no DataTime could be included
*
* @param iter
* @param time
* @param groupTimeInMillis
* @return
*/
public static TimeRange match(Iterator<DataTime> iter, TimeRange time,
long groupTimeInMillis) {
long startT = time.getStart().getTime();
long endT = time.getEnd().getTime();
while (iter.hasNext()) {
DataTime dt = iter.next();
TimeRange dtRange = dt.getValidPeriod();
long s = dtRange.getStart().getTime();
long e = dtRange.getEnd().getTime();
long startCheck = s - groupTimeInMillis;
long endCheck = e + groupTimeInMillis;
if ((startT <= startCheck && endT >= startCheck)
|| (startCheck <= startT && endCheck >= startT)) {
iter.remove();
return new TimeRange(Math.min(s, startT), Math.max(e, endT));
}
}
return null;
}
}

View file

@ -14,6 +14,7 @@ Require-Bundle: org.eclipse.core.runtime,
com.raytheon.uf.common.datastorage;bundle-version="1.12.1174",
com.raytheon.uf.common.dataquery;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin.grid;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin.bufrua;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin.goessounding;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin.poessounding;bundle-version="1.0.0",
com.raytheon.uf.common.dataplugin.profiler;bundle-version="1.12.1174",
@ -27,5 +28,6 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Eclipse-BuddyPolicy: registered
Export-Package: com.raytheon.uf.viz.sounding,
com.raytheon.uf.viz.sounding.adapters
com.raytheon.uf.viz.sounding.adapters,
com.raytheon.uf.viz.sounding.providers
Import-Package: com.raytheon.viz.core.map

View file

@ -21,6 +21,8 @@
<?eclipse version="3.2"?>
<plugin>
<extension-point id="com.raytheon.uf.viz.sounding.verticalSoundingAdapter" name="VerticalSoundingAdapter" schema="schema/verticalSoundingAdapter.exsd"/>
<extension-point id="com.raytheon.uf.viz.sounding.verticalSoundingProvider" name="VerticalSoundingProvider" schema="schema/verticalSoundingProvider.exsd"/>
<extension
point="com.raytheon.uf.viz.sounding.verticalSoundingAdapter">
<verticalSoundingAdapter
@ -54,4 +56,16 @@
name="VwpSoundingAdapter">
</verticalSoundingAdapter>
</extension>
<extension
point="com.raytheon.uf.viz.sounding.verticalSoundingProvider">
<verticalSoundingProvider
class="com.raytheon.uf.viz.sounding.providers.BufruaSoundingProvider"
type="bufrua">
</verticalSoundingProvider>
<verticalSoundingProvider
class="com.raytheon.uf.viz.sounding.providers.GridSoundingProvider"
type="grid">
</verticalSoundingProvider>
</extension>
</plugin>

View file

@ -0,0 +1,109 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="com.raytheon.uf.viz.sounding" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="com.raytheon.uf.viz.sounding" id="com.raytheon.uf.viz.sounding.verticalSoundingProvider" name="verticalSoundingProvider"/>
</appInfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="verticalSoundingProvider"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="verticalSoundingProvider">
<complexType>
<attribute name="type" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn="com.raytheon.uf.viz.sounding.providers.AbstractVerticalSoundingProvider:"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiinfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>

View file

@ -22,11 +22,17 @@ package com.raytheon.uf.viz.sounding;
import org.eclipse.core.runtime.Plugin;
import org.osgi.framework.BundleContext;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends Plugin {
public static final IUFStatusHandler statusHandler = UFStatus
.getHandler(Activator.class);
// The plug-in ID
public static final String PLUGIN_ID = "com.raytheon.uf.viz.sounding";
@ -41,7 +47,9 @@ public class Activator extends Plugin {
/*
* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
*
* @see
* org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
super.start(context);
@ -50,7 +58,9 @@ public class Activator extends Plugin {
/*
* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
*
* @see
* org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
plugin = null;

View file

@ -0,0 +1,71 @@
/**
* 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.sounding.providers;
import java.util.Map;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.catalog.LayerProperty;
import com.raytheon.uf.viz.core.datastructure.DataCubeContainer;
import com.raytheon.uf.viz.core.exception.VizException;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Abstract {@link IVerticalSoundingProvider} that uses {@link PluginDataObject}
* s for sounding creation
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 26, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public abstract class AbstractPDOVerticalSoundingProvider extends
AbstractVerticalSoundingProvider<PluginDataObject[]> {
@Override
protected PluginDataObject[] queryForData(
Map<String, RequestConstraint> constraints, DataTime time,
Coordinate location) {
try {
LayerProperty props = new LayerProperty();
props.setEntryTimes(new DataTime[] { time });
props.setSelectedEntryTimes(new DataTime[] { time });
props.setEntryQueryParameters(constraints, false);
return DataCubeContainer.getData(props, Integer.MAX_VALUE).toArray(
new PluginDataObject[0]);
} catch (VizException e) {
throw new RuntimeException("Error querying for sounding records: "
+ constraints, e);
}
}
}

View file

@ -0,0 +1,140 @@
/**
* 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.sounding.providers;
import java.util.HashMap;
import java.util.Map;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
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.vividsolutions.jts.geom.Coordinate;
/**
* Abstract implementation of {@link IVerticalSoundingProvider}, attempts to do
* {@link DataTime} and {@link PluginDataObject} retrieval in a common way
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 22, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public abstract class AbstractVerticalSoundingProvider<T> implements
IVerticalSoundingProvider {
protected static final String DATATIME_REQUEST_FIELD_ID = "dataTime";
private Map<String, RequestConstraint> constraints;
private DataTime[] dataTimes;
private Map<DataTime, T> dataMap = new HashMap<DataTime, T>();
void setConstraints(Map<String, RequestConstraint> constraints) {
if (constraints == null) {
throw new IllegalArgumentException(
"Sounding constraints must not be null");
}
this.constraints = constraints;
populateBaseConstraints(this.constraints);
}
/**
* Method classes can override to add to the base constraints
*
* @param constraints
*/
protected void populateBaseConstraints(
Map<String, RequestConstraint> constraints) {
// Default does nothing
}
@Override
public final DataTime[] getSoundingTimes() {
if (dataTimes == null) {
dataTimes = queryForSoundingTimes(new HashMap<String, RequestConstraint>(
constraints));
}
return dataTimes;
}
protected DataTime[] queryForSoundingTimes(
Map<String, RequestConstraint> constraints) {
DbQueryRequest request = new DbQueryRequest();
request.setConstraints(new HashMap<String, RequestConstraint>(
constraints));
request.setDistinct(true);
request.addRequestField(DATATIME_REQUEST_FIELD_ID);
try {
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
return response.getFieldObjects(DATATIME_REQUEST_FIELD_ID,
DataTime.class);
} catch (VizException e) {
throw new RuntimeException(
"Error querying for available sounding times", e);
}
}
@Override
public final VerticalSounding getSounding(DataTime time, Coordinate location) {
T data = dataMap.get(time);
if (data == null) {
data = queryForData(new HashMap<String, RequestConstraint>(
this.constraints), time, location);
dataMap.put(time, data);
}
VerticalSounding sounding = null;
if (data != null) {
sounding = createSounding(time, data, location);
}
return sounding;
}
protected abstract T queryForData(
Map<String, RequestConstraint> constraints, DataTime time,
Coordinate location);
/**
* Given records and a location, query for
*
* @param data
* @param location
* @return
*/
protected abstract VerticalSounding createSounding(DataTime time,
T records, Coordinate location);
}

View file

@ -17,30 +17,37 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.cloudheight.impl;
package com.raytheon.uf.viz.sounding.providers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.geotools.geometry.jts.JTS;
import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.bufrua.UAObs;
import com.raytheon.uf.common.dataplugin.bufrua.UAObsAdapter;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.TimeQueryRequest;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.sounding.SoundingLayer;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.cloudheight.data.CloudHeightData;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.sounding.Activator;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.index.strtree.STRtree;
/**
* Raob cloud height sounding implementation, requests soundings for all
* stations
* {@link IVerticalSoundingProvider} implementation using bufrua data
*
* <pre>
*
@ -48,7 +55,7 @@ import com.vividsolutions.jts.index.strtree.STRtree;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 18, 2011 mschenke Initial creation
* Jul 22, 2013 2190 mschenke Initial creation
*
* </pre>
*
@ -56,45 +63,39 @@ import com.vividsolutions.jts.index.strtree.STRtree;
* @version 1.0
*/
public class RaobCloudHeightSourceImplementation extends
AbstractCloudHeightSourceImpl {
public class BufruaSoundingProvider extends AbstractPDOVerticalSoundingProvider {
private static final double MAX_MOUSE_DISTANCE_DEG = 5.0;
private Map<DataTime, STRtree> searchMap = new HashMap<DataTime, STRtree>();
/**
*
*/
public RaobCloudHeightSourceImplementation(SoundingSource source) {
super(source);
resourceData.setBinOffset(new BinOffset(3600, 3600));
@Override
protected DataTime[] queryForSoundingTimes(
Map<String, RequestConstraint> constraints) {
TimeQueryRequest request = new TimeQueryRequest();
request.setPluginName("bufrua");
request.setBinOffset(new BinOffset(3600, 3600));
request.setQueryTerms(constraints);
try {
List<?> times = (List<?>) ThriftClient.sendRequest(request);
return times.toArray(new DataTime[0]);
} catch (VizException e) {
throw new RuntimeException(
"Error querying for available sounding times", e);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.AbstractCloudHeightSourceImpl#
* constructMetadataMap()
* @see
* com.raytheon.uf.viz.sounding.providers.AbstractVerticalSoundingProvider
* #createSounding(com.raytheon.uf.common.dataplugin.PluginDataObject[],
* com.vividsolutions.jts.geom.Coordinate)
*/
@Override
protected HashMap<String, RequestConstraint> constructMetadataMap() {
HashMap<String, RequestConstraint> requestMap = new HashMap<String, RequestConstraint>();
requestMap.put("pluginName", new RequestConstraint("bufrua"));
return requestMap;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.AbstractCloudHeightSourceImpl#
* createSoundingInternal(com.vividsolutions.jts.geom.Coordinate,
* com.raytheon.uf.common.time.DataTime)
*/
@Override
protected VerticalSounding createSoundingInternal(Coordinate latLon,
DataTime time, PluginDataObject[] pdos) {
CloudHeightData chd = CloudHeightData.getCloudHeightData();
double maxMouseDistanceDeg = chd.getMaxMouseDistanceDeg();
protected VerticalSounding createSounding(DataTime time,
PluginDataObject[] records, Coordinate location) {
STRtree searchTree = searchMap.get(time);
if (searchTree == null) {
long t0 = System.currentTimeMillis();
@ -102,7 +103,7 @@ public class RaobCloudHeightSourceImplementation extends
searchMap.put(time, searchTree);
Map<String, List<PluginDataObject>> pdoListMap = new HashMap<String, List<PluginDataObject>>();
for (PluginDataObject pdo : pdos) {
for (PluginDataObject pdo : records) {
UAObs obs = (UAObs) pdo;
List<PluginDataObject> pdoList = pdoListMap.get(obs
.getStationId());
@ -155,20 +156,29 @@ public class RaobCloudHeightSourceImplementation extends
// Find the station to query
// create envelope
Coordinate p1 = new Coordinate(latLon.x + maxMouseDistanceDeg, latLon.y
+ maxMouseDistanceDeg);
Coordinate p2 = new Coordinate(latLon.x - maxMouseDistanceDeg, latLon.y
- maxMouseDistanceDeg);
Coordinate p1 = new Coordinate(location.x + MAX_MOUSE_DISTANCE_DEG,
location.y + MAX_MOUSE_DISTANCE_DEG);
Coordinate p2 = new Coordinate(location.x - MAX_MOUSE_DISTANCE_DEG,
location.y - MAX_MOUSE_DISTANCE_DEG);
Envelope env = new Envelope(p1, p2);
// Find the closest station and retrieve the sounding
VerticalSounding closest = null;
double closestDist = Double.MAX_VALUE;
List<?> results = searchTree.query(env);
for (Object obj : results) {
VerticalSounding sounding = (VerticalSounding) obj;
Coordinate c = new Coordinate(sounding.getLongitude(),
sounding.getLatitude());
double distance = c.distance(latLon);
Coordinate c = sounding.getSpatialInfo().getLocation()
.getCoordinate();
double distance = Double.MAX_VALUE;
try {
distance = JTS.orthodromicDistance(c, location,
MapUtil.LATLON_PROJECTION);
} catch (TransformException e) {
Activator.statusHandler.handle(Priority.INFO,
"Error computing distance", e);
distance = c.distance(location);
}
if (distance < closestDist) {
closestDist = distance;
closest = sounding;
@ -188,12 +198,11 @@ public class RaobCloudHeightSourceImplementation extends
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.cloudheight.impl.AbstractCloudHeightSourceImpl#
* getValidTimeInterval()
* @see com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider#
* getSoundingSource()
*/
@Override
protected long getValidTimeInterval() {
// 18 hours in millis, from A1 SatPVImageDepict.C
return 18 * 3600 * 1000;
public String getSoundingSource() {
return "RAOB";
}
}

View file

@ -0,0 +1,285 @@
/**
* 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.sounding.providers;
import java.awt.Point;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.grid.GridConstants;
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.ISpatialObject;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.PointUtil;
import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation;
import com.raytheon.uf.common.sounding.SoundingLayer;
import com.raytheon.uf.common.sounding.VerticalSounding;
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.datastructure.DataCubeContainer;
import com.raytheon.uf.viz.core.datastructure.VizDataCubeException;
import com.raytheon.viz.core.map.GeoUtil;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Grid sounding provider
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 22, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class GridSoundingProvider extends AbstractPDOVerticalSoundingProvider {
private static final String PARAM_TEMP = "T";
private static final String PARAM_DEWPOINT = "DpT";
private static final String PARAM_HEIGHT = "GH";
private class GridSoundingJob extends Job {
private final PluginDataObject[] records;
private VerticalSounding[] soundings;
/**
* @param name
*/
public GridSoundingJob(String jobName, PluginDataObject[] records) {
super(jobName);
this.records = records;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
* IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
long t0 = System.currentTimeMillis();
try {
DataCubeContainer.getDataRecords(Arrays.asList(records),
Request.ALL, null);
} catch (VizDataCubeException e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error requesting model data for sounding", e);
}
Integer size = null;
for (PluginDataObject gr : records) {
Object messageData = gr.getMessageData();
IDataRecord record = null;
if (messageData instanceof IDataRecord[]) {
IDataRecord[] records = (IDataRecord[]) messageData;
if (records.length > 0) {
record = records[0];
}
} else if (messageData instanceof IDataRecord) {
record = (IDataRecord) messageData;
}
if (record != null) {
float[] floats = ((FloatDataRecord) record).getFloatData();
if (size == null) {
size = floats.length;
} else if (size != floats.length) {
throw new IllegalStateException(
"Grid sounding records returned do not have same sized dimensions");
}
gr.setMessageData(floats);
}
}
if (size != null) {
this.soundings = new VerticalSounding[size];
}
System.out.println("Time to request grib sounding data: "
+ (System.currentTimeMillis() - t0) + "ms");
return Status.OK_STATUS;
}
public VerticalSounding[] getSoundings() {
return soundings;
}
}
private Map<DataTime, GridSoundingJob> soundings = new HashMap<DataTime, GridSoundingJob>();
private String modelName = "Unknown";
@Override
protected void populateBaseConstraints(
Map<String, RequestConstraint> constraints) {
if (constraints.containsKey(GridConstants.DATASET_ID)) {
modelName = constraints.get(GridConstants.DATASET_ID)
.getConstraintValue();
}
RequestConstraint params = new RequestConstraint();
params.setConstraintType(ConstraintType.IN);
params.addToConstraintValueList(PARAM_TEMP);
params.addToConstraintValueList(PARAM_HEIGHT);
params.addToConstraintValueList(PARAM_DEWPOINT);
constraints.put(GridConstants.PARAMETER_ABBREVIATION, params);
constraints.put(GridConstants.MASTER_LEVEL_NAME, new RequestConstraint(
"MB"));
constraints.put(GridConstants.LEVEL_TWO,
new RequestConstraint(Level.getInvalidLevelValueAsString()));
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.sounding.providers.AbstractVerticalSoundingProvider
* #createSounding(com.raytheon.uf.common.dataplugin.PluginDataObject[],
* com.vividsolutions.jts.geom.Coordinate)
*/
@Override
protected VerticalSounding createSounding(DataTime time,
PluginDataObject[] records, Coordinate location) {
GridRecord pdo = (GridRecord) records[0];
ISpatialObject spatial = pdo.getSpatialObject();
Point p = null;
try {
p = PointUtil.determineIndex(location, spatial.getCrs(),
MapUtil.getGridGeometry(spatial));
} catch (Exception e) {
UFStatus.getHandler().handle(Priority.PROBLEM,
"Error determining index into grib record", e);
}
if (p == null || p.y < 0 || p.y >= spatial.getNy() || p.x < 0
|| p.x >= spatial.getNx()) {
return null;
}
int index = p.y * spatial.getNx() + p.x;
GridSoundingJob soundingJob = soundings.get(time);
if (soundingJob == null) {
soundingJob = new GridSoundingJob("Loading " + modelName + " Data",
records);
soundings.put(time, soundingJob);
soundingJob.schedule();
}
VerticalSounding vs = null;
VerticalSounding[] sounding = soundingJob.getSoundings();
if (sounding != null) {
vs = sounding[index];
if (vs == null) {
vs = createSounding(index, records);
SurfaceObsLocation loc = new SurfaceObsLocation();
loc.setStationId(vs.getStationId());
loc.setLatitude(location.y);
loc.setLongitude(location.x);
vs.setSpatialInfo(loc);
vs.setName(GeoUtil.formatCoordinate(location));
sounding[index] = vs;
}
}
return vs;
}
/**
* @param index
* @param asList
* @return
*/
private VerticalSounding createSounding(int index,
PluginDataObject[] records) {
Map<Double, SoundingLayer> layerMap = new HashMap<Double, SoundingLayer>();
for (PluginDataObject pdo : records) {
float[] data = (float[]) pdo.getMessageData();
if (data != null) {
Double level = ((GridRecord) pdo).getLevel().getLevelonevalue();
SoundingLayer layer = layerMap.get(level);
if (layer == null) {
layer = new SoundingLayer();
layer.setPressure(level.floatValue());
layerMap.put(level, layer);
}
float val = data[index];
String param = ((GridRecord) pdo).getParameter()
.getAbbreviation();
if (PARAM_TEMP.equals(param)) {
layer.setTemperature(val);
} else if (PARAM_HEIGHT.equals(param)) {
layer.setGeoHeight(val);
} else if (PARAM_DEWPOINT.equals(param)) {
layer.setDewpoint(val);
}
}
}
VerticalSounding sounding = new VerticalSounding();
sounding.setStationId(modelName);
for (SoundingLayer layer : layerMap.values()) {
sounding.addLayer(layer);
}
return sounding;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider#
* getSoundingSource()
*/
@Override
public String getSoundingSource() {
return GridConstants.PLUGIN_NAME;
}
}

View file

@ -0,0 +1,130 @@
/**
* 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.sounding.providers;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.sounding.Activator;
/**
* Factory for constructing {@link IVerticalSoundingProvider}s.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 22, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class VerticalSoundingProviderFactory {
private static final String VERTICAL_SOUNDING_ADAPTER_EXTENSION = Activator.PLUGIN_ID
+ ".verticalSoundingProvider";
private static final String TYPE_EXTENSION_ATTR_ID = "type";
private static final String CLASS_EXTENSION_ATTR_ID = "class";
private static Map<String, IConfigurationElement> extensionMap = new HashMap<String, IConfigurationElement>();
static {
// Internally uses extension point to look up available providers
IExtensionRegistry registry = Platform.getExtensionRegistry();
if (registry != null) {
IExtensionPoint point = registry
.getExtensionPoint(VERTICAL_SOUNDING_ADAPTER_EXTENSION);
if (point != null) {
IExtension[] extensions = point.getExtensions();
for (IExtension ext : extensions) {
IConfigurationElement[] config = ext
.getConfigurationElements();
for (IConfigurationElement cfg : config) {
String type = cfg.getAttribute(TYPE_EXTENSION_ATTR_ID);
if (extensionMap.containsKey(type) == false
&& cfg.getAttribute(CLASS_EXTENSION_ATTR_ID) != null) {
extensionMap.put(type, cfg);
}
}
}
}
}
}
/**
* Gets an {@link IVerticalSoundingProvider} for the type/constraints. Will
* return null if none available for the type
*
* @param type
* @param soundingConstraints
* @return
*/
public static IVerticalSoundingProvider getVerticalSoundingProvider(
String type, Map<String, RequestConstraint> soundingConstraints) {
AbstractVerticalSoundingProvider<?> provider = null;
IConfigurationElement element = extensionMap.get(type);
if (element != null) {
try {
provider = (AbstractVerticalSoundingProvider<?>) element
.createExecutableExtension(CLASS_EXTENSION_ATTR_ID);
if (soundingConstraints != null) {
provider.setConstraints(new HashMap<String, RequestConstraint>(
soundingConstraints));
}
} catch (CoreException e) {
Activator.statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
} else {
Activator.statusHandler.handle(Priority.INFO,
"No sounding provider registered for type: " + type);
}
return provider;
}
/**
* Checks if an {@link IVerticalSoundingProvider} is registered for the
* specified sounding type
*
* @param type
* @return
*/
public static boolean hasProviderForType(String type) {
return extensionMap.containsKey(type);
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.viz.ui.popupskewt</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,24 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Popup Skewt
Bundle-SymbolicName: com.raytheon.uf.viz.ui.popupskewt;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.raytheon.uf.viz.ui.popupskewt.Activator
Bundle-Vendor: RAYTHEON
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.ui;bundle-version="3.8.2",
com.raytheon.uf.common.sounding;bundle-version="1.12.1174",
com.raytheon.uf.common.geospatial;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.viz.ui;bundle-version="1.12.1174",
com.raytheon.uf.viz.sounding;bundle-version="1.12.1174",
com.raytheon.viz.core.graphing;bundle-version="1.12.1174",
com.raytheon.edex.meteolib;bundle-version="1.12.1174",
javax.measure;bundle-version="1.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.uf.viz.ui.popupskewt.rsc,
com.raytheon.uf.viz.ui.popupskewt.ui

View file

@ -0,0 +1 @@
com.raytheon.uf.viz.ui.popupskewt.rsc.PopupSkewTResourceData

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
localization/

View file

@ -0,0 +1,69 @@
<soundingSources>
<!-- Sounding Source Format:
<source type="<sounding source ext adapter>"
displayString="<User displayed String>"
validTimeInterval="<valid time interval in minutes>">
<constraints>
// Any custom metadata mappings for data retrieval
</constraints>
</source>
-->
<source type="grid" displayString="NAM" validTimeInterval="540">
<constraints>
<mapping key="pluginName">
<constraint constraintValue="grid"/>
</mapping>
<mapping key="info.datasetId">
<constraint constraintValue="ETA"/>
</mapping>
</constraints>
</source>
<source type="grid" displayString="GFS" validTimeInterval="540">
<constraints>
<mapping key="pluginName">
<constraint constraintValue="grid"/>
</mapping>
<mapping key="info.datasetId">
<constraint constraintValue="GFS212"/>
</mapping>
</constraints>
</source>
<source type="grid" displayString="RAP" validTimeInterval="90">
<constraints>
<mapping key="pluginName">
<constraint constraintValue="grid"/>
</mapping>
<mapping key="info.datasetId">
<constraint constraintValue="RUC236"/>
</mapping>
</constraints>
</source>
<source type="grid" displayString="Laps" validTimeInterval="90">
<constraints>
<mapping key="pluginName">
<constraint constraintValue="grid"/>
</mapping>
<mapping key="info.datasetId">
<constraint constraintValue="Laps"/>
</mapping>
</constraints>
</source>
<source type="bufrua" displayString="From Raobs" validTimeInterval="1080">
<constraints>
<mapping key="pluginName">
<constraint constraintValue="bufrua"/>
</mapping>
</constraints>
</source>
<source type="nucaps" displayString="NUCAPS" validTimeInterval="90">
<constraints>
<mapping key="pluginName">
<constraint constraintValue="nucaps"/>
</mapping>
</constraints>
</source>
</soundingSources>

View file

@ -0,0 +1,41 @@
package com.raytheon.uf.viz.ui.popupskewt;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
public class Activator implements BundleActivator {
public static IUFStatusHandler statusHandler = UFStatus
.getHandler(Activator.class);
private static BundleContext context;
static BundleContext getContext() {
return context;
}
/*
* (non-Javadoc)
*
* @see
* org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
* )
*/
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
}
/*
* (non-Javadoc)
*
* @see
* org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
}
}

View file

@ -0,0 +1,115 @@
/**
* 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.ui.popupskewt.config;
import java.util.HashMap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestableMetadataMarshaller;
/**
* Source configuration for popup-skewt sounding provider
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 19, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class SoundingSource {
@XmlAttribute
private String type;
@XmlAttribute
private String displayString;
@XmlAttribute
private long validTimeInterval;
@XmlJavaTypeAdapter(value = RequestableMetadataMarshaller.class)
protected HashMap<String, RequestConstraint> constraints = new HashMap<String, RequestConstraint>();
/**
* The type of the source (pluginName)
*
* @return
*/
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
/**
* Display string for the source
*
* @return
*/
public String getDisplayString() {
return displayString;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
/**
* The valid time interval for data in minutes
*
* @return
*/
public long getValidTimeInterval() {
return validTimeInterval;
}
public void setValidTimeInterval(long validTimeInterval) {
this.validTimeInterval = validTimeInterval;
}
/**
* The request constraints for the source
*
* @return
*/
public HashMap<String, RequestConstraint> getConstraints() {
return constraints;
}
public void setConstraints(HashMap<String, RequestConstraint> constraints) {
this.constraints = constraints;
}
}

View file

@ -0,0 +1,58 @@
/**
* 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.ui.popupskewt.config;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Config object for available sounding sources
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 19, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
@XmlRootElement(name = "soundingSources")
@XmlAccessorType(XmlAccessType.NONE)
public class SoundingSourceConfig {
@XmlElement(name = "source")
private SoundingSource[] sources;
public SoundingSource[] getSources() {
return sources;
}
public void setSources(SoundingSource[] sources) {
this.sources = sources;
}
}

View file

@ -0,0 +1,94 @@
/**
* 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.ui.popupskewt.config;
import javax.xml.bind.JAXBException;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.serialization.JAXBManager;
import com.raytheon.uf.common.serialization.SerializationException;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.ui.popupskewt.Activator;
/**
* Configuration factory for getting the available {@link SoundingSource}s
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 19, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class SoundingSourceConfigFactory {
private static final String SKEWT_SOURCES_DIR = "popupSkewT";
private static final String SKEWT_SOURCES_FILE = "sources.xml";
private static SoundingSource[] sources;
public static synchronized SoundingSource[] getSoundingSources() {
if (sources == null) {
String filePath = SKEWT_SOURCES_DIR + IPathManager.SEPARATOR
+ SKEWT_SOURCES_FILE;
try {
JAXBManager mgr = new JAXBManager(SoundingSourceConfig.class);
LocalizationFile file = PathManagerFactory.getPathManager()
.getStaticLocalizationFile(filePath);
if (file == null) {
sources = new SoundingSource[0];
throw new LocalizationException(
"Could not find skewt sources file: " + filePath);
}
SoundingSourceConfig config = (SoundingSourceConfig) mgr
.jaxbUnmarshalFromInputStream(file.openInputStream());
if (config == null) {
throw new SerializationException(
"SkewT Config file could not be deserialized");
}
sources = config.getSources();
} catch (JAXBException e) {
Activator.statusHandler.handle(UFStatus.Priority.PROBLEM,
e.getLocalizedMessage(), e);
} catch (SerializationException e) {
Activator.statusHandler.handle(UFStatus.Priority.PROBLEM,
e.getLocalizedMessage() + filePath, e);
} catch (LocalizationException e) {
Activator.statusHandler.handle(UFStatus.Priority.PROBLEM,
e.getLocalizedMessage() + filePath, e);
}
if (sources == null) {
sources = new SoundingSource[0];
}
}
return sources;
}
}

View file

@ -0,0 +1,154 @@
/**
* 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.ui.popupskewt.rsc;
import java.util.IdentityHashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.sounding.providers.VerticalSoundingProviderFactory;
import com.raytheon.uf.viz.ui.popupskewt.config.SoundingSource;
import com.raytheon.uf.viz.ui.popupskewt.ui.PopupSkewTDialog;
import com.raytheon.viz.ui.VizWorkbenchManager;
/**
* Container object for popupskewt
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 2, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class PopupSkewTContainer {
private static Map<IDisplayPaneContainer, PopupSkewTContainer> containers = new IdentityHashMap<IDisplayPaneContainer, PopupSkewTContainer>();
private IDisplayPaneContainer displayContainer;
private PopupSkewTDialog dialog;
private SoundingSource soundingSource;
private IVerticalSoundingProvider soundingProvider;
private boolean popupSkewTOn = false;
private int references = 0;
public synchronized static PopupSkewTContainer createContainer(
PopupSkewTResource resource) {
IDisplayPaneContainer rscContainer = resource.getResourceContainer();
PopupSkewTContainer container = containers.get(rscContainer);
if (container == null) {
container = new PopupSkewTContainer(rscContainer);
containers.put(rscContainer, container);
}
container.references += 1;
return container;
}
public synchronized static void disposeContainer(
PopupSkewTContainer container) {
container.references -= 1;
if (container.references == 0) {
container.closeSkewTDialog();
containers.remove(container.displayContainer);
}
}
private PopupSkewTContainer(IDisplayPaneContainer displayContainer) {
this.displayContainer = displayContainer;
}
public SoundingSource getSoundingSource() {
return soundingSource;
}
public void setSoundingSource(SoundingSource soundingSource) {
this.soundingSource = soundingSource;
if (soundingSource != null) {
this.soundingProvider = VerticalSoundingProviderFactory
.getVerticalSoundingProvider(soundingSource.getType(),
soundingSource.getConstraints());
}
}
public IVerticalSoundingProvider getSoundingProvider() {
return soundingProvider;
}
public boolean isPopupSkewTOn() {
return popupSkewTOn;
}
public void setPopupSkewTOn(boolean popupSkewTOn) {
this.popupSkewTOn = popupSkewTOn;
if (isPopupSkewTOn() == false) {
closeSkewTDialog();
}
}
public synchronized void showSkewTDialog() {
if (dialog == null) {
dialog = new PopupSkewTDialog(VizWorkbenchManager.getInstance()
.getCurrentWindow().getShell());
dialog.addListener(SWT.Dispose, new Listener() {
@Override
public void handleEvent(Event event) {
dialog = null;
popupSkewTOn = false;
}
});
dialog.open();
}
}
public synchronized void closeSkewTDialog() {
if (dialog != null) {
dialog.close();
dialog = null;
}
}
public synchronized void plotHeight(float height, float temp) {
showSkewTDialog();
dialog.plotHeight(height, temp);
}
public synchronized void plotSounding(VerticalSounding sounding) {
showSkewTDialog();
dialog.setSounding(sounding);
}
}

View file

@ -0,0 +1,425 @@
/**
* 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.ui.popupskewt.rsc;
import java.util.List;
import java.util.Map;
import javax.measure.Measure;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.eclipse.jface.action.IMenuManager;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.drawables.IDescriptor.FramesInfo;
import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceGroup;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.ui.popupskewt.config.SoundingSource;
import com.raytheon.uf.viz.ui.popupskewt.ui.PopupSkewTConfigAction;
import com.raytheon.viz.ui.cmenu.IContextMenuContributor;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Resource that interacts with other resources to plot height and temperature
* on a popup skewT dialog. Is enabled through inspecting/interrogating.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 19, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public class PopupSkewTResource extends
AbstractVizResource<PopupSkewTResourceData, IDescriptor> implements
IVerticalSoundingProvider, IContextMenuContributor {
public static final String HEIGHT_INTERROGATE_ID = "height";
public static final String DATA_VALUE_INTERROGATE_ID = "dataValue";
private static class InterrogateResult {
private final AbstractVizResource<?, ?> interrogatedResouce;
/** Height in kft */
private final Float height;
/** Temperature in deg C */
private final Float temperature;
private final DataTime dataTime;
public InterrogateResult(AbstractVizResource<?, ?> interrogatedResouce,
DataTime dataTime, Float height, Float temperature) {
this.interrogatedResouce = interrogatedResouce;
this.height = height;
this.temperature = temperature;
this.dataTime = dataTime;
}
public AbstractVizResource<?, ?> getInterrogatedResource() {
return interrogatedResouce;
}
public float getHeight() {
return height;
}
public float getTemperature() {
return temperature != null ? temperature : Float.NaN;
}
public DataTime getDataTime() {
return dataTime;
}
}
private PopupSkewTContainer container = PopupSkewTContainer
.createContainer(this);
/** Last calculated sounding */
private VerticalSounding sounding;
/**
* @param resourceData
* @param loadProperties
*/
protected PopupSkewTResource(PopupSkewTResourceData resourceData,
LoadProperties loadProperties) {
super(resourceData, loadProperties);
if (resourceData.isSystem() == false) {
setPopupSkewTOn(true);
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.rsc.AbstractVizResource#disposeInternal()
*/
@Override
protected void disposeInternal() {
PopupSkewTContainer.disposeContainer(container);
container = null;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#paintInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget,
* com.raytheon.uf.viz.core.drawables.PaintProperties)
*/
@Override
protected void paintInternal(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
if (resourceData.isSystem() == false) {
container.setPopupSkewTOn(true);
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractVizResource#initInternal(com.raytheon
* .uf.viz.core.IGraphicsTarget)
*/
@Override
protected void initInternal(IGraphicsTarget target) throws VizException {
if (container == null) {
container = PopupSkewTContainer.createContainer(this);
if (resourceData.isSystem() == false) {
container.setPopupSkewTOn(true);
}
}
}
@Override
public String getName() {
String name = super.getName();
DataTime cur = descriptor.getFramesInfo().getCurrentFrame();
if (cur != null) {
name += " " + cur.getLegendString();
}
return name;
}
@Override
public String inspect(ReferencedCoordinate coord) throws VizException {
if (isPopupSkewTOn()) {
FramesInfo currInfo = descriptor.getFramesInfo();
DataTime soundingTime = currInfo.getCurrentFrame();
InterrogateResult result = getSkewTParameters(
descriptor.getResourceList(), coord);
try {
if (result != null) {
container.plotHeight(result.getHeight(),
result.getTemperature());
if (result.getDataTime() != null) {
soundingTime = result.getDataTime();
}
}
VerticalSounding sounding = getSounding(soundingTime,
coord.asLatLon());
if (sounding != null && sounding.size() > 0) {
container.plotSounding(sounding);
}
} catch (Exception e) {
throw new VizException(e);
}
}
return resourceData.isSystem() ? super.inspect(coord) : "_";
}
/**
* Gets the best interrogation result to plot.
*
* @param resourceList
* @param coord
* @param currResult
* @return
*/
private InterrogateResult getSkewTParameters(ResourceList resourceList,
ReferencedCoordinate coord) {
FramesInfo currInfo = descriptor.getFramesInfo();
for (ResourcePair rp : resourceList) {
AbstractVizResource<?, ?> rsc = rp.getResource();
if (rsc != null && rsc != this && rp.getProperties().isVisible()) {
try {
Map<String, Object> dataMap = rsc.interrogate(coord);
if (dataMap != null) {
// Look for height
Float height = getValue(dataMap, HEIGHT_INTERROGATE_ID,
SI.METER);
if (height != null) {
// Check for temperature
Float temperature = getValue(dataMap,
DATA_VALUE_INTERROGATE_ID, SI.CELSIUS);
// Get the dataTime for the resource
DataTime dataTime = (DataTime) dataMap
.get(DataTime.class.toString());
if (dataTime == null) {
dataTime = currInfo.getTimeForResource(rsc);
}
return new InterrogateResult(rsc, dataTime, height,
temperature);
}
}
} catch (VizException e) {
// Ignore exception and move to next resource
}
}
}
List<AbstractVizResource<?, ?>> groups = resourceList
.getResourcesByType(IResourceGroup.class);
for (AbstractVizResource<?, ?> group : groups) {
if (group.getProperties().isVisible()) {
InterrogateResult result = getSkewTParameters(
((IResourceGroup) group).getResourceList(), coord);
if (result != null) {
return result;
}
}
}
return null;
}
private Float getValue(Map<String, Object> dataMap, String ID,
Unit<?> expectedUnit) {
Float expectedValue = null;
Object obj = dataMap.get(ID);
if (obj instanceof Measure) {
Measure<?, ?> measure = (Measure<?, ?>) obj;
if (measure.getValue() instanceof Number
&& measure.getUnit().isCompatible(expectedUnit)) {
Number value = (Number) measure.getValue();
expectedValue = (float) measure.getUnit()
.getConverterTo(expectedUnit)
.convert(value.doubleValue());
}
}
return expectedValue;
}
public SoundingSource getSource() {
return container.getSoundingSource();
}
public void setSource(SoundingSource soundingSource) {
if (getSource() != soundingSource) {
container.setSoundingSource(soundingSource);
}
}
public boolean isPopupSkewTOn() {
return container.isPopupSkewTOn();
}
public void setPopupSkewTOn(boolean popupSkewTOn) {
if (resourceData.isSystem()) {
container.setPopupSkewTOn(popupSkewTOn);
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider#getSounding
* (com.raytheon.uf.common.time.DataTime,
* com.vividsolutions.jts.geom.Coordinate)
*/
@Override
public VerticalSounding getSounding(DataTime requestTime,
Coordinate location) {
SoundingSource soundingSource = container.getSoundingSource();
IVerticalSoundingProvider soundingProvider = container
.getSoundingProvider();
if (soundingSource != null && soundingProvider != null
&& requestTime != null) {
if (sounding == null
|| sounding.getDataTime().equals(requestTime) == false
|| sounding.getLongitude() != location.x
|| sounding.getLatitude() != location.y) {
VerticalSounding sounding = new VerticalSounding();
sounding.setStationId(getName());
DataTime[] times = soundingProvider.getSoundingTimes();
if (times != null) {
long timeInterval = soundingSource.getValidTimeInterval()
* TimeUtil.MILLIS_PER_MINUTE;
DataTime timeToUse = null;
long minDiff = Long.MAX_VALUE;
for (DataTime dt : times) {
long diff = Math.abs(requestTime.getMatchValid()
- dt.getMatchValid());
if (diff < minDiff && diff <= timeInterval) {
minDiff = diff;
timeToUse = dt;
} else if (diff == minDiff
&& dt.getMatchRef() > timeToUse.getMatchRef()) {
minDiff = diff;
timeToUse = dt;
}
}
if (timeToUse != null) {
VerticalSounding providerSounding = soundingProvider
.getSounding(timeToUse, location);
if (providerSounding != null) {
sounding = providerSounding;
}
}
}
sounding.setLongitude(location.x);
sounding.setLatitude(location.y);
sounding.setDataTime(requestTime);
this.sounding = sounding;
}
return this.sounding;
}
return null;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider#
* getSoundingTimes()
*/
@Override
public DataTime[] getSoundingTimes() {
IVerticalSoundingProvider soundingProvider = container
.getSoundingProvider();
if (soundingProvider != null) {
return soundingProvider.getSoundingTimes();
}
return new DataTime[0];
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.common.sounding.adapter.IVerticalSoundingProvider#
* getSoundingSource()
*/
@Override
public String getSoundingSource() {
IVerticalSoundingProvider soundingProvider = container
.getSoundingProvider();
if (soundingProvider != null) {
return soundingProvider.getSoundingSource();
}
return null;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.ui.cmenu.IContextMenuContributor#addContextMenuItems
* (org.eclipse.jface.action.IMenuManager, int, int)
*/
@Override
public void addContextMenuItems(IMenuManager menuManager, int x, int y) {
if (resourceData.isSystem()) {
// check for non-system resource on same descriptor
for (PopupSkewTResource rsc : descriptor.getResourceList()
.getResourcesByTypeAsType(PopupSkewTResource.class)) {
if (rsc.getResourceData().isSystem() == false) {
// A non-system resource lives on descriptor, don't add menu
return;
}
}
}
menuManager.add(new PopupSkewTConfigAction(resourceData
.getContextMenuName(), this));
}
}

View file

@ -0,0 +1,146 @@
/**
* 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.ui.popupskewt.rsc;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.exception.NoDataAvailableException;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractNameGenerator;
import com.raytheon.uf.viz.core.rsc.AbstractResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
/**
* Resource data for {@link PopupSkewTResource}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 19, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
@XmlAccessorType(XmlAccessType.NONE)
public class PopupSkewTResourceData extends AbstractResourceData {
@XmlElement
private String resourceName = "Popup SkewT";
@XmlElement
private String contextMenuName = "Popup SkewT";
private boolean system = false;
public PopupSkewTResourceData() {
setNameGenerator(new AbstractNameGenerator() {
@Override
public String getName(AbstractVizResource<?, ?> resource) {
return resourceName;
}
});
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#construct(com.raytheon
* .uf.viz.core.rsc.LoadProperties,
* com.raytheon.uf.viz.core.drawables.IDescriptor)
*/
@Override
public AbstractVizResource<?, ?> construct(LoadProperties loadProperties,
IDescriptor descriptor) throws VizException {
if (isSystem() == false
&& descriptor.getFramesInfo().getFrameCount() == 0) {
throw new NoDataAvailableException(PopupSkewTResourceData.class);
}
return new PopupSkewTResource(this, loadProperties);
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public String getContextMenuName() {
return contextMenuName;
}
public void setContextMenuName(String contextMenuName) {
this.contextMenuName = contextMenuName;
}
public boolean isSystem() {
return system;
}
public void setSystem(boolean system) {
this.system = system;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.core.rsc.AbstractResourceData#update(java.lang.Object
* )
*/
@Override
public void update(Object updateData) {
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (system ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PopupSkewTResourceData other = (PopupSkewTResourceData) obj;
if (system != other.system)
return false;
return true;
}
}

View file

@ -17,7 +17,7 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.cloudheight.ui;
package com.raytheon.uf.viz.ui.popupskewt.ui;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
@ -27,52 +27,51 @@ import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import com.raytheon.uf.viz.cloudheight.CloudHeightAlgorithm;
import com.raytheon.uf.viz.cloudheight.data.CloudHeightData;
import com.raytheon.uf.viz.cloudheight.data.SoundingSource;
import com.raytheon.uf.viz.core.drawables.IDescriptor;
import com.raytheon.uf.viz.core.time.TimeMatchingJob;
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
import com.raytheon.uf.viz.sounding.providers.VerticalSoundingProviderFactory;
import com.raytheon.uf.viz.ui.popupskewt.config.SoundingSource;
import com.raytheon.uf.viz.ui.popupskewt.config.SoundingSourceConfigFactory;
import com.raytheon.uf.viz.ui.popupskewt.rsc.PopupSkewTResource;
/**
* Right click action for cloud height/popup skewt
* {@link Action} for creating menu for configuring a {@link PopupSkewTResource}
*
* TODO: How should this work on four-panel? See A1 D2D
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 14, 2009 randerso Initial creation
* Jul 19, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author randerso
* @author mschenke
* @version 1.0
*/
public class CloudHeightRightClickAction extends AbstractRightClickAction
implements IMenuCreator {
public class PopupSkewTConfigAction extends Action implements IMenuCreator {
private Menu menu;
private CloudHeightAlgorithm cloudHeight;
private PopupSkewTResource resource;
private IDescriptor descriptor;
/**
*
*/
public CloudHeightRightClickAction(IDescriptor descriptor,
CloudHeightAlgorithm cloudHeight) {
super("Sample Cloud Heights/Radar Skew T", SWT.DROP_DOWN);
this.cloudHeight = cloudHeight;
this.descriptor = descriptor;
public PopupSkewTConfigAction(String menuName, PopupSkewTResource resource) {
super(menuName, SWT.DROP_DOWN);
this.resource = resource;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.IMenuCreator#dispose()
*/
@Override
public void dispose() {
if (menu != null) {
menu.dispose();
menu = null;
}
}
@ -86,60 +85,75 @@ public class CloudHeightRightClickAction extends AbstractRightClickAction
return this;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.action.IMenuCreator#getMenu(org.eclipse.swt.widgets
* .Control)
*/
@Override
public Menu getMenu(Control parent) {
if (menu != null) {
menu.dispose();
}
dispose();
menu = new Menu(parent);
fillMenu(menu);
return menu;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.action.IMenuCreator#getMenu(org.eclipse.swt.widgets
* .Menu)
*/
@Override
public Menu getMenu(Menu parent) {
dispose();
menu = new Menu(parent);
fillMenu(menu);
return menu;
}
/**
*
* Fill's the menu with the popup skewt config options
*/
private void fillMenu(Menu menu) {
SoundingSource curSource = cloudHeight.getCurrentSource();
for (SoundingSource source : CloudHeightData.getCloudHeightData()
.getSources()) {
Action internalAction = new SetSourceInternalAction(source);
internalAction.setChecked(source.equals(curSource));
ActionContributionItem aci = new ActionContributionItem(
internalAction);
aci.fill(menu, -1);
SoundingSource[] sources = SoundingSourceConfigFactory
.getSoundingSources();
SoundingSource selected = resource.getSource();
Action noSampling = new SetSourceInternalAction(null);
noSampling.setChecked(selected == null);
new ActionContributionItem(noSampling).fill(menu, -1);
for (SoundingSource source : sources) {
if (VerticalSoundingProviderFactory.hasProviderForType(source
.getType())) {
Action action = new SetSourceInternalAction(source);
action.setChecked(selected == source);
new ActionContributionItem(action).fill(menu, -1);
}
}
new Separator().fill(menu, -1);
new ActionContributionItem(new ToggleSkewTInternalAction(
cloudHeight.isSkewT())).fill(menu, -1);
}
@Override
public Menu getMenu(Menu parent) {
if (menu != null) {
menu.dispose();
}
menu = new Menu(parent);
fillMenu(menu);
return menu;
resource.isPopupSkewTOn())).fill(menu, -1);
}
private class SetSourceInternalAction extends Action {
private static final String NO_SOURCE_STRING = "No Sampling";
private SoundingSource source;
public SetSourceInternalAction(SoundingSource source) {
super(source.toString(), Action.AS_RADIO_BUTTON);
super(
source == null ? NO_SOURCE_STRING : source
.getDisplayString(), Action.AS_RADIO_BUTTON);
this.source = source;
}
@ -150,8 +164,7 @@ public class CloudHeightRightClickAction extends AbstractRightClickAction
*/
@Override
public void run() {
cloudHeight.setCurrentSource(source);
TimeMatchingJob.scheduleTimeMatch(descriptor);
resource.setSource(source);
}
}
@ -170,7 +183,7 @@ public class CloudHeightRightClickAction extends AbstractRightClickAction
*/
@Override
public void run() {
cloudHeight.setSkewT(isChecked());
resource.setPopupSkewTOn(isChecked());
}
}

View file

@ -17,7 +17,7 @@
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.skewt.ui;
package com.raytheon.uf.viz.ui.popupskewt.ui;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.NonSI;
@ -37,7 +37,6 @@ import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.edex.meteoLib.Controller;
import com.raytheon.uf.common.sounding.SoundingLayer;
import com.raytheon.uf.common.sounding.SoundingLayer.DATA_TYPE;
import com.raytheon.uf.common.sounding.VerticalSounding;
@ -55,6 +54,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 14, 2009 randerso Initial creation
* Jul 19, 2013 2190 mschenke Moved from skewt project to popup skewt to
* separate out from old deprecated skewt code
*
* </pre>
*
@ -78,8 +79,6 @@ public class PopupSkewTDialog extends CaveSWTDialog {
private static final UnitConverter MtoFT = SI.METER
.getConverterTo(NonSI.FOOT);
private Display display;
private WGraphics world;
private Composite top;
@ -92,24 +91,12 @@ public class PopupSkewTDialog extends CaveSWTDialog {
private Point height;
private static float[] muParcelTrajectoryPressures = new float[20];
static {
int i = 0;
for (float p = 1000; p >= 50; p -= 50, ++i) {
muParcelTrajectoryPressures[i] = p;
}
}
private float[] muParcelTrajectory;
public PopupSkewTDialog(Shell parentShell) {
super(parentShell, SWT.TITLE | SWT.RESIZE | SWT.MODELESS,
CAVE.DO_NOT_BLOCK);
// this.parentShell = parentShell;
display = parentShell.getDisplay();
setText("Skew T");
Rectangle rectangle = new Rectangle(30, 20, 380, 240);
world = new WGraphics(rectangle);
@ -119,25 +106,6 @@ public class PopupSkewTDialog extends CaveSWTDialog {
TEMPS[TEMPS.length - 1]);
world.setWorldCoordinates(lowerLeft.x, upperRight.y, upperRight.x,
lowerLeft.y);
// dummy data for testing
// VerticalSounding dummySounding = new VerticalSounding();
// dummySounding.setName("TEST");
// for (float p = 1000; p >= 50; p -= 50) {
// SoundingLayer layer = new SoundingLayer();
// layer.setPressure(p);
// layer.setGeoHeight(Controller.ptozsa(p));
// float tt = (float) WxMath.poisson(1000, p, 293.15);
// float td = tt - 10f;
// layer.setTemperature(tt);
// layer.setDewpoint(td);
// dummySounding.addLayer(layer);
// }
//
// setSounding(dummySounding);
// SoundingLayer layer = dummySounding.getLayer(500f);
// setHeight(layer.getPressure(),
// (float) KtoC.convert(layer.getTemperature()));
}
public void plotHeight(float height, float temp) {
@ -162,7 +130,7 @@ public class PopupSkewTDialog extends CaveSWTDialog {
pres = sounding.get(i1).getPressure()
+ (sounding.get(i2).getPressure() - sounding.get(i1)
.getPressure()) * dz / lyrDz;
if (temp > 1e36) {
if (Float.isNaN(temp)) {
temperature = (sounding.get(i1).getTemperature() - 273.15f)
+ (sounding.get(i2).getTemperature() - sounding
.get(i1).getTemperature()) * dz / lyrDz;
@ -193,7 +161,7 @@ public class PopupSkewTDialog extends CaveSWTDialog {
public void setSounding(VerticalSounding sounding) {
this.sounding = sounding;
if (this.sounding != null && this.sounding.size() > 0) {
muParcelTrajectory = derivemuParcelTrajectory(sounding);
muParcelTrajectory = WxMath.derivemuParcelTrajectory(sounding);
if (label != null && !label.isDisposed()) {
label.setText(sounding.getName());
@ -211,30 +179,6 @@ public class PopupSkewTDialog extends CaveSWTDialog {
}
}
/**
* @param sounding
*/
public static float[] derivemuParcelTrajectory(VerticalSounding soundingData) {
float[] muParcelTrajectory = new float[muParcelTrajectoryPressures.length];
float thetae, maxthetae = -999.0f;
float etpar, tp;
for (int i = 0; i < soundingData.size(); i++) {
float tt = soundingData.get(i).getTemperature();
float td = soundingData.get(i).getDewpoint();
float p = soundingData.get(i).getPressure();
thetae = Controller.ept(tt, td, p);
if (thetae > maxthetae && soundingData.get(i).getPressure() > 500)
maxthetae = thetae;
}
for (int i = 0; i < muParcelTrajectoryPressures.length; ++i) {
float p = muParcelTrajectoryPressures[i];
etpar = (float) (maxthetae * (Math.pow(p / 1000.0f, 0.286f)));
tp = Controller.temp_of_te(etpar, p);
muParcelTrajectory[20 - (int) (p / 50)] = tp;
}
return muParcelTrajectory;
}
/**
* Map a pressure,temperature value to an x,y coordinate
*
@ -250,7 +194,7 @@ public class PopupSkewTDialog extends CaveSWTDialog {
protected void paint(PaintEvent e) {
GC gc = e.gc;
Display display = getDisplay();
// paint background
gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
Rectangle r = canvas.getClientArea();
@ -320,7 +264,7 @@ public class PopupSkewTDialog extends CaveSWTDialog {
gc.drawText(s, p0.x - te.x, p0.y - te.y, true);
}
if (sounding != null) {
if (sounding != null && sounding.size() > 0) {
// paint T line
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
@ -355,6 +299,8 @@ public class PopupSkewTDialog extends CaveSWTDialog {
// paint theta e line
gc.setForeground(display.getSystemColor(SWT.COLOR_DARK_MAGENTA));
p0 = null;
float[] muParcelTrajectoryPressures = WxMath
.getMuParcelTrajectoryPressures();
for (int i = 0; i < muParcelTrajectoryPressures.length - 1; ++i) {
float p = muParcelTrajectoryPressures[i];
Point p1 = PTtoXY(p, KtoC.convert(muParcelTrajectory[i]));
@ -405,8 +351,6 @@ public class PopupSkewTDialog extends CaveSWTDialog {
label.setText(sounding.getName());
}
shell.setText("Skew T");
shell.setLocation(0, 0);
}
}

View file

@ -44,6 +44,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* Aug 4, 2010 mnash Initial creation
* Feb 15, 2013 1638 mschenke Got rid of viz/edex topo classes
* and moved into common
* Jul 31, 2013 2190 mschenke Made "msl" interrogate key return
* height unformatted height data value
*
* </pre>
*
@ -53,7 +55,13 @@ import com.vividsolutions.jts.geom.Coordinate;
public class RadarRadialInterrogator extends RadarDefaultInterrogator implements
IRadarInterrogator {
private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(RadarRadialInterrogator.class);
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(RadarRadialInterrogator.class);
public static final String MSL_HEIGHT_ID = "msl";
public static final String MSL_HEIGHT_STRING_ID = "MSL";
protected RadarDataInterrogator interrogator = new RadarDataInterrogator(
null);
@ -100,9 +108,9 @@ public class RadarRadialInterrogator extends RadarDefaultInterrogator implements
"Topo Error: Radar AGL sampling has been disabled");
}
}
dataMap.put("MSL",
dataMap.put(MSL_HEIGHT_STRING_ID,
String.format("%.0fft", metersToFeet.convert(msl)));
dataMap.put("msl", "" + msl);
dataMap.put(MSL_HEIGHT_ID, "" + msl);
if (!Double.isNaN(topoHeight)) {
double agl = msl - topoHeight;

View file

@ -23,7 +23,9 @@ import java.awt.Rectangle;
import java.util.HashMap;
import java.util.Map;
import javax.measure.Measure;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@ -32,6 +34,7 @@ import com.raytheon.uf.common.dataplugin.IDecoderGettable.Amount;
import com.raytheon.uf.common.dataplugin.radar.RadarRecord;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.DrawableImage;
import com.raytheon.uf.viz.core.IGraphicsTarget;
@ -46,6 +49,7 @@ import com.raytheon.viz.awipstools.common.EstimatedActualVelocity;
import com.raytheon.viz.awipstools.common.IRadialVelocityToolSource;
import com.raytheon.viz.radar.VizRadarRecord;
import com.raytheon.viz.radar.interrogators.IRadarInterrogator;
import com.raytheon.viz.radar.interrogators.RadarRadialInterrogator;
import com.raytheon.viz.radar.rsc.RadarImageResource;
import com.raytheon.viz.radar.rsc.RadarProductFactory;
import com.raytheon.viz.radar.rsc.RadarResourceData;
@ -61,14 +65,18 @@ import com.vividsolutions.jts.geom.Coordinate;
* ------------ ---------- ----------- --------------------------
* Jul 29, 2010 mnash Initial creation
* 05/02/2013 DR 14587 D. Friedman Implement IRadialVelocityToolSource
*
* Jul 31, 2013 2190 mschenke Convert interrogate string "msl" to Measure and
* put in as "height"
* </pre>
*
* @author mnash
* @version 1.0
*/
public class RadarRadialResource extends RadarImageResource<MapDescriptor> implements IRadialVelocityToolSource {
public class RadarRadialResource extends RadarImageResource<MapDescriptor>
implements IRadialVelocityToolSource {
public static final String HEIGHT_INTERROGATE_ID = "height";
private static final String EAV_VALUE = "EAC.Value";
@ -147,6 +155,27 @@ public class RadarRadialResource extends RadarImageResource<MapDescriptor> imple
return sb.toString();
}
@Override
public Map<String, Object> interrogate(ReferencedCoordinate coord)
throws VizException {
Map<String, Object> dataMap = super.interrogate(coord);
if (dataMap != null
&& dataMap.containsKey(RadarRadialInterrogator.MSL_HEIGHT_ID)) {
Object obj = dataMap.get(RadarRadialInterrogator.MSL_HEIGHT_ID);
// Get MSL object, handles if String, Number or Measure
if (obj instanceof String) {
obj = Double.parseDouble(String.valueOf(obj));
}
if (obj instanceof Number) {
obj = Measure.valueOf(((Number) obj).doubleValue(), SI.METER);
}
if (obj instanceof Measure) {
dataMap.put(HEIGHT_INTERROGATE_ID, (Measure<?, ?>) obj);
}
}
return dataMap;
}
@Override
public Map<String, String> interrogate(DataTime dataTime, Coordinate latLon) {
Map<String, String> dataMap = super.interrogate(dataTime, latLon);
@ -224,7 +253,7 @@ public class RadarRadialResource extends RadarImageResource<MapDescriptor> imple
int productCode = -1;
try {
// TODO: This duplicates logic in RadarResourceData.constructResource
if (radarRecords != null && ! radarRecords.isEmpty()) {
if (radarRecords != null && !radarRecords.isEmpty()) {
RadarRecord r = radarRecords.values().iterator().next();
productCode = r.getProductCode();
} else {

View file

@ -60,6 +60,9 @@ import com.vividsolutions.jts.geom.Coordinate;
* Feb 18, 2009 2032 jsanchez Initial Creation.
* Updated inspect to display a single value.
* Mar 17, 2009 800 jsanchez Avoided displaying unnecessary 0.0.
* Jul 31, 2013 2190 mschenke Removed arbitrary check for 0.0 and instead
* only check for NaN. SatResource handles fill
* values and returns NaN now
*
* </pre>
*
@ -275,22 +278,17 @@ public class SatBlendedResource extends
@Override
public String inspect(ReferencedCoordinate coord) throws VizException {
String inspectString = "NO DATA";
Double inspectValue = null;
ResourceList list = getResourceList();
for (int i = list.size() - 1; i >= 0; --i) {
AbstractVizResource<?, ?> rsc = list.get(i).getResource();
Map<String, Object> dataMap = rsc.interrogate(coord);
if (dataMap.get(SatResource.RAW_VALUE) instanceof Double) {
Double value = (Double) dataMap.get(SatResource.RAW_VALUE);
if (value.isNaN()) {
// This one is no good, skip it.
continue;
}
if (inspectValue == null || inspectValue == 0.0) {
// Either there is no previous value or it was zero, so
// try this one.
inspectValue = value;
if (dataMap.get(SatResource.RAW_VALUE) instanceof Number) {
double value = ((Number) dataMap.get(SatResource.RAW_VALUE))
.doubleValue();
if (Double.isNaN(value) == false) {
// use this resource
inspectString = rsc.inspect(coord);
break;
}
}
}

View file

@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.measure.Measure;
import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit;
@ -91,6 +92,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* 07/17/2012 798 jkorman Use decimationLevels from SatelliteRecord. Removed hard-coded
* data set names.
* 06/20/2013 2122 mschenke Modified to use SatTileSetRenderable
* 07/31/2013 2190 mschenke Switched to use Measure objects for interrogation
* </pre>
*
* @author chammack
@ -104,6 +106,9 @@ public class SatResource extends
public static String RAW_VALUE = "rawValue";
/** String id to look for satellite-provided data values */
public static final String SATELLITE_DATA_INTERROGATE_ID = "satelliteDataValue";
private static class InterrogationResult {
private final SatelliteRecord record;
@ -374,19 +379,15 @@ public class SatResource extends
Map<String, Object> dataMap = new HashMap<String, Object>();
SatRenderable renderable = (SatRenderable) getRenderable(displayedDate);
ColorMapParameters parameters = getCapability(ColorMapCapability.class)
.getColorMapParameters();
double dataValue = Double.NaN;
if (renderable != null) {
try {
InterrogationResult result = renderable.interrogate(coord
.asLatLon());
if (result != null) {
double dataValue = result.getValue();
UnitConverter dataToDisplay = getCapability(
ColorMapCapability.class).getColorMapParameters()
.getDataToDisplayConverter();
if (dataToDisplay != null) {
dataValue = dataToDisplay.convert(dataValue);
}
dataMap.put(RAW_VALUE, dataValue);
dataValue = result.getValue();
dataMap.put(ISpatialObject.class.toString(), result
.getRecord().getSpatialObject());
}
@ -394,6 +395,11 @@ public class SatResource extends
throw new VizException("Error interrogating raw data", e);
}
}
dataMap.put(RAW_VALUE, dataValue);
dataMap.put(SATELLITE_DATA_INTERROGATE_ID,
Measure.valueOf(dataValue, parameters.getDataUnit()));
return dataMap;
}
@ -401,7 +407,7 @@ public class SatResource extends
public String inspect(ReferencedCoordinate coord) throws VizException {
Map<String, Object> dataMap = interrogate(coord);
Double value = (Double) dataMap.get(RAW_VALUE);
if (value == null) {
if (value == null || value.isNaN()) {
return "NO DATA";
}
ColorMapParameters cmp = getCapability(ColorMapCapability.class)
@ -410,17 +416,19 @@ public class SatResource extends
// check if data mapping preferences exist
DataMappingPreferences dataMapping = cmp.getDataMapping();
if (dataMapping != null) {
// convert to pixel value for checking labels
double pixelValue = cmp.getDisplayToDataConverter().convert(
value.doubleValue());
// if the pixel value matches the data mapping entry use that
// label instead
String label = dataMapping.getLabelValueForDataValue(pixelValue);
String label = dataMapping.getLabelValueForDataValue(value);
if (label != null) {
return label;
}
}
UnitConverter dataToDisplay = cmp.getDataToDisplayConverter();
if (dataToDisplay != null) {
value = dataToDisplay.convert(value);
}
Unit<?> unit = cmp.getDisplayUnit();
// Had to use 'bit' as the display unit because
// counts was not an acceptable unit.

View file

@ -21,6 +21,7 @@
<?eclipse version="3.2"?>
<plugin>
<extension-point id="displayCustomizer" name="displayCustomizer" schema="schema/displayCustomizer.exsd"/>
<extension-point id="contextualMenu" name="contextualMenu" schema="schema/contextualMenu.exsd"/>
<extension-point id="perspectiveManager" name="perspectiveManager" schema="schema/perspectiveManager.exsd"/>
<extension-point id="com.raytheon.uf.viz.ui.mouse.action" name="Mouse Preference" schema="schema/mousePreference.exsd"/>

View file

@ -0,0 +1,85 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="com.raytheon.viz.ui" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="com.raytheon.viz.ui" id="displayCustomizer" name="displayCustomizer"/>
</appInfo>
<documentation>
Provides an entry point for renderable display customization
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="displayCustomizer"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="displayCustomizer">
<complexType>
<attribute name="customizer" type="string" use="required">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":com.raytheon.viz.ui.perspectives.IRenderableDisplayCustomizer"/>
</appInfo>
</annotation>
</attribute>
<attribute name="perspective" type="string">
<annotation>
<documentation>
Comma separated list of perspectives this customizer applies to. Do not include this attribute if customizer applies to all perspectives
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
0.1
</documentation>
</annotation>
</schema>

View file

@ -19,7 +19,7 @@
**/
package com.raytheon.viz.ui.panes;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.ui.IEditorPart;
@ -47,6 +47,8 @@ import com.raytheon.viz.ui.VizWorkbenchManager;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 5, 2009 bgonzale Initial creation
* Aug 2, 2013 2190 mschenke Made displayPanes Set a LinkedHashSet to ensure
* rendered in order added
*
* </pre>
*
@ -54,7 +56,7 @@ import com.raytheon.viz.ui.VizWorkbenchManager;
* @version 1.0
*/
public class DrawCoordinatedPane implements Comparable<DrawCoordinatedPane> {
public class DrawCoordinatedPane {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(DrawCoordinatedPane.class);
@ -67,14 +69,13 @@ public class DrawCoordinatedPane implements Comparable<DrawCoordinatedPane> {
/**
* Multiple gl display panes can be registered with each container.
*/
private Set<VizDisplayPane> displayPanes = new HashSet<VizDisplayPane>();
private Set<VizDisplayPane> displayPanes = new LinkedHashSet<VizDisplayPane>();
private boolean editor = false;
private boolean dead = false;
public DrawCoordinatedPane(IDisplayPaneContainer container,
VizDisplayPane pane) {
public DrawCoordinatedPane(IDisplayPaneContainer container) {
this.container = container;
editor = container instanceof IEditorPart;
if (container instanceof IWorkbenchPart) {
@ -83,7 +84,6 @@ public class DrawCoordinatedPane implements Comparable<DrawCoordinatedPane> {
} else {
containerWindow = manager.getCurrentWindow();
}
displayPanes.add(pane);
}
public synchronized void add(VizDisplayPane pane) {
@ -156,18 +156,6 @@ public class DrawCoordinatedPane implements Comparable<DrawCoordinatedPane> {
}
}
/*
* Note, this implementation of compareTo is inconsistent with equals.
* ManagedPanes are identified by the IDisplayPaneContainer object member
* attribute. (non-Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(DrawCoordinatedPane other) {
return (this.container.hashCode() - other.container.hashCode());
}
public synchronized void draw(boolean actualDraw) {
if (dead) {
return;

View file

@ -21,8 +21,10 @@
package com.raytheon.viz.ui.panes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@ -31,7 +33,6 @@ import org.eclipse.core.runtime.jobs.Job;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.core.IDisplayPane;
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.preferences.PreferenceConstants;
@ -44,6 +45,7 @@ import com.raytheon.uf.viz.core.preferences.PreferenceConstants;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 14, 2007 chammack Initial Creation.
* Aug 2, 2013 2190 mschenke Changed "panes" to Map to simplify code
*
* </pre>
*
@ -78,7 +80,7 @@ public class DrawCoordinatorJob extends Job {
*/
private final long smallSleep = 5;
private List<DrawCoordinatedPane> panes;
private Map<IDisplayPaneContainer, DrawCoordinatedPane> panes = new IdentityHashMap<IDisplayPaneContainer, DrawCoordinatedPane>();
private boolean shouldRun = true;
@ -86,7 +88,6 @@ public class DrawCoordinatorJob extends Job {
private DrawCoordinatorJob() {
super("Draw Coordinator");
panes = new ArrayList<DrawCoordinatedPane>();
setSystem(true);
schedule();
}
@ -105,42 +106,17 @@ public class DrawCoordinatorJob extends Job {
*/
public void unregisterPane(IDisplayPaneContainer container,
VizDisplayPane displayPane) {
int index = Collections.binarySearch(panes, new DrawCoordinatedPane(
container, null));
if (index >= 0) {
DrawCoordinatedPane drawCoordinatedPane = panes.get(index);
drawCoordinatedPane.remove(displayPane);
if (drawCoordinatedPane.getPanes().isEmpty()) {
synchronized (this) {
List<DrawCoordinatedPane> newPanes = new ArrayList<DrawCoordinatedPane>(
panes);
newPanes.remove(drawCoordinatedPane);
panes = newPanes;
synchronized (panes) {
DrawCoordinatedPane pane = panes.get(container);
if (pane != null) {
pane.remove(displayPane);
if (pane.getPanes().isEmpty()) {
panes.remove(container);
}
}
}
}
/**
* Register a pane for drawing
*
* @param container
* the container of the pane
* @param displayPane
* the pane itself
*/
public IDisplayPane[] getDrawnPanes(IDisplayPaneContainer container) {
int index = Collections.binarySearch(panes, new DrawCoordinatedPane(
container, null));
if (index < 0) {
return new IDisplayPane[0];
} else {
DrawCoordinatedPane drawCoordinatedPane = panes.get(index);
return drawCoordinatedPane.getPanes().toArray(
new IDisplayPane[drawCoordinatedPane.getPanes().size()]);
}
}
/**
* Register a pane for drawing
*
@ -151,30 +127,15 @@ public class DrawCoordinatorJob extends Job {
*/
public void registerPane(IDisplayPaneContainer container,
VizDisplayPane displayPane) {
int index = Collections.binarySearch(panes, new DrawCoordinatedPane(
container, null));
if (index < 0) {
synchronized (this) {
DrawCoordinatedPane drawCoordinatedPane = new DrawCoordinatedPane(
container, displayPane);
List<DrawCoordinatedPane> newPanes = new ArrayList<DrawCoordinatedPane>(
panes);
newPanes.add(-index - 1, drawCoordinatedPane);
panes = newPanes;
}
} else {
DrawCoordinatedPane drawCoordinatedPane = panes.get(index);
drawCoordinatedPane.add(displayPane);
DrawCoordinatedPane pane;
synchronized (panes) {
pane = panes.get(container);
if (pane == null) {
pane = new DrawCoordinatedPane(container);
panes.put(container, pane);
}
}
public void draw(VizDisplayPane displayPane, boolean actualDraw) {
int index = Collections.binarySearch(panes, new DrawCoordinatedPane(
displayPane.container, null));
if (index >= 0) {
DrawCoordinatedPane pane = panes.get(index);
pane.draw(true);
}
pane.add(displayPane);
}
/*
@ -213,7 +174,11 @@ public class DrawCoordinatorJob extends Job {
}
listToDraw.clear();
for (DrawCoordinatedPane pane : panes) {
Set<DrawCoordinatedPane> managed;
synchronized (panes) {
managed = new HashSet<DrawCoordinatedPane>(panes.values());
}
for (DrawCoordinatedPane pane : managed) {
if (pane.needsRefresh()) {
listToDraw.add(pane);
}

View file

@ -19,18 +19,33 @@
**/
package com.raytheon.viz.ui.perspectives;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.ContextManager;
import com.raytheon.uf.viz.core.IDisplayPane;
import com.raytheon.uf.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.core.IRenderableDisplayChangedListener;
import com.raytheon.uf.viz.core.drawables.IRenderableDisplay;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.rsc.IInputHandler;
import com.raytheon.viz.ui.editor.AbstractEditor;
@ -54,11 +69,45 @@ import com.raytheon.viz.ui.statusline.TimeDisplay;
*/
public abstract class AbstractCAVEPerspectiveManager extends
AbstractVizPerspectiveManager {
AbstractVizPerspectiveManager implements IRenderableDisplayCustomizer {
private static final String DISPLAY_CUSTOMIZER_EXT_ID = "com.raytheon.viz.ui.displayCustomizer";
private static final String DISPLAY_CUSTOMIZER_EXT_CUSTOMIZER_ATTR_ID = "customizer";
private static final String DISPLAY_CUSTOMIZER_EXT_PERSPECTIVE_ATTR_ID = "perspective";
private IPartListener displayCustomizer;
private IWorkbenchPage perspectivePage;
/** Optional workbench part context activator for the perspective */
protected AbstractWorkbenchPartContextActivator contextActivator;
private Collection<IRenderableDisplayCustomizer> customizers;
@Override
public void activate() {
if (displayCustomizer == null
&& perspectiveWindow.getActivePage() != null) {
perspectivePage = perspectiveWindow.getActivePage();
displayCustomizer = new CAVEPerspectiveDisplayCustomizer(this);
perspectivePage.addPartListener(displayCustomizer);
customizers = getPerspectiveDisplayCustomizers(perspectivePage
.getPerspective());
}
super.activate();
}
@Override
public void close() {
if (displayCustomizer != null) {
perspectivePage.removePartListener(displayCustomizer);
displayCustomizer = null;
}
super.close();
}
/*
* (non-Javadoc)
*
@ -160,4 +209,148 @@ public abstract class AbstractCAVEPerspectiveManager extends
+ " - " + getLabel();
}
@Override
public void customizeDisplay(IRenderableDisplay display) {
if (customizers != null) {
for (IRenderableDisplayCustomizer customizer : customizers) {
customizer.customizeDisplay(display);
}
}
}
@Override
public void uncustomizeDisplay(IRenderableDisplay display) {
if (customizers != null) {
for (IRenderableDisplayCustomizer customizer : customizers) {
customizer.uncustomizeDisplay(display);
}
}
}
/**
* Looks up the {@link IRenderableDisplayCustomizer}s for the perspective
* descriptor passed in based on the displayCustomizer extension point
*
* @param descriptor
* @return
*/
private static Collection<IRenderableDisplayCustomizer> getPerspectiveDisplayCustomizers(
IPerspectiveDescriptor descriptor) {
List<IRenderableDisplayCustomizer> customizers = new ArrayList<IRenderableDisplayCustomizer>();
IExtensionPoint extPoint = Platform.getExtensionRegistry()
.getExtensionPoint(DISPLAY_CUSTOMIZER_EXT_ID);
if (extPoint != null) {
String id = descriptor.getId();
String name = descriptor.getLabel();
for (IExtension ext : extPoint.getExtensions()) {
for (IConfigurationElement element : ext
.getConfigurationElements()) {
try {
IRenderableDisplayCustomizer customizer = (IRenderableDisplayCustomizer) element
.createExecutableExtension(DISPLAY_CUSTOMIZER_EXT_CUSTOMIZER_ATTR_ID);
if (customizer != null) {
String perspectives = element
.getAttribute(DISPLAY_CUSTOMIZER_EXT_PERSPECTIVE_ATTR_ID);
if (perspectives == null) {
customizers.add(customizer);
} else {
String[] parts = perspectives.split("[,]");
for (String part : parts) {
part = part.trim();
if (part.equalsIgnoreCase(id)
|| part.equalsIgnoreCase(name)) {
customizers.add(customizer);
break;
}
}
}
}
} catch (CoreException e) {
statusHandler.handle(Priority.PROBLEM,
e.getLocalizedMessage(), e);
}
}
}
}
return customizers;
}
private static class CAVEPerspectiveDisplayCustomizer implements
IPartListener, IRenderableDisplayChangedListener {
private AbstractCAVEPerspectiveManager perspectiveManager;
public CAVEPerspectiveDisplayCustomizer(
AbstractCAVEPerspectiveManager perspectiveManager) {
this.perspectiveManager = perspectiveManager;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.core.IRenderableDisplayChangedListener#
* renderableDisplayChanged(com.raytheon.uf.viz.core.IDisplayPane,
* com.raytheon.uf.viz.core.drawables.IRenderableDisplay,
* com.raytheon.uf.viz
* .core.IRenderableDisplayChangedListener.DisplayChangeType)
*/
@Override
public void renderableDisplayChanged(IDisplayPane pane,
IRenderableDisplay renderableDisplay, DisplayChangeType type) {
if (type == DisplayChangeType.ADD) {
perspectiveManager.customizeDisplay(renderableDisplay);
} else if (type == DisplayChangeType.REMOVE) {
perspectiveManager.uncustomizeDisplay(renderableDisplay);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart
* )
*/
@Override
public void partOpened(IWorkbenchPart part) {
if (part instanceof IDisplayPaneContainer) {
IDisplayPaneContainer container = (IDisplayPaneContainer) part;
container.addRenderableDisplayChangedListener(this);
for (IDisplayPane pane : container.getDisplayPanes()) {
renderableDisplayChanged(pane, pane.getRenderableDisplay(),
DisplayChangeType.ADD);
}
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart
* )
*/
@Override
public void partClosed(IWorkbenchPart part) {
if (part instanceof IDisplayPaneContainer) {
((IDisplayPaneContainer) part)
.removeRenderableDisplayChangedListener(this);
}
}
@Override
public void partActivated(IWorkbenchPart part) {
// Do nothing
}
@Override
public void partBroughtToTop(IWorkbenchPart part) {
// Do nothing
}
@Override
public void partDeactivated(IWorkbenchPart part) {
// Do nothing
}
}
}

View file

@ -83,7 +83,7 @@ import com.raytheon.viz.ui.tools.ModalToolManager;
*/
public abstract class AbstractVizPerspectiveManager implements
IBackgroundColorChangedListener {
private static final transient IUFStatusHandler statusHandler = UFStatus
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(AbstractVizPerspectiveManager.class);
private static class PerspectivePageListener implements IPageListener {
@ -434,7 +434,7 @@ public abstract class AbstractVizPerspectiveManager implements
*
* @param perspectiveId
*/
public void setPerspectiveId(String perspectiveId) {
void setPerspectiveId(String perspectiveId) {
this.perspectiveId = perspectiveId;
}

View file

@ -0,0 +1,59 @@
/**
* 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.viz.ui.perspectives;
import com.raytheon.uf.viz.core.drawables.IRenderableDisplay;
/**
* Interface for customizing renderable displays for a perspective when a new
* renderable display is created in the perspective
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 31, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public interface IRenderableDisplayCustomizer {
/**
* Method for customizing the a renderable display
*
* @param display
*/
public void customizeDisplay(IRenderableDisplay display);
/**
* Method for undoing customizations done to the renderable display from
* {@link #customizeDisplay(IRenderableDisplay)}
*
* @param display
*/
public void uncustomizeDisplay(IRenderableDisplay display);
}

View file

@ -55,7 +55,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
*/
@Entity
@SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "nucapsseq")
@Table(name = "nucaps", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) })
@Table(name = NucapsRecord.PLUGIN_NAME, uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) })
@DynamicSerialize
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
@ -63,6 +63,8 @@ public class NucapsRecord extends NPPSoundingRecord {
private static final long serialVersionUID = 1L;
public static final String PLUGIN_NAME = "nucaps";
public static final String PDV_SURFACE_PRESSURE = "Surface_Pressure";
public static final String PDV_PRESSURE = "Pressure";
@ -85,6 +87,10 @@ public class NucapsRecord extends NPPSoundingRecord {
public static final String PDV_QUALITY_FLAG = "Quality_Flag";
public NucapsRecord() {
setPluginName(PLUGIN_NAME);
}
@Override
@Column
@Access(AccessType.PROPERTY)

View file

@ -12,6 +12,7 @@ Require-Bundle: com.raytheon.uf.common.pointdata;bundle-version="1.11.31",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.status;bundle-version="1.12.1174",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
com.raytheon.edex.meteolib;bundle-version="1.12.1174",
javax.measure;bundle-version="1.0.0"
Export-Package: com.raytheon.uf.common.sounding,
com.raytheon.uf.common.sounding.adapter,

View file

@ -19,6 +19,7 @@
**/
package com.raytheon.uf.common.sounding;
import com.raytheon.edex.meteoLib.Controller;
import com.raytheon.uf.common.sounding.util.SoundingPrefs;
import com.vividsolutions.jts.geom.Coordinate;
@ -33,6 +34,8 @@ import com.vividsolutions.jts.geom.Coordinate;
* ------------ ---------- ----------- --------------------------
* 06 Nov 2006 jkorman Initial Coding
* 29 Sept 2008 dhladky Added more stuff to finish SkewT.
* 25 Jul 2013 2190 mschenke Moved common sounding calculation
* from PopupSkewTDialog to here
* </pre>
*
* @author jkorman
@ -76,6 +79,8 @@ public class WxMath {
private static final double EPS = Mmoist / Mdry;
private static float[] muParcelTrajectoryPressures = new float[20];
private static double[][][] DRY_ADIABATS;
static {
@ -84,6 +89,11 @@ public class WxMath {
for (int i = -30; i <= 50; i += 10) {
DRY_ADIABATS[j++] = createDryAdiabatIsoLine(i, 1000, 300, 10);
}
int i = 0;
for (float p = 1000; p >= 50; p -= 50, ++i) {
muParcelTrajectoryPressures[i] = p;
}
}
/**
@ -137,6 +147,40 @@ public class WxMath {
return DRY_ADIABATS;
}
/**
* @param sounding
*/
public static float[] derivemuParcelTrajectory(VerticalSounding soundingData) {
float[] muParcelTrajectory = new float[muParcelTrajectoryPressures.length];
float thetae, maxthetae = -999.0f;
float etpar, tp;
for (int i = 0; i < soundingData.size(); i++) {
float tt = soundingData.get(i).getTemperature();
float td = soundingData.get(i).getDewpoint();
float p = soundingData.get(i).getPressure();
thetae = Controller.ept(tt, td, p);
if (thetae > maxthetae && soundingData.get(i).getPressure() > 500)
maxthetae = thetae;
}
for (int i = 0; i < muParcelTrajectoryPressures.length; ++i) {
float p = muParcelTrajectoryPressures[i];
etpar = (float) (maxthetae * (Math.pow(p / 1000.0f, 0.286f)));
tp = Controller.temp_of_te(etpar, p);
muParcelTrajectory[20 - (int) (p / 50)] = tp;
}
return muParcelTrajectory;
}
/**
* Returns the pressures used in
* {@link #derivemuParcelTrajectory(VerticalSounding)}
*
* @return
*/
public static float[] getMuParcelTrajectoryPressures() {
return muParcelTrajectoryPressures;
}
/**
* Convert wind speed and direction to U/V components.
*
@ -195,7 +239,8 @@ public class WxMath {
tempPressure.y = Math.pow(10, ((point.y - 132.182) / -44.061));
tempPressure.x = (point.x - (0.90692 * point.y)) / 0.54;
tempPressure.x += SoundingPrefs.getSoundingPrefs().getTemperatureOffset();
tempPressure.x += SoundingPrefs.getSoundingPrefs()
.getTemperatureOffset();
return tempPressure;
}

View file

@ -0,0 +1,68 @@
/**
* 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.sounding.adapter;
import com.raytheon.uf.common.sounding.VerticalSounding;
import com.raytheon.uf.common.time.DataTime;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Interface for an object that provides soundings for a time and location
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 19, 2013 2190 mschenke Initial creation
*
* </pre>
*
* @author mschenke
* @version 1.0
*/
public interface IVerticalSoundingProvider {
/**
* The available times the provider has soundings for
*
* @return
*/
public DataTime[] getSoundingTimes();
/**
* Given a time and location, the provider will attempt to create a
* {@link VerticalSounding}
*
* @param time
* @param location
* @return
*/
public VerticalSounding getSounding(DataTime time, Coordinate location);
/**
* The name of the sounding provider's data source
*
* @return
*/
public String getSoundingSource();
}

View file

@ -25,7 +25,6 @@
<import feature="com.raytheon.uf.viz.sounding.feature" version="1.0.0.qualifier"/>
<import feature="com.raytheon.uf.viz.displays.feature" version="1.0.0.qualifier"/>
<import feature="com.raytheon.uf.viz.ncep.displays.feature" version="1.0.0.qualifier"/>
<import feature="com.raytheon.uf.viz.d2d.skewt.feature" version="1.0.0.qualifier"/>
</requires>
<plugin

View file

@ -37,7 +37,6 @@ Import-Package: com.raytheon.edex.meteoLib,
com.raytheon.uf.viz.d2d.ui.perspectives,
com.raytheon.uf.viz.sounding,
com.raytheon.viz.core.graphing,
com.raytheon.viz.skewt,
com.vividsolutions.jts.geom,
gov.noaa.nws.ncep.common.dataplugin.ncuair,
gov.noaa.nws.ncep.edex.common.ncinventory,