diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractDescriptor.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractDescriptor.java index e27260027b..5d51ceffaf 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractDescriptor.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/AbstractDescriptor.java @@ -37,15 +37,12 @@ import org.geotools.coverage.grid.GeneralGridEnvelope; import org.geotools.coverage.grid.GeneralGridGeometry; import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.geometry.GeneralEnvelope; -import org.geotools.referencing.CRS; -import org.geotools.referencing.operation.DefaultMathTransformFactory; -import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.opengis.referencing.crs.GeneralDerivedCRS; import org.opengis.referencing.datum.PixelInCell; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; +import com.raytheon.uf.common.geospatial.TransformFactory; import com.raytheon.uf.common.serialization.adapters.GridGeometryAdapter; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -718,18 +715,9 @@ public abstract class AbstractDescriptor extends ResourceGroup implements protected void setupTransforms() throws Exception { GeneralGridGeometry gridGeometry = getGridGeometry(); - MathTransform worldToCRS = getWorldToCRSTransform(gridGeometry); - if (worldToCRS != null) { - MathTransform crsToPixel = gridGeometry.getGridToCRS( - PixelInCell.CELL_CENTER).inverse(); - worldToPixel = new DefaultMathTransformFactory() - .createConcatenatedTransform(worldToCRS, crsToPixel); - pixelToWorld = worldToPixel.inverse(); - - } else { - pixelToWorld = null; - worldToPixel = null; - } + worldToPixel = TransformFactory.worldToGrid(gridGeometry, + PixelInCell.CELL_CENTER); + pixelToWorld = (worldToPixel != null ? worldToPixel.inverse() : null); } /* @@ -869,28 +857,4 @@ public abstract class AbstractDescriptor extends ResourceGroup implements false), envelope); } - /** - * Get the world to CRS transform used for {@link #worldToPixel(double[])} - * and {@link #pixelToWorld(double[])} - * - * @param gridGeometry - * @return The world to gridGeometry CRS transform or null if there is none - */ - public static MathTransform getWorldToCRSTransform( - GeneralGridGeometry gridGeometry) { - CoordinateReferenceSystem crs = gridGeometry.getEnvelope() - .getCoordinateReferenceSystem(); - if (crs instanceof GeneralDerivedCRS) { - GeneralDerivedCRS projCRS = (GeneralDerivedCRS) crs; - CoordinateReferenceSystem worldCRS = projCRS.getBaseCRS(); - try { - return CRS.findMathTransform(worldCRS, crs); - } catch (FactoryException e) { - statusHandler.handle(Priority.PROBLEM, - "Error setting up Math Transforms," - + " this descriptor may not work properly", e); - } - } - return null; - } } diff --git a/cave/com.raytheon.uf.viz.d2d.core/src/com/raytheon/uf/viz/d2d/core/time/D2DTimeMatcher.java b/cave/com.raytheon.uf.viz.d2d.core/src/com/raytheon/uf/viz/d2d/core/time/D2DTimeMatcher.java index 4047e9f945..91f07b67a7 100644 --- a/cave/com.raytheon.uf.viz.d2d.core/src/com/raytheon/uf/viz/d2d/core/time/D2DTimeMatcher.java +++ b/cave/com.raytheon.uf.viz.d2d.core/src/com/raytheon/uf/viz/d2d/core/time/D2DTimeMatcher.java @@ -42,6 +42,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.DataTime; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.viz.core.AbstractTimeMatcher; +import com.raytheon.uf.viz.core.IDisplayPane; import com.raytheon.uf.viz.core.IDisplayPaneContainer; import com.raytheon.uf.viz.core.VizConstants; import com.raytheon.uf.viz.core.comm.PerspectiveSpecificLoadProperties; @@ -229,8 +230,10 @@ public class D2DTimeMatcher extends AbstractTimeMatcher { @Override public void redoTimeMatching(IDescriptor descriptor) throws VizException { synchronized (this) { - if (timeMatchBasis != null && ! validateTimeMatchBasis(descriptor.getResourceList())) - timeMatchBasis = null; + if (timeMatchBasis != null && timeMatchBasis.getDescriptor() == descriptor && + ! validateTimeMatchBasis(descriptor)) { + changeTimeMatchBasis(null); + } if (timeMatchBasis != null) { IDescriptor tmDescriptor = timeMatchBasis.getDescriptor(); if (tmDescriptor != null) { @@ -1053,6 +1056,33 @@ public class D2DTimeMatcher extends AbstractTimeMatcher { configFactory.resetMultiload(); } + private boolean validateTimeMatchBasis(IDescriptor descriptor ) { + /* + * If a resource is shared by multiple panels (this can be the case with + * tools, at least), then it is necessary to search all of them as + * resource.descriptor() may not contain resource. TODO: Don't allow + * this condition to occur? + */ + IRenderableDisplay display = descriptor.getRenderableDisplay(); + IDisplayPaneContainer container = display != null ? + display.getContainer() : null; + if (container != null) { + for (IDisplayPane pane : container.getDisplayPanes()) { + IRenderableDisplay paneDisplay = pane.getRenderableDisplay(); + IDescriptor paneDescriptor = paneDisplay != null ? + paneDisplay.getDescriptor() : null; + if (paneDescriptor != null + && validateTimeMatchBasis(paneDescriptor + .getResourceList())) { + return true; + } + } + } else { + return validateTimeMatchBasis(descriptor.getResourceList()); + } + return false; + } + private boolean validateTimeMatchBasis(ResourceList list) { for (ResourcePair rp : list) { AbstractVizResource rsc = rp.getResource(); diff --git a/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/point/KmlPointImageExtension.java b/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/point/KmlPointImageExtension.java index 24e7829b77..eac078893e 100644 --- a/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/point/KmlPointImageExtension.java +++ b/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/point/KmlPointImageExtension.java @@ -57,15 +57,17 @@ import de.micromata.opengis.kml.v_2_2_0.Style; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jun 1, 2012 bsteffen Initial creation + * Jun 1, 2012 bsteffen Initial creation + * Aug 27, 2013 #2287 randerso Removed 180 degree adjustment required by error + * in Maputil.rotation * * * * @author bsteffen * @version 1.0 */ -public class KmlPointImageExtension extends GraphicsExtension - implements IPointImageExtension { +public class KmlPointImageExtension extends + GraphicsExtension implements IPointImageExtension { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(KmlRasterImageExtension.class); @@ -113,7 +115,7 @@ public class KmlPointImageExtension extends GraphicsExtension IconStyle iconStyle = style.createAndSetIconStyle(); iconStyle.setScale(options.getPlotIconScale()); - double heading = 180 + MapUtil.rotation( + double heading = MapUtil.rotation( new com.vividsolutions.jts.geom.Coordinate(loc .getLongitude(), loc.getLatitude()), gridGeometry); diff --git a/cave/com.raytheon.uf.viz.ncep.dataplugins.feature/feature.xml b/cave/com.raytheon.uf.viz.ncep.dataplugins.feature/feature.xml index e6c9832ff4..414da7b814 100644 --- a/cave/com.raytheon.uf.viz.ncep.dataplugins.feature/feature.xml +++ b/cave/com.raytheon.uf.viz.ncep.dataplugins.feature/feature.xml @@ -233,4 +233,11 @@ version="0.0.0" unpack="false"/> + + diff --git a/cave/com.raytheon.uf.viz.ncep.displays.feature/feature.xml b/cave/com.raytheon.uf.viz.ncep.displays.feature/feature.xml index 0ddf6dcddd..3cd2684160 100644 --- a/cave/com.raytheon.uf.viz.ncep.displays.feature/feature.xml +++ b/cave/com.raytheon.uf.viz.ncep.displays.feature/feature.xml @@ -107,13 +107,6 @@ version="0.0.0" unpack="false"/> - - - - - - - - - - - - + + diff --git a/cave/com.raytheon.uf.viz.objectiveanalysis/src/com/raytheon/uf/viz/objectiveanalysis/rsc/OAResource.java b/cave/com.raytheon.uf.viz.objectiveanalysis/src/com/raytheon/uf/viz/objectiveanalysis/rsc/OAResource.java index 572e12a40b..82e609ba87 100644 --- a/cave/com.raytheon.uf.viz.objectiveanalysis/src/com/raytheon/uf/viz/objectiveanalysis/rsc/OAResource.java +++ b/cave/com.raytheon.uf.viz.objectiveanalysis/src/com/raytheon/uf/viz/objectiveanalysis/rsc/OAResource.java @@ -79,6 +79,7 @@ import com.raytheon.uf.viz.core.style.VizStyleException; import com.raytheon.uf.viz.core.style.level.SingleLevel; import com.raytheon.viz.core.contours.rsc.displays.GriddedContourDisplay; import com.raytheon.viz.core.contours.rsc.displays.GriddedVectorDisplay; +import com.raytheon.viz.core.contours.util.VectorGraphicsRenderableFactory; import com.raytheon.viz.core.drawables.ColorMapParameterFactory; import com.raytheon.viz.core.rsc.displays.GriddedImageDisplay; import com.raytheon.viz.core.rsc.displays.GriddedImageDisplay.GriddedImagePaintProperties; @@ -93,8 +94,10 @@ import com.vividsolutions.jts.geom.Coordinate; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 5, 2009 randerso Initial creation - * Jan 8, 2010 4205 jelkins add equals checking for OA resources + * Nov 5, 2009 randerso Initial creation + * Jan 8, 2010 4205 jelkins add equals checking for OA resources + * Aug 27, 2013 2287 randerso Added new parameters to GriddedVectorDisplay + * constructor * * * @@ -424,9 +427,10 @@ public class OAResource extends FloatBuffer mag = data; data.position(transformer.getNx() * transformer.getNy()); FloatBuffer dir = data.slice(); + VectorGraphicsRenderableFactory factory = new VectorGraphicsRenderableFactory(); GriddedVectorDisplay vector = new GriddedVectorDisplay(mag, - dir, descriptor, transformer.getGridGeom(), 80, - displayType); + dir, descriptor, transformer.getGridGeom(), 80, 0.75, + true, displayType, factory); renderableMap.put(dataTime, vector); break; diff --git a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/cachedata/PythonCacheGuidanceJob.java b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/cachedata/PythonCacheGuidanceJob.java index 8741bbc213..7e906888b8 100644 --- a/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/cachedata/PythonCacheGuidanceJob.java +++ b/cave/com.raytheon.viz.aviation/src/com/raytheon/viz/aviation/cachedata/PythonCacheGuidanceJob.java @@ -55,6 +55,7 @@ import com.raytheon.viz.aviation.monitor.AvnPyUtil; * Nov 11, 2012 1298 rferrel Non-blocking dialog discovered problem * adding dispose listener when not on the * UI thread. + * Aug 26, 2013 #2283 lvenable Cleaned up some synchronized code. * * * @@ -200,7 +201,7 @@ public class PythonCacheGuidanceJob extends * * @param req */ - private synchronized void waitAdd(CacheGuidanceRequest req) { + private void waitAdd(CacheGuidanceRequest req) { synchronized (waitMonitor) { if (waitList.contains(req) == false) { waitList.add(req); @@ -213,7 +214,7 @@ public class PythonCacheGuidanceJob extends * * @param req */ - private synchronized void waitRemove(CacheGuidanceRequest req) { + private void waitRemove(CacheGuidanceRequest req) { synchronized (waitMonitor) { waitList.remove(req); waitMonitor.notify(); @@ -286,11 +287,13 @@ public class PythonCacheGuidanceJob extends * - Unique tag * @return siteObj */ - public synchronized String getSiteObj(String siteID, String tag) { + public String getSiteObj(String siteID, String tag) { String siteObj = null; - Map siteObjs = siteObjMaps.get(siteID); - if (siteObjs != null) { - siteObj = siteObjs.get(tag); + synchronized (siteObjMaps) { + Map siteObjs = siteObjMaps.get(siteID); + if (siteObjs != null) { + siteObj = siteObjs.get(tag); + } } return siteObj; } @@ -303,10 +306,12 @@ public class PythonCacheGuidanceJob extends * @param tag * - Unique tag */ - private synchronized void clearSiteObj(String siteID, String tag) { + private void clearSiteObj(String siteID, String tag) { Map siteObjs = siteObjMaps.get(siteID); - if (siteObjs != null) { - siteObjs.remove(tag); + synchronized (siteObjMaps) { + if (siteObjs != null) { + siteObjs.remove(tag); + } } } @@ -317,7 +322,7 @@ public class PythonCacheGuidanceJob extends * A map with key of stites an array of tags to clear for the * site */ - public synchronized void clearSiteObjs(Map> tags) { + public void clearSiteObjs(Map> tags) { for (Object s : tags.keySet().toArray()) { String siteID = s.toString(); for (String tag : tags.get(siteID)) { @@ -336,14 +341,15 @@ public class PythonCacheGuidanceJob extends * @param siteObj * - Pickle string to cache */ - private synchronized void setSiteObj(String siteID, String tag, - String siteObj) { - Map siteObjs = siteObjMaps.get(siteID); - if (siteObjs == null) { - siteObjs = new HashMap(); - siteObjMaps.put(siteID, siteObjs); + private void setSiteObj(String siteID, String tag, String siteObj) { + synchronized (siteObjMaps) { + Map siteObjs = siteObjMaps.get(siteID); + if (siteObjs == null) { + siteObjs = new HashMap(); + siteObjMaps.put(siteID, siteObjs); + } + siteObjs.put(tag, siteObj); } - siteObjs.put(tag, siteObj); } /* diff --git a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/AbstractGriddedDisplay.java b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/AbstractGriddedDisplay.java index 6ab8438b5d..c9ffc123e4 100644 --- a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/AbstractGriddedDisplay.java +++ b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/AbstractGriddedDisplay.java @@ -57,6 +57,9 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Apr 23, 2010 bsteffen Initial creation * Aug 07, 2013 2077 bsteffen Revise pixel size calculations. + * Aug 27, 2013 2287 randerso Replaced hard coded constant with densityFactor + * parameter to allow application specific density + * scaling to better match A1 displays * * * @@ -103,6 +106,8 @@ public abstract class AbstractGriddedDisplay implements IRenderable { protected final int size; + protected final double densityFactor; + protected RGB color; protected double density = 1.0; @@ -120,16 +125,18 @@ public abstract class AbstractGriddedDisplay implements IRenderable { * @param descriptor * @param gridGeometryOfGrid * @param size - * @param plotLocations - * Pre-configured plot locations. If null, they will be created. + * @param densityFactor + * adjustment factor to make density match A1 */ public AbstractGriddedDisplay(IMapDescriptor descriptor, - GeneralGridGeometry gridGeometryOfGrid, int size) { + GeneralGridGeometry gridGeometryOfGrid, int size, + double densityFactor) { this.calculationQueue = new ConcurrentLinkedQueue(); this.descriptor = descriptor; this.gridGeometryOfGrid = gridGeometryOfGrid; this.size = size; + this.densityFactor = densityFactor; this.gridDims = new int[] { this.gridGeometryOfGrid.getGridRange().getSpan(0), @@ -211,7 +218,8 @@ public abstract class AbstractGriddedDisplay implements IRenderable { * infinite loops. */ int increment = Math.max( - (int) Math.ceil(adjSize * 0.75 / pixelSize / density), 1); + (int) Math.ceil(adjSize * densityFactor / pixelSize / density), + 1); for (int x = 0; x < gridDims[0]; x += increment) { for (int y = 0; y < gridDims[1]; y += increment) { diff --git a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/GriddedVectorDisplay.java b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/GriddedVectorDisplay.java index dd79a5f704..e906f0d79f 100644 --- a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/GriddedVectorDisplay.java +++ b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/rsc/displays/GriddedVectorDisplay.java @@ -34,6 +34,7 @@ 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.DisplayType; +import com.raytheon.viz.core.contours.util.IVectorGraphicsRenderableFactory; import com.raytheon.viz.core.contours.util.VectorGraphicsRenderable; import com.vividsolutions.jts.geom.Coordinate; @@ -53,6 +54,13 @@ import com.vividsolutions.jts.geom.Coordinate; * Jun 22, 2010 bsteffen Initial creation * Feb 07, 2011 7948 bkowal added a public method to get * the direction. + * Aug 27, 2013 2287 randerso Added VectorGraphicsRenderable Factory to allow + * application specific rendering of wind barbs and + * arrows. + * Added densityFactor to allow application specific + * adjustment of density. + * Added gridRelative flag to indicate whether direction + * data is relative to grid or true north * * * @@ -69,36 +77,43 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { private LineStyle lineStyle; - private double scale = 0.6; - private IExtent lastExtent; private VectorGraphicsRenderable vectorRenderable; + private boolean gridRelative; + private DisplayType displayType; private GeodeticCalculator gc; + private IVectorGraphicsRenderableFactory factory; + /** * @param magnitude * @param direction - * @param mode * @param descriptor * @param gridGeometryOfGrid - * @param imageSize - * @param gridLocation - * @param forceCircle - * @param plotLocations - * Pre-configured plot locations. If null, they will be created. + * @param size + * @param densityFactor + * adjustment factor to make density match A1 + * @param gridRelative + * true if direction is grid relative, false if relative to true + * north + * @param displayType + * @param factory */ public GriddedVectorDisplay(FloatBuffer magnitude, FloatBuffer direction, IMapDescriptor descriptor, GeneralGridGeometry gridGeometryOfGrid, - int size, DisplayType displayType) { - super(descriptor, gridGeometryOfGrid, size); + int size, double densityFactor, boolean gridRelative, + DisplayType displayType, IVectorGraphicsRenderableFactory factory) { + super(descriptor, gridGeometryOfGrid, size, densityFactor); this.magnitude = magnitude; this.direction = direction; + this.gridRelative = gridRelative; this.displayType = displayType; this.gc = new GeodeticCalculator(descriptor.getCRS()); + this.factory = factory; } @Override @@ -110,8 +125,8 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { lastExtent = paintProps.getView().getExtent().clone(); } if (vectorRenderable == null) { - vectorRenderable = new VectorGraphicsRenderable(descriptor, target, - this.size, this.scale); + vectorRenderable = factory.createRenderable(descriptor, target, + this.size); super.paint(target, paintProps); } vectorRenderable.setColor(this.color); @@ -126,12 +141,13 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { super.issueRefresh(); } + @Override protected void paint(Coordinate ijcoord, PaintProperties paintProps, Coordinate plotLoc, double adjSize) throws VizException { int idx = (int) (ijcoord.x + (ijcoord.y * this.gridDims[0])); float spd = this.magnitude.get(idx); - float dir = this.direction.get(idx) - 180; + float dir = this.direction.get(idx); if (dir < -999999 || dir > 9999999) { // perhaps this check should limit +/- 180 @@ -161,9 +177,13 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { newWorldLocation[1]); } - dir = dir - + (float) MapUtil.rotation(latLon, - GridGeometry2D.wrap(gridGeometryOfGrid)); + if (gridRelative) { + // rotate data from grid up to true north + dir += (float) MapUtil.rotation(latLon, + GridGeometry2D.wrap(gridGeometryOfGrid)); + } + + // rotate dir from true north to display up dir -= this.gc.getAzimuth(); } catch (Exception e) { throw new VizException(e); @@ -185,14 +205,6 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { } } - /** - * - * @param color - */ - public void setScale(double scale) { - this.scale = scale; - } - public void setLineWidth(int lineWidth) { this.lineWidth = lineWidth; } @@ -208,6 +220,7 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { * @param density * the density to set */ + @Override public boolean setDensity(double density) { if (super.setDensity(density)) { disposeResources(); @@ -223,6 +236,7 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { * @param magnification * the magnification to set */ + @Override public boolean setMagnification(double magnification) { if (super.setMagnification(magnification)) { disposeResources(); @@ -245,6 +259,7 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { return direction; } + @Override protected void disposeResources() { if (vectorRenderable != null) { vectorRenderable.dispose(); @@ -252,6 +267,7 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay { } } + @Override protected Coordinate createResource(Coordinate coord) throws VizException { return coord; } diff --git a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/IVectorGraphicsRenderableFactory.java b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/IVectorGraphicsRenderableFactory.java new file mode 100644 index 0000000000..0084db2e60 --- /dev/null +++ b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/IVectorGraphicsRenderableFactory.java @@ -0,0 +1,46 @@ +/** + * 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.core.contours.util; + +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.drawables.IDescriptor; + +/** + * Interface for factory class to create a VectorGraphicsRenderable for + * GriddedVectorDisplay + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 22, 2013     #2287  randerso     Initial creation
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public interface IVectorGraphicsRenderableFactory { + public VectorGraphicsRenderable createRenderable(IDescriptor descriptor, + IGraphicsTarget target, double size); +} diff --git a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/VectorGraphicsRenderable.java b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/VectorGraphicsRenderable.java index 7216f7465f..4fee99f2d2 100644 --- a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/VectorGraphicsRenderable.java +++ b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/VectorGraphicsRenderable.java @@ -38,7 +38,8 @@ import com.vividsolutions.jts.geom.Coordinate; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * May 27, 2011 bsteffen Initial creation + * May 27, 2011 bsteffen Initial creation + * Aug 27, 2013 #2287 randerso Refactored to allow subclassing * * * @@ -47,17 +48,17 @@ import com.vividsolutions.jts.geom.Coordinate; */ public class VectorGraphicsRenderable { - private IWireframeShape lastShape; + protected IWireframeShape lastShape; - private double size = 80; + protected double size = 80; - private double scale = 1.0; + protected double scale = 1.0; - private RGB color; + protected RGB color; - private float lineWidth = 1.0f; + protected float lineWidth = 1.0f; - private LineStyle lineStyle; + protected LineStyle lineStyle; public VectorGraphicsRenderable(IDescriptor descriptor, IGraphicsTarget target, double size, double scale) { @@ -89,36 +90,7 @@ public class VectorGraphicsRenderable { public void paintBarb(Coordinate plotLoc, double adjSize, double spd, double dir) { if (spd < 2.5) { - double[][] line = new double[9][2]; - - double aa = adjSize * .030; - double saa = aa * 0.707; - - line[8][0] = line[0][0] = plotLoc.x + aa; - line[8][1] = line[0][1] = plotLoc.y; - line[1][0] = plotLoc.x + saa; - line[1][1] = plotLoc.y + saa; - - line[2][0] = plotLoc.x; - line[2][1] = plotLoc.y + aa; - - line[3][0] = plotLoc.x - saa; - line[3][1] = plotLoc.y + saa; - - line[4][0] = plotLoc.x - aa; - line[4][1] = plotLoc.y; - - line[5][0] = plotLoc.x - saa; - line[5][1] = plotLoc.y - saa; - - line[6][0] = plotLoc.x; - line[6][1] = plotLoc.y - aa; - - line[7][0] = plotLoc.x + saa; - line[7][1] = plotLoc.y - saa; - - lastShape.addLineSegment(line); - + paintPoint(plotLoc, adjSize); return; } @@ -198,6 +170,38 @@ public class VectorGraphicsRenderable { } } + protected void paintPoint(Coordinate plotLoc, double adjSize) { + double[][] line = new double[9][2]; + + double aa = adjSize * .030; + double saa = aa * 0.707; + + line[8][0] = line[0][0] = plotLoc.x + aa; + line[8][1] = line[0][1] = plotLoc.y; + line[1][0] = plotLoc.x + saa; + line[1][1] = plotLoc.y + saa; + + line[2][0] = plotLoc.x; + line[2][1] = plotLoc.y + aa; + + line[3][0] = plotLoc.x - saa; + line[3][1] = plotLoc.y + saa; + + line[4][0] = plotLoc.x - aa; + line[4][1] = plotLoc.y; + + line[5][0] = plotLoc.x - saa; + line[5][1] = plotLoc.y - saa; + + line[6][0] = plotLoc.x; + line[6][1] = plotLoc.y - aa; + + line[7][0] = plotLoc.x + saa; + line[7][1] = plotLoc.y - saa; + + lastShape.addLineSegment(line); + } + public void paintDualArrow(Coordinate plotLoc, double adjSize, double spd, double dir) { if (spd < 4.0) { diff --git a/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/VectorGraphicsRenderableFactory.java b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/VectorGraphicsRenderableFactory.java new file mode 100644 index 0000000000..2ceddf324d --- /dev/null +++ b/cave/com.raytheon.viz.core.contours/src/com/raytheon/viz/core/contours/util/VectorGraphicsRenderableFactory.java @@ -0,0 +1,77 @@ +/** + * 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.core.contours.util; + +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.drawables.IDescriptor; + +/** + * VectorGraphicsRenderable Factory + * + * Constructs the VectorGraphicsRenderable for D2D usage of GriddedVectorDisplay + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 22, 2013     #2287  randerso     Initial creation
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class VectorGraphicsRenderableFactory implements + IVectorGraphicsRenderableFactory { + private double scale; + + public VectorGraphicsRenderableFactory() { + this.scale = 0.6; + } + + public VectorGraphicsRenderableFactory(double scale) { + this.scale = scale; + } + + /** + * @param scale + * the scale to set + */ + public void setScale(double scale) { + this.scale = scale; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.core.contours.util.IVectorGraphicsRenderableFactory# + * createRenderable() + */ + @Override + public VectorGraphicsRenderable createRenderable(IDescriptor descriptor, + IGraphicsTarget target, double size) { + return new VectorGraphicsRenderable(descriptor, target, size, scale); + } + +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ShowAutoSaveIntervalDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ShowAutoSaveIntervalDialog.java index 49746c9c93..ab972e07ac 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ShowAutoSaveIntervalDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ShowAutoSaveIntervalDialog.java @@ -20,10 +20,12 @@ package com.raytheon.viz.gfe.actions; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; -import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; @@ -42,8 +44,9 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jan 23, 2008 Eric Babin Initial Creation - * Jul 8, 2008 randerso reworked + * Jul 8, 2008 randerso reworked * Oct 23, 2012 1287 rferrel Changes for non-blocking AutoSaveIntervalDialog. + * Aug 27, 2013 2302 randerso Code clean up for AutoSaveJob changes * * * @@ -51,7 +54,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback; * @version 1.0 */ public class ShowAutoSaveIntervalDialog extends AbstractHandler { - private AutoSaveIntervalDialog dialog; + final private Map dialogMap = new HashMap(); /** * @@ -69,47 +72,28 @@ public class ShowAutoSaveIntervalDialog extends AbstractHandler { */ @Override public Object execute(ExecutionEvent arg0) throws ExecutionException { + final IWorkbenchWindow window = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow(); + DataManager dm = DataManagerUIFactory.findInstance(window); + if (dm == null) { + return null; + } + + AutoSaveIntervalDialog dialog = dialogMap.get(window); if (dialog == null || dialog.getShell() == null || dialog.isDisposed()) { - final IWorkbenchWindow window = PlatformUI.getWorkbench() - .getActiveWorkbenchWindow(); - Shell shell = window.getShell(); - int interval = AutoSaveJob.getInterval(); - boolean autoSaveEnabled = interval > 0; - if (!autoSaveEnabled) { - interval = AutoSaveJob.MAX_INTERVAL; - } - dialog = new AutoSaveIntervalDialog(shell, interval, - autoSaveEnabled); + AutoSaveJob autoSaveJob = dm.getAutoSaveJob(); + + Shell shell = window.getShell(); + dialog = new AutoSaveIntervalDialog(shell, autoSaveJob); + dialogMap.put(window, dialog); dialog.setBlockOnOpen(false); dialog.setCloseCallback(new ICloseCallback() { @Override public void dialogClosed(Object returnValue) { - if (returnValue instanceof Integer) { - int returnCode = (Integer) returnValue; - if (returnCode == Window.OK) { - DataManager dm = DataManagerUIFactory - .findInstance(window); - // update - if (dialog.isAutoSaveEnabled()) { - int interval = dialog.getCurrentInterval(); - AutoSaveJob.setInterval(interval); - if (dm != null) { - dm.enableAutoSave(); - } - DataManagerUIFactory.findInstance(window) - .enableAutoSave(); - } else { - AutoSaveJob.setInterval(0); - if (dm != null) { - dm.disableAutoSave(); - } - } - - } - } + dialogMap.remove(window); } }); dialog.open(); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java index a7df8ff665..721d9188a1 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java @@ -96,6 +96,7 @@ import com.raytheon.viz.gfe.textformatter.TextProductManager; * initialized by constructor. * 04/24/2013 1936 dgilling Move initialization of TextProductMgr * to GFE startup. + * 08/27/2013 2302 randerso Code cleanup for AutoSaveJob * * * @@ -271,18 +272,10 @@ public class DataManager { } /** - * Start auto save jobs + * @return the autoSaveJob */ - public void enableAutoSave() { - autoSaveJob.cancel(); - autoSaveJob.reSchedule(); - } - - /** - * Stop auto save jobs - */ - public void disableAutoSave() { - autoSaveJob.cancel(); + public AutoSaveJob getAutoSaveJob() { + return autoSaveJob; } /** diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java index 69d2335a85..795a4f62f5 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/Parm.java @@ -84,6 +84,7 @@ import com.raytheon.viz.gfe.GFEServerException; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.griddata.AbstractGridData; import com.raytheon.viz.gfe.core.griddata.IGridData; +import com.raytheon.viz.gfe.core.parm.ParmSaveJob.ParmSaveStatus; import com.raytheon.viz.gfe.core.parm.ParmState.InterpMode; import com.raytheon.viz.gfe.core.wxvalue.DiscreteWxValue; import com.raytheon.viz.gfe.core.wxvalue.ScalarWxValue; @@ -182,6 +183,8 @@ import com.vividsolutions.jts.geom.Coordinate; * Mar 13, 2013 1792 bsteffen Improve performance of gfe parm average * ant time weighted average. * Apr 02, 2013 #1774 randerso Fixed a possible deadlock issue. + * Aug 27, 2013 #2302 randerso Fix simultaneous save issue + * * * * @author chammack @@ -229,6 +232,8 @@ public abstract class Parm implements Comparable { protected boolean disposed; + private ParmSaveJob saveJob; + /** * The create from scratch mode */ @@ -360,6 +365,7 @@ public abstract class Parm implements Comparable { } this.disposed = false; + this.saveJob = new ParmSaveJob(this); } public void dispose() { @@ -708,7 +714,7 @@ public abstract class Parm implements Comparable { * Save a parameter * * @param all - * @return + * @return true if save successful */ public boolean saveParameter(boolean all) { if (inParmEdit) { @@ -729,14 +735,16 @@ public abstract class Parm implements Comparable { /** * Save a parameter * - * @param tr - * @return + * @param times + * TimeRanges to be saved + * @return true if save successful */ - public boolean saveParameter(List tr) { + public boolean saveParameter(List times) { if (inParmEdit) { return false; } else { - return saveParameterSubClass(tr); + ParmSaveStatus status = this.saveJob.requestSave(times); + return status.isSuccessful(); } } @@ -744,7 +752,7 @@ public abstract class Parm implements Comparable { * Save a parameter * * @param tr - * @return + * @return true if save successful */ public boolean saveParameter(TimeRange tr) { ArrayList trs = new ArrayList(); @@ -756,7 +764,8 @@ public abstract class Parm implements Comparable { * Subclass specific save implementation * * @param tr - * @return + * TimeRanges to be saved + * @return true if save successful */ protected abstract boolean saveParameterSubClass(List tr); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/ParmSaveJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/ParmSaveJob.java new file mode 100644 index 0000000000..94329309a3 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/parm/ParmSaveJob.java @@ -0,0 +1,135 @@ +/** + * 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.gfe.core.parm; + +import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Semaphore; + +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.time.TimeRange; + +/** + * Job to queue up and work of parm save requests + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 27, 2013     #2302  randerso    Initial creation
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class ParmSaveJob extends Job { + public static class ParmSaveStatus { + boolean successful = false; + + Semaphore complete = new Semaphore(0); + + /** + * @return the successful + */ + public boolean isSuccessful() { + try { + complete.acquire(); + return successful; + } catch (InterruptedException e) { + return false; + } + } + + /** + * @param successful + * the successful to set + */ + private void setSuccessful(boolean successful) { + this.successful = successful; + complete.release(); + } + + } + + private class ParmSaveRequest { + private List times; + + private ParmSaveStatus status; + + public ParmSaveRequest(List times) { + this.times = times; + this.status = new ParmSaveStatus(); + } + } + + private Parm parm; + + private ConcurrentLinkedQueue saveQueue; + + /** + * @param parm + */ + public ParmSaveJob(Parm parm) { + super("ParmSaveJob"); + this.setSystem(true); + this.parm = parm; + this.saveQueue = new ConcurrentLinkedQueue(); + } + + /** + * Request save. + * + * Caller should call isSuccessful on the returned ParmSaveStatus object to + * await completion and to determine success + * + * @param times + * @return ParmSaveStatus object + */ + public ParmSaveStatus requestSave(List times) { + ParmSaveRequest request = new ParmSaveRequest(times); + this.saveQueue.add(request); + this.schedule(); + return request.status; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime. + * IProgressMonitor) + */ + @Override + protected IStatus run(IProgressMonitor monitor) { + ParmSaveRequest req = null; + while ((req = this.saveQueue.poll()) != null) { + boolean successful = parm.saveParameterSubClass(req.times); + req.status.setSuccessful(successful); + } + return Status.OK_STATUS; + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AutoSaveIntervalDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AutoSaveIntervalDialog.java index be323b64b4..69dc641414 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AutoSaveIntervalDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/AutoSaveIntervalDialog.java @@ -29,20 +29,21 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Scale; import org.eclipse.swt.widgets.Shell; import com.raytheon.viz.gfe.jobs.AutoSaveJob; import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; +import com.raytheon.viz.ui.widgets.SpinScale; /** - * The auto save iterval dialog. + * The auto save interval dialog. * *
  * SOFTWARE HISTORY
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * 	Jan 30, 2008					Eric Babin Initial Creation
+ * Jan 30, 2008            Eric Babin  Initial Creation
+ * Aug 27, 2013     #2302  randerso    Code cleanup
  * 
  * 
* @@ -52,98 +53,26 @@ import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; public class AutoSaveIntervalDialog extends CaveJFACEDialog { - private Composite top = null; - - private Label intervalMinutes; - - private Scale intervalScale; - - private int currentInterval = 1; - - private boolean autoSaveEnabled = false; + private AutoSaveJob autoSaveJob; private Button offButton; private Button onButton; - public AutoSaveIntervalDialog(Shell parent, int currentInterval, - boolean isEnabled) { + private Label intervalLabel; + + private SpinScale intervalScale; + + /** + * Constructor + * + * @param parent + * @param currentInterval + * @param isEnabled + */ + public AutoSaveIntervalDialog(Shell parent, AutoSaveJob autoSaveJob) { super(parent); - this.setShellStyle(SWT.TITLE | SWT.MODELESS | SWT.CLOSE); - this.currentInterval = currentInterval; - this.autoSaveEnabled = isEnabled; - } - - @Override - protected Control createDialogArea(Composite parent) { - top = (Composite) super.createDialogArea(parent); - - top.setLayout(new GridLayout(2, false)); - loadConfigData(); - initializeComponents(); - - return top; - } - - private void initializeComponents() { - - Group g = new Group(top, SWT.NONE); - g.setLayout(new GridLayout(2, true)); - - offButton = new Button(g, SWT.RADIO); - offButton.setText("Off"); - offButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - autoSaveEnabled = false; - } - }); - offButton.setSelection(!autoSaveEnabled); - - onButton = new Button(g, SWT.RADIO); - onButton.setText("On"); - onButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - autoSaveEnabled = true; - } - }); - onButton.setSelection(autoSaveEnabled); - - Composite c = new Composite(top, SWT.NONE); - GridLayout layout = new GridLayout(2, false); - layout.marginBottom = 10; - - c.setLayout(layout); - c.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL)); - - Label label = new Label(c, SWT.NONE); - label.setText("Save Interval in Minutes"); - GridData data = new GridData(); - data.horizontalSpan = 2; - label.setLayoutData(data); - - intervalScale = new Scale(c, SWT.HORIZONTAL); - intervalScale.setLayoutData(new GridData(120, SWT.DEFAULT)); - intervalScale.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - autoSaveEnabled = true; - currentInterval = intervalScale.getSelection(); - String s = Integer.toString(currentInterval); - intervalMinutes.setText(s); - intervalMinutes.setToolTipText(s); - onButton.setSelection(autoSaveEnabled); - offButton.setSelection(!autoSaveEnabled); - } - }); - intervalScale.setMinimum(AutoSaveJob.MIN_INTERVAL); - intervalScale.setMaximum(AutoSaveJob.MAX_INTERVAL); - intervalScale.setSelection(this.currentInterval); - - intervalMinutes = new Label(c, SWT.NONE); - intervalMinutes.setLayoutData(new GridData(20, SWT.DEFAULT)); - intervalMinutes.setText(String.valueOf(intervalScale.getSelection())); + this.autoSaveJob = autoSaveJob; } /* @@ -154,23 +83,92 @@ public class AutoSaveIntervalDialog extends CaveJFACEDialog { * .Shell) */ @Override - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText("Auto Save Interval Dialog"); + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText("Auto Save Interval Dialog"); } - /** - * Method for loading the various config data for the dialog. + @Override + protected Control createDialogArea(Composite parent) { + Composite comp = (Composite) super.createDialogArea(parent); + GridLayout layout = (GridLayout) comp.getLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + + Group group = new Group(comp, SWT.NONE); + layout = new GridLayout(2, false); + group.setLayout(layout); + GridData layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + group.setLayoutData(layoutData); + group.setText("Auto Save"); + + int interval = autoSaveJob.getInterval(); + + offButton = new Button(group, SWT.RADIO); + layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + offButton.setLayoutData(layoutData); + offButton.setText("Off"); + offButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + if (offButton.getSelection()) { + intervalLabel.setEnabled(false); + intervalScale.setEnabled(false); + } + } + }); + offButton.setSelection(interval == 0); + + onButton = new Button(group, SWT.RADIO); + layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false); + onButton.setLayoutData(layoutData); + onButton.setText("On"); + onButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + if (onButton.getSelection()) { + intervalLabel.setEnabled(true); + intervalScale.setEnabled(true); + } + } + }); + onButton.setSelection(interval > 0); + + intervalLabel = new Label(group, SWT.CENTER); + intervalLabel.setText("Save Interval in Minutes"); + layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1); + intervalLabel.setLayoutData(layoutData); + + intervalScale = new SpinScale(group, SWT.HORIZONTAL); + layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1); + layoutData.minimumWidth = 240; + intervalScale.setLayoutData(layoutData); + intervalScale.setMinimum(AutoSaveJob.MIN_INTERVAL); + intervalScale.setMaximum(AutoSaveJob.MAX_INTERVAL); + if (interval > 0) { + intervalScale.setSelection(interval); + } else { + intervalLabel.setEnabled(false); + intervalScale.setEnabled(false); + intervalScale.setSelection(AutoSaveJob.MAX_INTERVAL); + } + + return comp; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.dialogs.Dialog#okPressed() */ - private void loadConfigData() { - + @Override + protected void okPressed() { + if (offButton.getSelection()) { + autoSaveJob.setInterval(0); + } else { + autoSaveJob.setInterval(intervalScale.getSelection()); + } + super.okPressed(); } - public int getCurrentInterval() { - return currentInterval; - } - - public boolean isAutoSaveEnabled() { - return autoSaveEnabled; - } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/jobs/AutoSaveJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/jobs/AutoSaveJob.java index db6879b963..97eede7351 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/jobs/AutoSaveJob.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/jobs/AutoSaveJob.java @@ -24,11 +24,14 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; -import com.raytheon.viz.gfe.Activator; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.viz.gfe.GFEPreference; import com.raytheon.viz.gfe.PreferenceConstants; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.parm.Parm; +import com.raytheon.viz.gfe.ui.HazardUIUtils; /** * Job implementing the auto save functionality. Uses user preferences to @@ -38,7 +41,8 @@ import com.raytheon.viz.gfe.core.parm.Parm; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jun 25, 2008 Eric Babin Initial Creation + * Jun 25, 2008 Eric Babin Initial Creation + * Aug 27, 2013 #2302 randerso Fixed to behave more like A1, code cleanup * * * @@ -47,38 +51,34 @@ import com.raytheon.viz.gfe.core.parm.Parm; */ public class AutoSaveJob extends Job { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(AutoSaveJob.class); - private static final int MILLISECONDS_PER_MINUTE = 60 * 1000; - + /** + * Max auto save interval in minutes + */ public static final int MAX_INTERVAL = 60; + /** + * Min auto save interval in minutes + */ public static final int MIN_INTERVAL = 1; /** - * auto save interval in minutes, 0 = disabled + * auto save interval in milliseconds, 0 = disabled */ - private static int interval; - static { - int i = 0; - if (GFEPreference.storeAvailable()) { - i = GFEPreference - .getIntPreference(PreferenceConstants.GFE_AUTO_SAVE_INTERVAL); - } - - interval = i; - } + private long interval; /** * Set the auto save interval * - * @param i + * @param interval * desired interval in minutes */ - public static void setInterval(int i) { - interval = i; - - GFEPreference.setPreference(PreferenceConstants.GFE_AUTO_SAVE_INTERVAL, - Integer.toString(i)); + public void setInterval(int interval) { + this.interval = interval * TimeUtil.MILLIS_PER_MINUTE; + this.cancel(); + this.reSchedule(this.interval); } /** @@ -86,8 +86,8 @@ public class AutoSaveJob extends Job { * * @return interval in minutes */ - public static int getInterval() { - return interval; + public int getInterval() { + return (int) (interval / TimeUtil.MILLIS_PER_MINUTE); } private DataManager dataManager; @@ -104,17 +104,28 @@ public class AutoSaveJob extends Job { this.dataManager = dataManager; this.disposed = false; this.setSystem(true); + int pref = GFEPreference + .getIntPreference(PreferenceConstants.GFE_AUTO_SAVE_INTERVAL); + if (pref > MAX_INTERVAL) { + pref = MAX_INTERVAL; + } else if (pref < 0) { + pref = 0; + } - reSchedule(); + this.interval = pref * TimeUtil.MILLIS_PER_MINUTE; + reSchedule(this.interval); } /** - * Schedule this job to run after the desired interval + * Schedule this job to run after the desired + * + * @param delay + * interval in milliseconds */ - public void reSchedule() { + public void reSchedule(long delay) { if (!disposed) { - if (interval > 0) { - this.schedule(interval * MILLISECONDS_PER_MINUTE); + if (delay > 0) { + this.schedule(delay); } } else { dataManager = null; @@ -138,53 +149,51 @@ public class AutoSaveJob extends Job { */ @Override protected IStatus run(IProgressMonitor monitor) { - IStatus status = Status.OK_STATUS; - try { - Parm[] parms = this.dataManager.getParmManager().getModifiedParms(); - if (parms != null && parms.length != 0) { - String autoSaveResult = "GFE Auto Save called. Save of Parms["; - for (int i = 0; i < parms.length; i++) { - String name = parms[i].getParmID().getParmName(); - if (name.indexOf("Hazards") == -1) { - autoSaveResult += saveParm(parms[i]); - } else { - if (!tempHazardsExist()) { - saveParm(parms[i]); - autoSaveResult += saveParm(parms[i]); - } - } - } - autoSaveResult += "]"; + long delay = this.interval; + if (delay > 0) { + String msg = "GFE Auto Save called. "; + boolean success = false; + try { + Parm modifiedParm = getModifiedParm(); + if (modifiedParm != null) { + msg += "Save of Parm " + + modifiedParm.getParmID().getParmName() + " = "; - Activator.getDefault().getLog().log( - new Status(IStatus.INFO, Activator.PLUGIN_ID, - autoSaveResult)); + // save the data + success = modifiedParm.saveParameter(false); + msg += (success ? "success" : "failure"); + delay = 1500; + } else { + msg += "Nothing to save."; + } + statusHandler.info(msg); + } catch (Exception e) { + msg += "failure"; + statusHandler.error(msg, e); } - } catch (Exception e) { - status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, - "GFE auto save failed.", e); + reSchedule(delay); } - reSchedule(); - return status; + return Status.OK_STATUS; } /** - * If tempHazards exist, then autosave kicked off in the middle of merge - * hazard. (which creates a "temp" hazard with "haz" in the name. + * Find the first available modified parm. Skip Hazards if temp hazards + * exist * - * So we will ignore the "Hazard" WE parm save... - * - * @return if temp haz exists. + * @return the first available modified parm or null if none */ - private boolean tempHazardsExist() { - Parm[] parms = this.dataManager.getParmManager().getDisplayedParms(); - for (int i = 0; i < parms.length; i++) { - if (parms[i].getParmID().getParmName().indexOf("haz") != -1) { - return true; + private Parm getModifiedParm() { + boolean tempHazDisplayed = HazardUIUtils + .tempHazardsExist(this.dataManager); + for (Parm p : this.dataManager.getParmManager().getModifiedParms()) { + if (p.getParmID().getParmName().contains("Hazards") + && tempHazDisplayed) { + continue; + } else { + return p; } } - - return false; + return null; } /** diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java index 1921b058d2..028ced353e 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java @@ -161,6 +161,7 @@ import com.vividsolutions.jts.geom.Envelope; * May 11, 2012 njensen Allow rsc to be recycled * Nov 08, 2012 1298 rferrel Changes for non-blocking FuzzValueDialog. * Mar 04, 2013 1637 randerso Fix time matching for ISC grids + * Aug 27, 2013 2287 randerso Fixed scaling and direction of wind arrows * * * @@ -617,6 +618,7 @@ public class GFEResource extends } clearVectorDisplays(); + GFEVectorGraphicsRenderableFactory factory; for (VisualizationType type : visTypes) { switch (type) { case WIND_ARROW: @@ -626,24 +628,31 @@ public class GFEResource extends if (logFactor < 0.0) { logFactor = 0.0; } - // TODO: add logFactor to PointWindDisplay, - // GriddedVectorDisplay + factory = new GFEVectorGraphicsRenderableFactory( + logFactor, parm.getGridInfo().getMaxValue()); this.vectorDisplay.add(new GriddedVectorDisplay( mag, dir, descriptor, MapUtil .getGridGeometry(gs.getGridInfo() .getGridLoc()), getVectorSize("WindArrowDefaultSize"), - visTypeToDisplayType(type))); + 1.36, false, visTypeToDisplayType(type), + factory)); break; case WIND_BARB: - this.vectorDisplay.add(new GriddedVectorDisplay( - mag, dir, descriptor, MapUtil - .getGridGeometry(gs.getGridInfo() - .getGridLoc()), - getVectorSize("WindBarbDefaultSize"), - visTypeToDisplayType(type))); + factory = new GFEVectorGraphicsRenderableFactory( + 0.0, parm.getGridInfo().getMaxValue()); + this.vectorDisplay + .add(new GriddedVectorDisplay( + mag, + dir, + descriptor, + MapUtil.getGridGeometry(gs + .getGridInfo().getGridLoc()), + getVectorSize("WindBarbDefaultSize"), + 1.36, false, + visTypeToDisplayType(type), factory)); break; case IMAGE: @@ -1000,8 +1009,6 @@ public class GFEResource extends size = 60; } - size = (int) (size / 0.8); - int offset = parm.getDisplayAttributes().getFontOffset() + Activator.getDefault().getPreferenceStore() .getInt("Contour_font"); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEVectorGraphicsRenderable.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEVectorGraphicsRenderable.java new file mode 100644 index 0000000000..80dbbbde26 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEVectorGraphicsRenderable.java @@ -0,0 +1,213 @@ +/** + * 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.gfe.rsc; + +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.drawables.IDescriptor; +import com.raytheon.viz.core.contours.util.VectorGraphicsRenderable; +import com.vividsolutions.jts.geom.Coordinate; + +/** + * GFE version of VectorGraphicsRenderable. Subclassed to better match A1 GFE + * behavior + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 22, 2013     #2287  randerso     Initial creation
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class GFEVectorGraphicsRenderable extends VectorGraphicsRenderable { + double minLog = 0.0; + + double maxLog = 0.0; + + private double maxLimit; + + /** + * @param descriptor + * @param target + * @param size + * @param logFactor + * @param maxLimit + */ + public GFEVectorGraphicsRenderable(IDescriptor descriptor, + IGraphicsTarget target, double size, double logFactor, + double maxLimit) { + super(descriptor, target, size, logFactor); + + this.maxLimit = maxLimit; + if (logFactor > 0.0) { + minLog = Math.log(logFactor); + maxLog = Math.log(logFactor + 1.0); + } + } + + /** + * + * @param plotLoc + * @param adjSize + * @param spd + * @param dir + * barb direction in radians + */ + @Override + public void paintBarb(Coordinate plotLoc, double adjSize, double spd, + double dir) { + paintPoint(plotLoc, adjSize); + + int speed = (int) (spd + 2.5); + double staff = adjSize * .4; + double barb = staff * 0.30; + double add = staff * 0.105; + // DIRECTIONS + double uudd = -spd * Math.sin(dir); + double vvff = -spd * Math.cos(dir); + double dix = -uudd / spd; + double djy = -vvff / spd; + double dix1 = Math.cos(Math.toRadians(75)) * dix + + Math.sin(Math.toRadians(75)) * djy; + double djy1 = (-1) * Math.sin(Math.toRadians(75)) * dix + + Math.cos(Math.toRadians(75)) * djy; + + // SPEED AND COUNTERS: + int n50 = speed / 50; + int calcSpd = speed - 50 * n50; + int n10 = calcSpd / 10; + calcSpd = calcSpd - 10 * n10; + int n5 = calcSpd / 5; + double sx = ((n50 + n50 + n10 + n5 + 2)) * add; + staff = Math.max(adjSize * .4, sx); + + // DRAW STAFF + double ix2 = plotLoc.x; + double jy2 = plotLoc.y; + double ix1 = ix2 + dix * staff; + double jy1 = jy2 - djy * staff; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, { ix1, jy1 } }); + + // PLOT LONE HALF-BARB, IF NECESSARY + if (n50 == 0 && n10 == 0) { + ix2 = ix1 - dix * add; + jy2 = jy1 + djy * add; + ix1 = ix2 + dix1 * barb / 2.0; + jy1 = jy2 - djy1 * barb / 2.0; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, + { ix1, jy1 } }); + return; + } + + // PLOT FLAGS, IF NECESSARY + for (int i = 0; i < n50; i++) { + ix2 = ix1 + dix1 * barb; + jy2 = jy1 - djy1 * barb; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, + { ix1, jy1 } }); + ix1 = ix1 - dix * add * 2; + jy1 = jy1 + djy * add * 2; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, + { ix1, jy1 } }); + } + if (n50 > 0) { + ix1 = ix1 - dix * add / 2.0; + jy1 = jy1 + djy * add / 2.0; + } + + // PLOT BARB, IF NECESSARY + for (int i = 0; i < n10; i++) { + ix2 = ix1 + dix1 * barb; + jy2 = jy1 - djy1 * barb; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, + { ix1, jy1 } }); + ix1 = ix1 - dix * add; + jy1 = jy1 + djy * add; + } + + // PLOT HALF-BARB, IF NECESSARY + if (n5 != 0) { + ix2 = ix1 + dix1 * barb / 2.0; + jy2 = jy1 - djy1 * barb / 2.0; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, + { ix1, jy1 } }); + } + } + + @Override + public void paintArrow(Coordinate plotLoc, double adjSize, double mag, + double dir) { + paintPoint(plotLoc, adjSize); + + double staff = 0.0; + + double logFactor = this.scale; + + // linear scaling + if (logFactor == 0.00) { + staff = mag * size / maxLimit; + } else { + double pcentRange = mag / maxLimit; + double lg = Math.log(logFactor + pcentRange); + double pcentLog = (lg - minLog) / (maxLog - minLog); + staff = pcentLog * size; + } + + double barb = staff / 7.0; + + // if (staff < barb) { + // return; + // } + + double ratio = adjSize / size; + staff *= ratio; + barb *= ratio; + + // DIRECTIONS + double uudd = -mag * Math.sin(dir); + double vvff = -mag * Math.cos(dir); + double dix = uudd / mag; + double djy = vvff / mag; + double dix1 = -dix - djy; + double djy1 = dix - djy; + double dix2 = -dix + djy; + double djy2 = -dix - djy; + + // DRAW BODY OF ARROW + double ix2 = plotLoc.x; + double jy2 = plotLoc.y; + double ix1 = ix2 + dix * staff; + double jy1 = jy2 - djy * staff; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, { ix1, jy1 } }); + // DRAW HEAD OF ARROW. + ix2 = ix1 + dix1 * barb; + jy2 = jy1 - djy1 * barb; + double ix3 = ix1 + dix2 * barb; + double jy3 = jy1 - djy2 * barb; + lastShape.addLineSegment(new double[][] { { ix2, jy2 }, { ix1, jy1 }, + { ix3, jy3 } }); + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEVectorGraphicsRenderableFactory.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEVectorGraphicsRenderableFactory.java new file mode 100644 index 0000000000..9448e8d6c5 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEVectorGraphicsRenderableFactory.java @@ -0,0 +1,80 @@ +/** + * 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.gfe.rsc; + +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.drawables.IDescriptor; +import com.raytheon.viz.core.contours.util.IVectorGraphicsRenderableFactory; +import com.raytheon.viz.core.contours.util.VectorGraphicsRenderable; + +/** + * GFE VectorGraphicsRenderable Factory + * + * Constructs the VectorGraphicsRenderable for GFE usage of GriddedVectorDisplay + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 22, 2013     #2287  randerso     Initial creation
+ * 
+ * 
+ * + * @author randerso + * @version 1.0 + */ + +public class GFEVectorGraphicsRenderableFactory implements + IVectorGraphicsRenderableFactory { + private double logFactor; + + private double maxLimit; + + /** + * Constructor + * + * @param logFactor + * logFactor scaling value from parm_arrowScaling preference + * @param maxLimit + * max allowable value for parm + */ + public GFEVectorGraphicsRenderableFactory(double logFactor, double maxLimit) { + this.logFactor = logFactor; + this.maxLimit = maxLimit; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.viz.core.contours.util.IVectorGraphicsRenderableFactory# + * createRenderable(com.raytheon.uf.viz.core.drawables.IDescriptor, + * com.raytheon.uf.viz.core.IGraphicsTarget, double) + */ + @Override + public VectorGraphicsRenderable createRenderable(IDescriptor descriptor, + IGraphicsTarget target, double size) { + return new GFEVectorGraphicsRenderable(descriptor, target, size, + logFactor, maxLimit); + } + +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java index 22a6bafaec..9c47ca94f8 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/colorbar/GFEColorbarResource.java @@ -62,9 +62,11 @@ import com.raytheon.viz.gfe.actions.SetDiscretePickupAction; import com.raytheon.viz.gfe.actions.SetDiscreteWxPickupAction; import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.ISpatialDisplayManager; +import com.raytheon.viz.gfe.core.msgs.GridDataChangedMsg; import com.raytheon.viz.gfe.core.msgs.IDisplayModeChangedListener; import com.raytheon.viz.gfe.core.msgs.IDisplayedParmListChangedListener; import com.raytheon.viz.gfe.core.msgs.IPickupValueChangedListener; +import com.raytheon.viz.gfe.core.msgs.ISpatialEditorTimeChangedListener; import com.raytheon.viz.gfe.core.msgs.Message; import com.raytheon.viz.gfe.core.msgs.Message.IMessageClient; import com.raytheon.viz.gfe.core.msgs.ShowQuickViewDataMsg; @@ -100,6 +102,7 @@ import com.raytheon.viz.ui.input.InputAdapter; * Changes for non-blocking SetValueDialog. * 01/23/2013 #1524 randerso Fix error when clicking on discrete color bar when * no grid exists + * 08/27/2013 #2287 randerso Fixed fitToDataColorTable for Single Grids * * * @@ -110,7 +113,7 @@ public class GFEColorbarResource extends AbstractVizResource implements IContextMenuProvider, IPickupValueChangedListener, IDisplayModeChangedListener, IMessageClient, - IDisplayedParmListChangedListener { + IDisplayedParmListChangedListener, ISpatialEditorTimeChangedListener { public static final double HEIGHT = 25.0; @@ -317,6 +320,8 @@ public class GFEColorbarResource extends dManager.getParmManager().removeDisplayedParmListChangedListener(this); dManager.getSpatialDisplayManager().removeDisplayModeChangedListener( this); + dManager.getSpatialDisplayManager() + .removeSpatialEditorTimeChangedListener(this); IDisplayPaneContainer container = getResourceContainer(); if (container != null) { @@ -324,6 +329,7 @@ public class GFEColorbarResource extends } Message.unregisterInterest(this, ShowQuickViewDataMsg.class); + Message.unregisterInterest(this, GridDataChangedMsg.class); if (colorbarScaleFont != null) { colorbarScaleFont.dispose(); @@ -358,9 +364,12 @@ public class GFEColorbarResource extends @Override protected void initInternal(IGraphicsTarget target) throws VizException { dManager.getSpatialDisplayManager().addDisplayModeChangedListener(this); + dManager.getSpatialDisplayManager() + .addSpatialEditorTimeChangedListener(this); dManager.getParmManager().addDisplayedParmListChangedListener(this); Message.registerInterest(this, ShowQuickViewDataMsg.class); + Message.registerInterest(this, GridDataChangedMsg.class); colorbarScaleFont = GFEFonts.makeGFEIFont(target, "ColorBarScale_font", 1); @@ -680,6 +689,16 @@ public class GFEColorbarResource extends parm = gridId.getParm(); } updateColorbar(parm); + } else if (message instanceof GridDataChangedMsg) { + GridDataChangedMsg msg = (GridDataChangedMsg) message; + if (currentParm != null + && msg.getParmID().equals(currentParm.getParmID()) + && msg.getTimeRange().contains( + currentParm.getDataManager() + .getSpatialDisplayManager() + .getSpatialEditorTime())) { + checkFitToData(); + } } } @@ -689,6 +708,10 @@ public class GFEColorbarResource extends * continuous colorbar range. */ protected void checkFitToData() { + if (currentParm == null) { + return; + } + String parmName = currentParm.getParmID().getParmName(); String fitToDataPref = parmName + "_fitToDataColorTable"; if (GFEPreference.contains(fitToDataPref)) { @@ -836,4 +859,9 @@ public class GFEColorbarResource extends updateColorbar(normalParm); } } + + @Override + public void spatialEditorTimeChanged(Date date) { + checkFitToData(); + } } diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GriddedIconDisplay.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GriddedIconDisplay.java index fedefeda79..434e44643d 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GriddedIconDisplay.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/GriddedIconDisplay.java @@ -50,6 +50,8 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Apr 23, 2010 bsteffen Initial creation + * Aug 27, 2013 #2287 randerso Added densityFactor to allow application specific + * adjustment of density. * * * @@ -68,13 +70,17 @@ public class GriddedIconDisplay extends AbstractGriddedDisplay { private PointIconFactory iconFactory; /** + * @param values * @param descriptor * @param gridGeometryOfGrid * @param imageSize + * @param densityFactor + * adjustment factor to make density match A1 */ public GriddedIconDisplay(float[] values, IMapDescriptor descriptor, - GeneralGridGeometry gridGeometryOfGrid, int imageSize) { - super(descriptor, gridGeometryOfGrid, imageSize); + GeneralGridGeometry gridGeometryOfGrid, int imageSize, + double densityFactor) { + super(descriptor, gridGeometryOfGrid, imageSize, densityFactor); this.values = values; } @@ -126,6 +132,7 @@ public class GriddedIconDisplay extends AbstractGriddedDisplay { return (int) values[idx]; } + @Override public boolean setColor(RGB color) { if (super.setColor(color)) { iconFactory = null; @@ -166,8 +173,8 @@ public class GriddedIconDisplay extends AbstractGriddedDisplay { if (renderable.resource != empty) { PointImage image = new PointImage(renderable.resource, renderable.plotLocation); - image.setHeight((double) size * magnification); - image.setWidth((double) size * magnification); + image.setHeight(size * magnification); + image.setWidth(size * magnification); images.add(image); } } diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java index ff8574b9c8..f88268818a 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java @@ -87,6 +87,7 @@ import com.raytheon.viz.core.contours.rsc.displays.AbstractGriddedDisplay; import com.raytheon.viz.core.contours.rsc.displays.GriddedContourDisplay; import com.raytheon.viz.core.contours.rsc.displays.GriddedStreamlineDisplay; import com.raytheon.viz.core.contours.rsc.displays.GriddedVectorDisplay; +import com.raytheon.viz.core.contours.util.VectorGraphicsRenderableFactory; import com.raytheon.viz.core.drawables.ColorMapParameterFactory; import com.raytheon.viz.core.rsc.displays.GriddedImageDisplay2; import com.raytheon.viz.core.style.arrow.ArrowPreferences; @@ -111,6 +112,8 @@ import com.vividsolutions.jts.geom.Coordinate; * May 08, 2013 1980 bsteffen Set paint status in GridResources for * KML. * Jul 15, 2013 2107 bsteffen Fix sampling of grid vector arrows. + * Aug 27, 2013 2287 randerso Added new parameters required by GriddedVectorDisplay + * and GriddedIconDisplay * * * @@ -154,13 +157,14 @@ public abstract class AbstractGridResource protected AbstractGridResource(T resourceData, LoadProperties loadProperties) { super(resourceData, loadProperties); resourceData.addChangeListener(new IResourceDataChanged() { + @Override public void resourceChanged(ChangeType type, Object object) { if (type == ChangeType.DATA_UPDATE) { if (object instanceof PluginDataObject) { addDataObject((PluginDataObject) object); } else if (object instanceof PluginDataObject[]) { for (PluginDataObject pdo : (PluginDataObject[]) object) { - addDataObject((PluginDataObject) pdo); + addDataObject(pdo); } } else if (object instanceof Object[]) { for (Object obj : (Object[]) object) { @@ -489,9 +493,10 @@ public abstract class AbstractGridResource case ARROW: case DUALARROW: convertData(data); + VectorGraphicsRenderableFactory factory = new VectorGraphicsRenderableFactory(); GriddedVectorDisplay vectorDisplay = new GriddedVectorDisplay( data.getMagnitude(), data.getDirection(), descriptor, - gridGeometry, 64, displayType); + gridGeometry, 64, 0.75, true, displayType, factory); vectorDisplay.setColor(getCapability(ColorableCapability.class) .getColor()); vectorDisplay.setLineStyle(getCapability(OutlineCapability.class) @@ -504,14 +509,15 @@ public abstract class AbstractGridResource MagnificationCapability.class).getMagnification()); if (stylePreferences != null && stylePreferences instanceof ArrowPreferences) { - vectorDisplay.setScale(((ArrowPreferences) stylePreferences) + factory.setScale(((ArrowPreferences) stylePreferences) .getScale()); } renderable = vectorDisplay; break; case ICON: GriddedIconDisplay iconDisplay = new GriddedIconDisplay(data - .getScalarData().array(), descriptor, gridGeometry, 80); + .getScalarData().array(), descriptor, gridGeometry, 80, + 0.75); iconDisplay.setColor(getCapability(ColorableCapability.class) .getColor()); iconDisplay.setDensity(getCapability(DensityCapability.class) diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGridResource.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGridResource.java index 6cf9d87158..53b2979421 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGridResource.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/D2DGridResource.java @@ -79,6 +79,8 @@ import com.vividsolutions.jts.geom.Coordinate; * constructor to avoid duplicate data * requests. * Jul 15, 2013 2107 bsteffen Fix sampling of grid vector arrows. + * Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error + * in Maputil.rotation * * * @@ -174,7 +176,7 @@ public class D2DGridResource extends GridResource implements crs2ll.transform(dp, dp); Coordinate ll = new Coordinate(dp.x, dp.y); float rot = (float) MapUtil.rotation(ll, geom); - dir = (dir + rot + 180) % 360; + dir = (dir + rot) % 360; data.getScalarData().put(index, dir); } } diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java index 63b34bc948..361bd9b293 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java @@ -59,6 +59,8 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Mar 09, 2011 bsteffen Initial creation * Jul 17, 2013 2185 bsteffen Cache computed grid reprojections. + * Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error + * in Maputil.rotation * * * @@ -250,8 +252,8 @@ public class GeneralGridData { Coordinate ll = new Coordinate(dp.x, dp.y); double rot = MapUtil.rotation(ll, newGeom); double rot2 = MapUtil.rotation(ll, gridGeometry); - double cos = Math.cos(Math.toRadians(180 + rot - rot2)); - double sin = Math.sin(Math.toRadians(180 + rot - rot2)); + double cos = Math.cos(Math.toRadians(rot - rot2)); + double sin = Math.sin(Math.toRadians(rot - rot2)); double u = udata[index]; double v = vdata[index]; udata[index] = (float) (cos * u - sin * v); diff --git a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java index b989664b0b..20bae8b075 100644 --- a/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java +++ b/cave/com.raytheon.viz.mpe.ui/src/com/raytheon/viz/mpe/ui/dialogs/ChooseDataPeriodDialog.java @@ -381,6 +381,7 @@ public class ChooseDataPeriodDialog extends CaveJFACEDialog { final QcPrecipOptionsDialog dialog = new QcPrecipOptionsDialog( getParentShell().getShell()); display.asyncExec(new Runnable() { + @Override public void run() { dialog.open(); } @@ -407,6 +408,7 @@ public class ChooseDataPeriodDialog extends CaveJFACEDialog { final QcTempOptionsDialog dialog = new QcTempOptionsDialog( getParentShell().getShell()); display.asyncExec(new Runnable() { + @Override public void run() { dialog.open(); } @@ -433,6 +435,7 @@ public class ChooseDataPeriodDialog extends CaveJFACEDialog { final QcFreezeOptionsDialog dialog = new QcFreezeOptionsDialog( getParentShell().getShell()); display.asyncExec(new Runnable() { + @Override public void run() { dialog.open(); } @@ -559,7 +562,7 @@ public class ChooseDataPeriodDialog extends CaveJFACEDialog { j = area_names.length(); } aList.add(area_names.substring(i, j)); - i += j + 1; + i = j + 1; } } else { aList.add(0, area_names.trim()); diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/GetBasinData.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/GetBasinData.java index d3b41b1b97..b06d3d8ece 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/GetBasinData.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/GetBasinData.java @@ -55,6 +55,8 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Maps; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 4, 2009 snaples Initial creation + * Aug 12, 2013 16490 snaples Fixed mapping of hrap grid to basins + * in get_basin_data * * * @@ -75,7 +77,6 @@ public class GetBasinData { int ib, l, numpts, ip, x, y, ip2, ip3, ip4, i; int hrap_basin_flag = 1; double lat, lon; - int m; int mm; int num_points; File basin_f = new File(basin_file); @@ -150,20 +151,14 @@ public class GetBasinData { ib++; } - // mean_areal_precip_global[ib] = dc.new Maps(); - // mean_areal_precip_global[ib].hb5 = ""; maxib = ib; System.out.println("Size of map array is : " + maxib + " basins"); s.close(); in.close(); } catch (FileNotFoundException e) { - // TODO Auto-generated catch block. Please revise as - // appropriate. statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); return false; } catch (IOException e) { - // TODO Auto-generated catch block. Please revise as - // appropriate. statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); return false; } catch (NumberFormatException e) { @@ -192,7 +187,6 @@ public class GetBasinData { mean_areal_precip_global[ib].tmaps_done = new int[200]; mean_areal_precip_global[ib].zmaps_done = new int[200]; - // for (m = 0; m < 200; m++) { Arrays.fill(mean_areal_precip_global[ib].gz, -1); Arrays.fill(mean_areal_precip_global[ib].uz, -1); Arrays.fill(mean_areal_precip_global[ib].mz, -1); @@ -209,30 +203,31 @@ public class GetBasinData { Arrays.fill(mean_areal_precip_global[ib].tmaps_done, -1); Arrays.fill(mean_areal_precip_global[ib].zmaps_done, -1); - // } } if (hrap_basin_flag == 1) { try { - System.out.println("Reading basin data from file."); + System.out.println("Reading hrap basin data from file."); long basin_start = System.currentTimeMillis(); in = new BufferedReader(new FileReader(hrap_f)); - char eb[] = new char[100]; + Scanner s = new Scanner(in); + String eb = new String(); for (ib = 0; ib < maxib; ib++) { - in.read(eb, 0, 80); - int p = new String(eb).indexOf('\n'); + eb = in.readLine(); //(eb, 0, 80); + int p = eb.length(); //new String(eb).indexOf('\n'); if (p != -1) { p = 0; } - String t = new String(eb); - Scanner s = new Scanner(t); + eb = eb.trim(); + s = new Scanner(eb); + Pattern pc = Pattern.compile("\\s*[A-Z]+$"); numpts = s.nextInt(); mean_areal_precip_global[ib].hrap_points = numpts; String bchar = ""; - bchar = s.findInLine("*$"); - mean_areal_precip_global[ib].bchar = bchar; + bchar = s.findInLine(pc); + mean_areal_precip_global[ib].bchar = bchar.trim(); mean_areal_precip_global[ib].hrap_data = new Hrap_Data[numpts]; for (mm = 0; mm < 4; mm++) { @@ -240,42 +235,34 @@ public class GetBasinData { } for (l = 0; l < numpts; l++) { - + Hrap_Data d = dc.new Hrap_Data(); + mean_areal_precip_global[ib].hrap_data[l] = d; + for (mm = 0; mm < 4; mm++) { mean_areal_precip_global[ib].hrap_data[l].zone[mm] = -1; } - p = in.read(eb, 0, 100); + eb = in.readLine(); //(eb, 0, 100); + eb = eb.trim(); + p = eb.length(); if (p == 0) { break; } - t = new String(eb); - - // ier = sscanf (ibuf, "%d %d %d %d %d %d\n", &x, &y, - // &ip, &ip2, &ip3,&ip4); - + s = new Scanner(eb); x = s.nextInt(); y = s.nextInt(); if (s.hasNextInt()) { ip = s.nextInt(); - if (ip < 0 || ip > 4) { - System.out - .println("HRAP error in read_basin_data routine.\n"); - return false; - } - ip2 = s.nextInt(); - ip3 = s.nextInt(); - ip4 = s.nextInt(); - mean_areal_precip_global[ib].hrap_data[l].x = x; mean_areal_precip_global[ib].hrap_data[l].y = y; mean_areal_precip_global[ib].hrap_data[l].zone[ip - 1] = 1; mean_areal_precip_global[ib].zones[0] = 1; if (s.hasNextInt()) { + ip2 = s.nextInt(); if (ip2 < 0 || ip2 > 4) { System.out .println("HRAP error in read_basin_data routine.\n"); @@ -288,7 +275,7 @@ public class GetBasinData { } if (s.hasNextInt()) { - + ip3 = s.nextInt(); if (ip3 < 0 || ip3 > 4) { System.out .println("HRAP error in read_basin_data routine.\n"); @@ -301,7 +288,7 @@ public class GetBasinData { } if (s.hasNextInt()) { - + ip4 = s.nextInt(); if (ip4 < 0 || ip4 > 4) { System.out .println("HRAP error in read_basin_data routine.\n"); @@ -315,22 +302,18 @@ public class GetBasinData { } } - System.out - .println("Finished reading basin data from file, elapsed time: " - + (System.currentTimeMillis() - basin_start) - + " ms"); - s.close(); - in.close(); } + System.out + .println("Finished reading basin data from file, elapsed time: " + + (System.currentTimeMillis() - basin_start) + + " ms"); + s.close(); + in.close(); } catch (FileNotFoundException e) { - // TODO Auto-generated catch block. Please revise as - // appropriate. statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); return false; } catch (IOException e) { - // TODO Auto-generated catch block. Please revise as - // appropriate. statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); return false; diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcp.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcp.java index f1f73cdc6a..49bd21c60a 100644 --- a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcp.java +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcp.java @@ -47,697 +47,123 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station; public class RenderPcp { - private static boolean first = true; - - Pcp pcp = DailyQcUtils.pcp; - - /* - * QC codes - */ - private static final int MISSING = -1; - - private static final int STANDARD = 0; - - private static final int FAILED = 1; - - private static final int MANUAL = 2; - - private static final int QUESTIONABLE = 3; - - private static final int PARTIAL = 4; - - private static final int ESTIMATED = 5; - - private static final int TIMEDISTRIBUTED = 6; - - private static final int VERIFIED = 8; - - /** - * Converts point precipitation data in struct pdata to hrap grid. The 20 - * closest stations are precalculated for each grid point - this speeds - * computations for data sets with many precipitation points. If there are - * no good precipitation points for a grid point, then a recalculation is - * made using all precipitation points. 1/R**2 interpolation is used. If - * requested, the final interpolation is scaled using seasonal isohyets. The - * grid is saved as a disk file and used later for a raster or vector (HRAP) - * plot. - * - * @param m - * @param k - * @param mk - * @param numPstations - * @param precip_stations - * @param hrap_grid - * @param pdata - * @param pcp_in_use - */ - public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step, - int numPstations, ArrayList precip_stations, - Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) { - - int isom = DailyQcUtils.isom; - int method = DailyQcUtils.method; - int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors; - int i, j, h, hh, time_pos, htotal; - double distance, dist1, dist2, dist, value; - double temp; - int totals[] = new int[5]; - - for (i = 0; i < 5; i++) { - totals[i] = 0; - } - - /* - * pcpn_time_step is a function parameter. It specifies whether to - * interpolate 6hr or 24hr HRAP grid - */ - /* - * pcpn_time is a function parameter. It specifies which 6hr HRAP grid - * to generate. It takes 0,1,2,or 3 to represent different 6hr period of - * a day. - */ - /* - * time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for - * 24hr data). This value is used in - * pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to - * retrieve 6hr data or 24hr data. - */ - if (pcpn_time_step == 0) { - time_pos = pcpn_time; // for 6 hour data: 0,1,2,3. - } else { - time_pos = 4; // for 24 hour data - - /* - * in case the 24hr grid rendering is required, we check - * 24hr_grid_gen_method_token() to determine how to generate the - * grid. New Post OB9.2 - */ - - if (getTokenValue24hrGridGenMeth() == 1) { - render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations, - precip_stations, hrap_grid, pdata, pcp_in_use); - return; - } - } - - /* begin to interpolate value for each bin in the HRAP grid */ - /* - * to interpolate, two quantities are needed first: value and distance. - * They are calculated by using the neighboring stations. - */ - for (i = 0; i < hrap_grid.maxi; i++) { - for (j = 0; j < hrap_grid.maxj; j++) { - /* - * Check if the grid cell is covered by an HSA. If not, then do - * not estimate precipitation for it. - */ - if (hrap_grid.owner[i][j] == -1) { - pcp.value[i][j] = 0; - continue; - } - - value = 0.0; - distance = 0.0; - htotal = 0; - - /* - * the following for loop is to calculate two quantities: value - * and distance, which later on, are used to interpret the HRAP - * grid. - */ - /* - * It uses neighbor stations of a HRAP grid bin to calculate - * value and distance. - */ - /* for each neighbor station of the grid bin, do the following */ - - /* For each of the closest stations. */ - for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) { - hh = hrap_grid.gage[i][j].index[h]; - // hh is index of stations - if (pdata[pcpn_day].stn[hh].frain[time_pos].data < 0) { - /* No precip data. */ - continue; - } // frain refers to level 2 data; rrain refers to level 1 - - if (method == 2 && precip_stations.get(hh).isoh[isom] <= 0) { - continue; - } - - if (pdata[pcpn_day].stn[hh].frain[time_pos].qual != 0 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 8 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 6 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 3 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 4 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 2) { - /* The station has a bad qc flag. Do not use it. */ - continue; - } - - /* - * Convert the coordinates of the grid and station in - * lat/lon into distance. - */ - dist1 = (i + (hrap_grid.hrap_minx - precip_stations.get(hh).hrap_x)); - dist2 = (j + (hrap_grid.hrap_miny - precip_stations.get(hh).hrap_y)); - - dist = Math.pow(dist1, 2) + Math.pow(dist2, 2); - - if (dist < .00001) { - dist = .00001; - } - - dist = 1 / dist; - - temp = pdata[pcpn_day].stn[hh].frain[time_pos].data * dist; - - if (method == 2 && precip_stations.get(hh).isoh[isom] > 0) { - temp = temp * hrap_grid.isoh[isom][i][j] - / (precip_stations.get(hh).isoh[isom] * 25.4); - } - - value = value + temp; - - distance = distance + dist; - - htotal++; - - if (htotal == 10) { - break; - } - - } - /* - * end for loop (h = 0; h < mpe_dqc_max_precip_neighbors;h++) - * the above for loop is for each neighbor station. - */ - /* - * the above for loop is to calculate value and distance, which - * later on, are used to interpret the HRAP grid - */ - - /* - * the resulting htotal is the valid number of neighbor stations - * that are used to calculate value and distance, which later - * on, are used to interpret the HRAP grid - */ - - /* - * if there is not enough valid neighbor station, such as htotal - * <4, the code below handle this situation. Basically, the code - * recalculate the value and distance using all the stations -- - * see the for (h = 0; h < max_stations; h++) loop below. - */ - if (htotal < 4) { - - value = 0.0; - distance = 0.0; - htotal = 0; - - for (h = 0; h < numPstations; h++) { - if (pdata[pcpn_day].stn[h].frain[time_pos].data < 0) { - continue; - } - - if (pdata[pcpn_day].stn[h].frain[time_pos].qual != 0 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 8 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 6 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 3 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 4 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 2) { - continue; - } - - if (method == 2 - && precip_stations.get(h).isoh[isom] <= 0) { - continue; - } - - dist1 = (i + (hrap_grid.hrap_minx - precip_stations - .get(h).hrap_x)); - dist2 = (j + (hrap_grid.hrap_miny - precip_stations - .get(h).hrap_y)); - - dist = Math.pow(dist1, 2) + Math.pow(dist2, 2); - - /* - * if distance from grid box to station is > - * mpe_dqc_grid_max_distbins, - */ - /* then do not use station */ - if (dist < .00001) { - dist = .00001; - } - - else if (Math.sqrt(dist) > DailyQcUtils.mpe_dqc_grid_max_dist) { - continue; - } - dist = 1 / dist; - - temp = pdata[pcpn_day].stn[h].frain[time_pos].data - * dist; - - if (method == 2 - && precip_stations.get(h).isoh[isom] > 0) { - temp = temp - * hrap_grid.isoh[isom][i][j] - / (precip_stations.get(h).isoh[isom] * 25.4); - } - - value = value + temp; - - distance = distance + dist; - - htotal++; - - } - - }/* end the handling of special case : if (htotal < 4), */ - /* which means there is no enough neighboring stations */ - - if (htotal == 0) { - pcp.value[i][j] = 0; - } else { - pcp.value[i][j] = (int) (value / distance * 100.0); - } - // if (htotal != 0) { - // pcp.value[i][j] += (int) (value / distance * 100); - // } - if (pcp.value[i][j] < .01) { - pcp.value[i][j] = 0; - } - } - } // end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP - // grid. - - /* final adjustment of the pcp->value */ - // for (i = 0; i < hrap_grid.maxi; i++) { - // hrap_grid comes from the function parameter - // for (j = 0; j < hrap_grid.maxj; j++) { - // - // if (pcp.value[i][j] < .01) { - // pcp.value[i][j] = 0; - // } - // } - // } - - if (pcpn_time_step == 0) { - time_pos = pcpn_day * 4 + 3 - pcpn_time; - } else { - time_pos = 40 + pcpn_day; - } - // notice that time_pos is a variable defined inside the function, and - // its value do not need to be limited as 0,1,2,3,or 4. Here it is - // assigned with bigger numbers. - // time_pos = 40 + pcpn_day; - - // pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2 - // option - // = -1 --grids for this time period not rendered (initialization value) - pcp_in_use[time_pos] = 1; - - ReadQPFGrids rqp = new ReadQPFGrids(); - rqp.write_file("pcp", time_pos, pcp); - } - - /* - * get the token value of token mpe_24hr_grid_gen_method. This token will - * determine how we generate the 24hr grid. We can either use the 24hr gage - * values, which is the old way, or we can use four 6hr gage values and add - * them together. - */ - /* there is some problem with the static */ - - /** - * @param pcpn_day - * @param pcpn_time - * @param numPstations - * @param precip_stations - * @param hrap_grid - * @param pdata - * @param pcp_in_use - */ - private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time, - int numPstations, ArrayList precip_stations, - Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) { - - int i, j, k, h, hh, time_pos, htotal; - double distance, dist1, dist2, dist, value; - double temp; - int isom = DailyQcUtils.isom; - int method = DailyQcUtils.method; - int totals[] = new int[5]; - int all_total = 0; - int neighbor_total = 0; - - for (i = 0; i < 5; i++) { - totals[i] = 0; - } - - /* - * pcpn_time_step is function parameter. It specifies whether to - * interpolate 6hr or 24hr HRAP grid - */ - /* - * pcpn_time is a function parameter. It specifies which 6hr HRAP grid - * to generate. It takes 0,1,2,or 3 to represent different 6hr period of - * a day. - */ - /* - * time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for - * 24hr data). This value is used in - * pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to - * retrieve 6hr data or 24hr data. - */ - - /* initialization of the pcp->value */ - for (i = 0; i < hrap_grid.maxi; i++) { /* - * hrap_grid comes from the - * function parameter - */ - for (j = 0; j < hrap_grid.maxj; j++) { - pcp.value[i][j] = 0; - } - } - - /* - * begin to interpolate 4 6hr grids. At the end of each iteration, the - * calculated interpolation value is added to pcp->value[i][j]. - */ - /* - * time_pos is assigned a value of 0,1,2,or 3 (for four 6hr data). This - * value is used in pdata[pcpn_day].stn[hh].frain[time_pos].data to - * retrieve 6hr data. - */ - for (k = 0; k < 4; k++) { - time_pos = k; /* for 6 hour data: 0, 1,2,3. */ - - /* begin to interpolate value for each bin in the HRAP grid */ - /* - * to interpolate, two quantities are needed first: value and - * distance. They are calculated by using the neighboring stations. - */ - - for (i = 0; i < hrap_grid.maxi; i++) { /* - * hrap_grid comes from the - * function parameter - */ - for (j = 0; j < hrap_grid.maxj; j++) { - /* - * Check if the grid cell is covered by an HSA. If not, then - * do not estimate precipitation for it. - */ - if (hrap_grid.owner[i][j] == -1) { - pcp.value[i][j] = 0; - continue; - } - - value = 0.0; - distance = 0.0; - htotal = 0; - - /* - * the following for loop is to calculate two quantities: - * value and distance, which later on, are used to interpret - * the HRAP grid. - */ - /* - * It uses neighbor stations of a HRAP grid bin to calculate - * value and distance. - */ - /* - * for each neighbor station of the grid bin, do the - * following - */ - int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors; - - for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) { - hh = hrap_grid.gage[i][j].index[h];/* - * hh is index of - * stations - */ - - if (pdata[pcpn_day].stn[hh].frain[time_pos].data < 0) { - /* No precip data. */ - continue; - } /* - * frain refers to level 2 data; rain refers to level - * 1 - */ - - /* - * generate something for output later on if in debug - * mode - */ - // if (debug_level >= 1) { - // if (pdata[pcpn_day].stn[hh].frain[time_pos].qual - // == MISSING) - // { - // missing_total++; - // } - // - // if (pdata[pcpn_day].stn[hh].frain[time_pos].qual - // == ESTIMATED) - // { - // estimated_total++; - // } - // - // if (pdata[pcpn_day].stn[hh].frain[time_pos].qual - // == FAILED) - // { - // failed_total++; - // } - // - // if (method == 2 && station[hh].isoh[isom] <= 0) - // { - // climo_total++; - // } - // } /* end if (debug_level >= 1) */ - - if (DailyQcUtils.method == 2 - && precip_stations.get(hh).isoh[isom] <= 0) { - continue; - } - - if (pdata[pcpn_day].stn[hh].frain[time_pos].qual != 0 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 8 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 6 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 3 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 4 - && pdata[pcpn_day].stn[hh].frain[time_pos].qual != 2) { - /* The station has a bad qc flag. Do not use it. */ - continue; - } - - /* - * Convert the coordinates of the grid and station in - * lat/lon into distance. - */ - dist1 = (i + hrap_grid.hrap_minx - precip_stations - .get(hh).hrap_x); - dist2 = (j + hrap_grid.hrap_miny - precip_stations - .get(hh).hrap_y); - - dist = Math.pow(dist1, 2) + Math.pow(dist2, 2); - - if (dist < .00001) { - dist = .00001; - } - - dist = 1 / dist; - - temp = pdata[pcpn_day].stn[hh].frain[time_pos].data - * dist; - - if (method == 2 - && precip_stations.get(hh).isoh[isom] > 0) { - temp = temp - * hrap_grid.isoh[isom][i][j] - / (precip_stations.get(hh).isoh[isom] * 25.4); - } - - value = value + temp; - - distance = distance + dist; - - htotal++; - - if (htotal == 10) { - break; - } - - } - /* - * end for loop (h = 0; h < - * mpe_dqc_max_precip_neighbors;h++) - */ - /* the above for loop is for each neighbor station. */ - /* - * the above for loop is to calculate value and distance, - * which later on, are used to interpret the HRAP grid - */ - - /* - * the resulting htotal is the valid number of neighbor - * stations that are used to calculate value and distance, - * which later on, are used to interpret the HRAP grid - */ - - /* - * if there is not enough valid neighbor station, such as - * htotal <4, the code below handle this situation. - * Basically, the code recalculate the value and distance - * using all the stations -- see the for (h = 0; h < - * max_stations; h++) loop below. - */ - if (htotal < 4) { - - value = 0.0; - distance = 0.0; - htotal = 0; - - for (h = 0; h < numPstations; h++) { - if (pdata[pcpn_day].stn[h].frain[time_pos].data < 0) { - continue; - } - - if (pdata[pcpn_day].stn[h].frain[time_pos].qual != 0 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 8 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 6 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 3 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 4 - && pdata[pcpn_day].stn[h].frain[time_pos].qual != 2) { - continue; - } - - if (method == 2 - && precip_stations.get(h).isoh[isom] <= 0) { - continue; - } - - dist1 = (i + hrap_grid.hrap_minx - precip_stations - .get(h).hrap_x); - dist2 = (j + hrap_grid.hrap_miny - precip_stations - .get(h).hrap_y); - - dist = Math.pow(dist1, 2) + Math.pow(dist2, 2); - - if (dist < .00001) { - dist = .00001; - } - - dist = 1 / dist; - - temp = pdata[pcpn_day].stn[h].frain[time_pos].data - * dist; - - if (method == 2 - && precip_stations.get(h).isoh[isom] > 0) { - temp = temp - * hrap_grid.isoh[isom][i][j] - / (precip_stations.get(h).isoh[isom] * 25.4); - } - - value = value + temp; - - distance = distance + dist; - - htotal++; - - } - neighbor_total++; - } /* end the handling of special case : if (htotal < 4), */ - /* which means there is no enough neighboring stations */ - - /* - * add the interpreted value for the bin of the HRAP_grid - */ - /* - * if (htotal == 0) { pcp->value[i][j] += 0; } else { - * pcp->value[i][j] += (int) (value / distance * 100); } - */ - if (htotal != 0) { - pcp.value[i][j] += (int) (value / distance * 100); - } - - /* - * if (pcp->value[i][j] < .01) { pcp->value[i][j] = 0; } - */ - all_total++; - - } /* end of for loop (j = 0; j < hrap_grid->maxj; j++) */ - } /* end of for loop (i = 0; i < hrap_grid->maxi; i++) */ - /* At this moment, the interpretation of HRAP grid is done */ - - }/* - * end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP - * grid. - */ - - /* final adjustment of the pcp->value */ - for (i = 0; i < hrap_grid.maxi; i++) { /* - * hrap_grid comes from the - * function parameter - */ - for (j = 0; j < hrap_grid.maxj; j++) { - - if (pcp.value[i][j] < .01) { - pcp.value[i][j] = 0; - } - } - } - - /* time_pos = pcpn_day * 4 + 3 - pcpn_time; */ - time_pos = 40 + pcpn_day; - - /* - * pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2 - * option = -1 --grids for this time period not rendered (initialization - * value) - */ - pcp_in_use[time_pos] = 1; - - /* - * results of grid rendering routines (render_t, render_t6, render_pcp, - * render_z) are written to scratch files using the write_file routine. - * scratch file is stored in the scratch directory. - */ - ReadQPFGrids rqp = new ReadQPFGrids(); - rqp.write_file("pcp", time_pos, pcp); - - } - - int getTokenValue24hrGridGenMeth() { - - int token_of_24hr_grid_gen_method = 0; - - /* int token_of_24hr_grid_gen_method = 0; */ - - if (first == true) { - String token_name_of_24hr_grid_gen_method_token = "mpe_dqc_24hr_precip_grid_meth"; - - /* char strTokenValue[50] = { '\0' }; */ - String DQC24hrPrecipMeth; - - // char message[GAGEQC_MESSAGE_LEN] = { '\0' }; - - AppsDefaults appsDefaults = AppsDefaults.getInstance(); - DQC24hrPrecipMeth = appsDefaults - .getToken(token_name_of_24hr_grid_gen_method_token); - // sprintf(message, "\nSTATUS: token value of \"%s\" : %s\n", - // token_name_of_24hr_grid_gen_method_token, strTokenValue); - // logMessage(message); - - if (DQC24hrPrecipMeth != null && DQC24hrPrecipMeth.length() > 0) { - /* we use the token ACCUM_6HR and USE_24HR */ - if (DQC24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) { - token_of_24hr_grid_gen_method = 1; - } - } - - first = false; - } - - return token_of_24hr_grid_gen_method; - } -} + private static boolean first = true; + + Pcp pcp = DailyQcUtils.pcp; + + /* + * QC codes + */ + private static final int MISSING = -1; + + private static final int STANDARD = 0; + + private static final int SCREENED = 0; + + private static final int FAILED = 1; + + private static final int MANUAL = 2; + + private static final int QUESTIONABLE = 3; + + private static final int PARTIAL = 4; + + private static final int ESTIMATED = 5; + + private static final int TIMEDISTRIBUTED = 6; + + private static final int VERIFIED = 8; + + private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN = "mpe_dqc_grid_render_method"; + + private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist + * DailyQcUtils.mpe_dqc_grid_max_dist; + + /** + * Converts point precipitation data in struct pdata to hrap grid. The 20 + * closest stations are precalculated for each grid point - this speeds + * computations for data sets with many precipitation points. If there are + * no good precipitation points for a grid point, then a recalculation is + * made using all precipitation points. 1/R**2 interpolation is used. If + * requested, the final interpolation is scaled using seasonal isohyets. The + * grid is saved as a disk file and used later for a raster or vector (HRAP) + * plot. + * + * @param m + * @param k + * @param mk + * @param numPstations + * @param + * @param hrap_grid + * @param pdata + * @param pcp_in_use + */ + // mpe_dqc_grid_render_method + + // --------------------------------------------------------------------------------------- + + public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step, + int numPstations, ArrayList precip_stations, + Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) { + + String header = "RenderPcp.render_pcp(): "; + + AppsDefaults appsDefaults = AppsDefaults.getInstance(); + + String tokenValue = appsDefaults + .getToken(MPE_DQC_GRID_RENDERING_METHOD_TOKEN); + + // System.out.println(header + "tokenValue = " + tokenValue); + + // tokenValue = "BLOCKING"; + // tokenValue = "DISTANCE_SQUARED"; + + System.out.println(header + "now tokenValue = " + tokenValue); + + if (tokenValue != null && tokenValue.equalsIgnoreCase("BLOCKING")) { + RenderPcpBlocking renderer = new RenderPcpBlocking(); + + renderer.render_pcp(pcpn_day, pcpn_time, pcpn_time_step, + numPstations, precip_stations, hrap_grid, pdata, pcp_in_use); + } + + else { + RenderPcpStandard renderer = new RenderPcpStandard(); + + renderer.render_pcp(pcpn_day, pcpn_time, pcpn_time_step, + numPstations, precip_stations, hrap_grid, pdata, pcp_in_use); + + } + + determineMaxPrecip(hrap_grid); + + } + + private int determineMaxPrecip(Hrap_Grid hrap_grid) { + // TODO Auto-generated method stub + + String header = "RenderPcp.determineMaxPrecip(): "; + + int value = 0; + int maxValue = -1; + + for (int col = 0; col < hrap_grid.maxi; col++) { + for (int row = 0; row < hrap_grid.maxj; row++) { + value = pcp.value[row][col]; + + if (value > maxValue) { + maxValue = value; + } + + } + + } + + System.out.println(header + "maxValue = " + maxValue); + + return maxValue; + + } // end determineMaxPrecip() + + // --------------------------------------------------------------------------------------- +} // end class RenderPcp \ No newline at end of file diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpBlocking.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpBlocking.java new file mode 100644 index 0000000000..c45d46ace5 --- /dev/null +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpBlocking.java @@ -0,0 +1,957 @@ +/** + * 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.mpe.util; + +import java.util.ArrayList; + +import com.raytheon.uf.common.ohd.AppsDefaults; +import com.raytheon.viz.mpe.util.DailyQcUtils.Hrap_Grid; +import com.raytheon.viz.mpe.util.DailyQcUtils.Pcp; +import com.raytheon.viz.mpe.util.DailyQcUtils.Pdata; +import com.raytheon.viz.mpe.util.DailyQcUtils.Station; + +/** + * DESCRIPTION: Maps precipitation station values to an HRAP grid. Produces the + * DailyQC version of the GageOnly analysis. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 11, 2009            snaples     Initial creation
+ * May 02, 2011   8962     snaples     Added render24hrPcpUsingFour6hr() method
+ * 
+ * 
+ * + * @author snaples + * @version 1.0 + */ + +public class RenderPcpBlocking { + + private static boolean first = true; + + Pcp pcp = DailyQcUtils.pcp; + + /* + * QC codes + */ + private static final int MISSING = -1; + private static final int STANDARD = 0; + private static final int SCREENED = 0; + private static final int FAILED = 1; + private static final int MANUAL = 2; + private static final int QUESTIONABLE = 3; + private static final int PARTIAL = 4; + private static final int ESTIMATED = 5; + private static final int TIMEDISTRIBUTED = 6; + private static final int VERIFIED = 8; + + // private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN = + // "mpe_dqc_grid_render_method"; + + private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist + * DailyQcUtils.mpe_dqc_grid_max_dist; + + // private static final int maxDistSquared = 400; + + /** + * Converts point precipitation data in struct pdata to hrap grid. The 20 + * closest stations are precalculated for each grid point - this speeds + * computations for data sets with many precipitation points. If there are + * no good precipitation points for a grid point, then a recalculation is + * made using all precipitation points. 1/R**2 interpolation is used. If + * requested, the final interpolation is scaled using seasonal isohyets. The + * grid is saved as a disk file and used later for a raster or vector (HRAP) + * plot. + * + * @param m + * @param k + * @param mk + * @param numPstations + * @param + * @param hrap_grid + * @param pdata + * @param pcp_in_use + */ + // mpe_dqc_grid_render_method + + private boolean usingSingleDirectionCloseOutMode = true; + private static final int MIN_PREFERRED_USED_GRID_CELLS = 4; + private static final int MIN_REQUIRED_USED_GRID_CELLS = 1; + + private SearchDirection north = new SearchDirection(); + private SearchDirection south = new SearchDirection(); + private SearchDirection east = new SearchDirection(); + private SearchDirection west = new SearchDirection(); + + private int colMin; + private int colMax; + private int rowMin; + private int rowMax; + private int prevColMin; + private int prevColMax; + private int prevRowMin; + private int prevRowMax; + + // weighting variables + private int usedGridCellCount = 0; + private double totalWeightedValue = 0; + private double totalDistanceWeight = 0; + + // grid variables + private int binStationCount[][]; + + private int usableStationCount = 0; + + private double valueGrid[][]; + private double prismStationGrid[][]; + + private int isom = -1; + + class SearchDirection { + private boolean isOpen; + private int level; + + public SearchDirection() { + reset(); + } + + public void reset() { + setOpen(true); + setLevel(0); + } + + public boolean isOpen() { + return isOpen; + } + + public void setOpen(boolean isOpen) { + this.isOpen = isOpen; + } + + public void close() { + setOpen(false); + } + + void expandSearchIfAllowed() { + if (isOpen()) { + incrementLevel(); + + if (getLevel() > DailyQcUtils.mpe_dqc_grid_max_dist) { + setLevel(DailyQcUtils.mpe_dqc_grid_max_dist); + close(); + } + + } + } + + public void incrementLevel() { + this.level++; + } + + private void setLevel(int level) { + this.level = level; + } + + public int getLevel() { + return level; + } + + } // end inner class SearchDirection + + // --------------------------------------------------------------------------------------- + + // --------------------------------------------------------------------------------------- + int getTokenValue24hrGridGenMeth() { + + int token_of_24hr_grid_gen_method = 0; + + if (first == true) { + String tokenName = "mpe_dqc_24hr_precip_grid_meth"; + + String dqc24hrPrecipMeth; + + // char message[GAGEQC_MESSAGE_LEN] = { '\0' }; + + AppsDefaults appsDefaults = AppsDefaults.getInstance(); + dqc24hrPrecipMeth = appsDefaults.getToken(tokenName); + + if (dqc24hrPrecipMeth != null) { + /* allowed token values: (ACCUM_6HR, USE_24HR) */ + if (dqc24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) { + token_of_24hr_grid_gen_method = 1; + } + } + first = false; + } + + return token_of_24hr_grid_gen_method; + } + + // ---------------------------------------------------------------------------- + + // ---------------------------------------------------------------------------- + public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step, + int numPstations, ArrayList stationList, + Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) { + + isom = DailyQcUtils.isom; + + int time_pos; + + if (pcpn_time_step == 0) { + time_pos = pcpn_time; // for 6 hour data: 0,1,2,3. + + boolean save_grids = true; + boolean accumulate_grids = false; + + render_pcp_internal(pcpn_day, pcpn_time, pcpn_time_step, + numPstations, stationList, hrap_grid, pdata, pcp_in_use, + save_grids, accumulate_grids); + } else { + time_pos = 4; // for 24 hour data + + /* + * in case the 24hr grid rendering is required, we check + * 24hr_grid_gen_method_token() to determine how to generate the + * grid. New Post OB9.2 + */ + + // debug + // first = true; + + if (getTokenValue24hrGridGenMeth() == 1) { + render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations, + stationList, hrap_grid, pdata, pcp_in_use); + return; + } else // calculate 24-hour grids the regular way + { + + boolean save_grids = true; + boolean accumulate_grids = false; + + render_pcp_internal(pcpn_day, pcpn_time, pcpn_time_step, + numPstations, stationList, hrap_grid, pdata, + pcp_in_use, save_grids, accumulate_grids); + + } + } + + } + + private void render_pcp_internal(int pcpn_day, int pcpn_time, + int pcpn_time_step, int numPstations, + ArrayList stationList, Hrap_Grid hrap_grid, Pdata[] pdata, + int[] pcp_in_use, boolean save_grids, boolean should_accumulate) { + // String header = "RenderPcpBlocking.render_pcp_internal(): "; + + int isom = DailyQcUtils.isom; + + double resultingPrecipValue = 0.0; + + /*-----------------------------------------------------*/ + + allocateGrids(hrap_grid); + + initializeGrids(hrap_grid, should_accumulate); + + placeStationsInGrid(pcpn_day, pcpn_time, pcpn_time_step, numPstations, + stationList, hrap_grid, pdata); + + // for every grid location, determine its estimated value + for (int col = 0; col < hrap_grid.maxi; col++) { + for (int row = 0; row < hrap_grid.maxj; row++) { + + /* + * Check if the grid cell is covered by an HSA. If not, then do + * not estimate precipitation for it. + */ + if (hrap_grid.owner[col][row] == -1) { + pcp.value[row][col] = 0; + continue; + } + + if (binStationCount[col][row] > 0) // if any station is in this + // grid bin + { + resultingPrecipValue = valueGrid[col][row]; + + // adjust grid bin with actual gage by the prism factor + if (prismStationGrid[col][row] > 0) { + double prismStationValue = prismStationGrid[col][row] * 25.4; + double prismGridValue = hrap_grid.isoh[isom][col][row]; + + double prismFactor = (double) prismGridValue + / prismStationValue; + + resultingPrecipValue *= prismFactor; + } else { + resultingPrecipValue = 0.0; + } + + // pcp.value[row][col] is the value of grid, + // so we don't need to estimate a value for [row][col] + } + + else // this grid location requires an estimate to be generated + { + resultingPrecipValue = estimateValue(isom, col, row, + hrap_grid); + } + + if (resultingPrecipValue >= 0.0) { + int precipInHundredthsOfMm = (int) Math + .floor((resultingPrecipValue * 100.0)); + + if (should_accumulate) { // for case where we want to make + // 24 = 4 6hr periods added + // together + pcp.value[col][row] += precipInHundredthsOfMm; + } else { + pcp.value[col][row] = precipInHundredthsOfMm; + } + } + + } /* end for (col = 0 ... */ + + } /* end for (row = 0 ... */ + + // System.out.println(header + "maxPrecip in hundredths of mm = " + + // maxPrecip); + + int time_pos; + /* + * notice that time_pos is a variable defined inside the function, and + * its value do not need to be limited as 0,1,2,3,or 4. Here it is + * assigned with bigger numbers. + */ + if (pcpn_time_step == 0) // one of the 6-hr periods + { + time_pos = pcpn_day * 4 + 3 - pcpn_time; + } else // 24 hr + { + time_pos = 40 + pcpn_day; + } + + if (save_grids) { + /* + * pcp_in_use[i] = 1 -- grids rendered via Render button OR Save + * Level2 option = -1 --grids for this time period not rendered + * (initialization value) + */ + pcp_in_use[time_pos] = 1; + + /* + * results of grid rendering routines (render_t, render_t6, + * render_pcp, render_z) are written to scratch files using the + * write_file routine. scratch file is stored in the scratch + * directory. + */ + + ReadQPFGrids rqp = new ReadQPFGrids(); + rqp.write_file("pcp", time_pos, pcp); + } + + } // end render_pcp_internal() + + private double estimateValue(int isom, int col, int row, Hrap_Grid hrap_grid) { + + // String header = "RenderPcpBlocking.estimateValue(): "; + int r; + int c; + + double estimatedPrecipValue = 0.0; + + if (hrap_grid.isoh[isom][col][row] < 0.01) { + estimatedPrecipValue = 0; + return estimatedPrecipValue; // can't do anything more, quit + } + + // look through surrounding grid bins only for + // values to be used in the distance-weighted interpolation + + // set to open and level = 0 + north.reset(); + south.reset(); + east.reset(); + west.reset(); + + // initialize + totalWeightedValue = 0.0; + totalDistanceWeight = 0.0; + usedGridCellCount = 0; + + rowMax = row; + rowMin = row; + colMax = col; + colMin = col; + + prevRowMax = rowMax; + prevRowMin = rowMin; + prevColMax = colMax; + prevColMin = colMin; + + while (north.isOpen() || south.isOpen() || east.isOpen() + || west.isOpen()) { + // expand search levels as appropriate + // changes rowMin, rowMax, colMin, colMax + expandGridSearch(col, row, hrap_grid); + + if (rowMin < prevRowMin) // grew the top side + { + r = rowMin; + for (c = colMin; c <= colMax; c++) { + processGriddedStationValues(col, row, c, r, hrap_grid); + } + } else // didn't grow the top side + { + if (colMin < prevColMin) // still need to check top left corner + { + c = colMin; + r = rowMin; + processGriddedStationValues(col, row, c, r, hrap_grid); + } + + if (colMax > prevColMax) // still need to check top right corner + { + c = colMax; + r = rowMin; + processGriddedStationValues(col, row, c, r, hrap_grid); + } + + } + + if (rowMax > prevRowMax) // grew the bottom side + { + r = rowMax; + for (c = colMin; c <= colMax; c++) { + processGriddedStationValues(col, row, c, r, hrap_grid); + } + } else // didn't grow the bottom side + { + if (colMin < prevColMin) // still need to check bottom left + // corner + { + c = colMin; + r = rowMax; + processGriddedStationValues(col, row, c, r, hrap_grid); + } + if (colMax > prevColMax) // still need to check bottom right + // corner + { + c = colMax; + r = rowMax; + processGriddedStationValues(col, row, c, r, hrap_grid); + } + } + + if (colMin < prevColMin) // grew left side + { + c = colMin; + for (r = rowMin + 1; r < rowMax; r++) { + processGriddedStationValues(col, row, c, r, hrap_grid); + } + } + + if (colMax > prevColMax) // grew right side + { + c = colMax; + for (r = rowMin + 1; r < rowMax; r++) { + processGriddedStationValues(col, row, c, r, hrap_grid); + } + } + + if (usedGridCellCount >= MIN_PREFERRED_USED_GRID_CELLS) // have + // enough + // cells to + // look at, + // can quit + // now + { + north.close(); + south.close(); + east.close(); + west.close(); + + // System.out.println(header + + // "met minimum cell preference, resultingPrecipValue = " + + // resultingPrecipValue); + } + + } /* end while (northLevelOpen ... */ + + // set weighted value to the cell or set value to 0.0 if there is not + // enough data + if (usedGridCellCount >= MIN_REQUIRED_USED_GRID_CELLS) { + estimatedPrecipValue = totalWeightedValue / totalDistanceWeight; + + // System.out.println(header + + // "met minimum cell requirement, resultingPrecipValue = " + + // resultingPrecipValue); + } else // set to zero precip + { + estimatedPrecipValue = 0.0; + } + + return estimatedPrecipValue; + + } // end estimateValue() + + // *-------------------------------------------------------------------------- + + void processGriddedStationValues(int renderingCol, int renderingRow, + int gridCol, int gridRow, Hrap_Grid hrap_grid) { + + String header = "RenderPcpBlocking.processGriddedStationValues(): "; + + int usedCells = 0; + // sprintf(message, + // "renderingCol = %d, renderingRow = %d, gridCol = %d, gridRow = %d \n", + // renderingCol, renderingRow, gridCol, gridRow); + + // logMessage(message); + + if ((gridCol < 0) || (gridCol > hrap_grid.maxi) || (gridRow < 0) + || (gridRow > hrap_grid.maxj)) { + System.out.println(header + "OUT OF RANGE gridCol = " + gridCol + + " gridRow = " + gridRow); + } + + double gageValue = valueGrid[gridCol][gridRow]; + + if (gageValue >= 0.0) // there is a gage + // located at (gridCol,gridRow) + // with a valid precip value + { + + usedCells = adjustWeights(gageValue, gridRow, gridCol, + renderingRow, renderingCol, hrap_grid, isom, + prismStationGrid); + + usedGridCellCount += usedCells; + // if data was found, close off a direction, usually 2 directions, + // such as north and west + + if (usedCells > 0) { + determineDirectionFoundAndCloseOff(renderingCol, renderingRow, + gridCol, gridRow); + } + + } + + return; + } // end processGriddedStationValues() + + // *-------------------------------------------------------------------------- + + void expandGridSearch(int col, int row, Hrap_Grid hrap_grid) { + // expand search levels as appropriate + + north.expandSearchIfAllowed(); + south.expandSearchIfAllowed(); + east.expandSearchIfAllowed(); + west.expandSearchIfAllowed(); + + // save previous values of row and col min and max + prevRowMax = rowMax; + prevRowMin = rowMin; + prevColMax = colMax; + prevColMin = colMin; + + // determine nested for loop ranges + rowMax = row + north.getLevel(); + if (rowMax >= hrap_grid.maxj) { + rowMax = hrap_grid.maxj - 1; + north.close(); + } + + rowMin = row - south.getLevel(); // row + if (rowMin < 0) { + rowMin = 0; + south.close(); + } + + colMin = col - west.getLevel(); + if (colMin < 0) { + colMin = 0; + west.close(); + } + + colMax = col + east.getLevel(); + if (colMax >= hrap_grid.maxi) { + colMax = hrap_grid.maxi - 1; + east.close(); + } + + return; + } // end expandGridSearch() + + /*--------------------------------------------------------------------------*/ + + void determineDirectionFoundAndCloseOffSimpleVersion(int renderingCol, + int renderingRow, int stationCol, int stationRow) { + if (stationRow < renderingRow) { + south.close(); + } else if (stationRow > renderingRow) { + north.close(); + } + + if (stationCol < renderingCol) { + west.close(); + } else if (stationCol > renderingCol) { + east.close(); + } + + } + + /*--------------------------------------------------------------------------*/ + + void determineDirectionFoundAndCloseOff(int renderingCol, int renderingRow, + int stationCol, int stationRow) { + + final int closeEnoughToBeEqual = 2; + + // String header = + // "RenderPcpBlocking.determineDirectionFoundAndCloseOff(): "; + + // consider taking a diff and a point is considered in a straightline if + // its difference is < 3 from the grid bin to render + + int northSouthDifference = Math.abs(stationRow - renderingRow); + int eastWestDifference = Math.abs(stationCol - renderingCol); + + boolean isNorthOrSouth = false; + boolean isEastOrWest = false; + + if (northSouthDifference - eastWestDifference <= closeEnoughToBeEqual) { + isNorthOrSouth = true; + isEastOrWest = true; + } else if (northSouthDifference > eastWestDifference) { + isNorthOrSouth = true; + } else { + isEastOrWest = true; + } + + if (usingSingleDirectionCloseOutMode) { + // System.out.println(header + + // "Using usingSingleDirectionCloseOutMode difference-based close off."); + + if (isNorthOrSouth) { + // this point functions as the north-south representative, since + // it is primarily north or south + + if (stationRow < renderingRow) { + south.close(); + } else if (stationRow > renderingRow) { + north.close(); + } + } + + if (isEastOrWest) { + if (stationCol < renderingCol) { + west.close(); + } else if (stationCol > renderingCol) { + east.close(); + } + } + } + + else // in mode in which points represent 2 directions (unless directly + // North-south or east-west) + { + // System.out.println(header + + // "Using traditional difference cutoff."); + if (stationRow < renderingRow) { + south.close(); + } else if (stationRow > renderingRow) { + north.close(); + } + + if (stationCol < renderingCol) { + west.close(); + } else if (stationCol > renderingCol) { + east.close(); + } + + } + + return; + } // determineDirectionFoundAndCloseOff() + + /*--------------------------------------------------------------------------*/ + void allocateGrids(Hrap_Grid hrap_grid) { + + int maxI = hrap_grid.maxi; + int maxJ = hrap_grid.maxj; + + binStationCount = new int[maxI][maxJ]; + + valueGrid = new double[maxI][maxJ]; + + prismStationGrid = new double[maxI][maxJ]; + + return; + } + + /*--------------------------------------------------------------------------*/ + + void initializeGrids(Hrap_Grid hrap_grid, boolean should_accumulate) { + int i = 0; + int j = 0; + + /* initialize grids */ + for (i = 0; i < hrap_grid.maxi; i++) { + for (j = 0; j < hrap_grid.maxj; j++) { + binStationCount[i][j] = 0; + valueGrid[i][j] = DailyQcUtils.MOSAIC_DEFAULT; // precip in + // inches + prismStationGrid[i][j] = DailyQcUtils.MOSAIC_DEFAULT; // prism + // station + // value + // mapped + // to + // grid + // (this + // algorithm + // only) + + if (!should_accumulate) { + // in special 24hr = sum of 4 6hr periods mode, + // we accumulate in this grid, so we don't reinit every time + + pcp.value[i][j] = (int) DailyQcUtils.MOSAIC_DEFAULT; // final + // precip + // in + // hundredths + // of + // mm + } + } + } + } + + /*--------------------------------------------------------------------------*/ + + void placeStationsInGrid(int pcpn_day, int pcpn_time, int pcpn_time_step, + int max_stations, ArrayList stationList, + Hrap_Grid hrap_grid, Pdata pdata[]) { + + int method = DailyQcUtils.method; + String header = "RenderPcpBlocking.placeStationsInGrid(): "; + + int time_pos; + + if (pcpn_time_step == 0) { + time_pos = pcpn_time; // for 6 hour data: 0,1,2,3. + } else { + time_pos = 4; // for 24 hour data + } + + int hx, hy; + int h = 0; + + int noPrismCount = 0; + + // System.out.println("max_stations = " + max_stations); + + int maxPrecip = 0; + + for (h = 0; h < max_stations; h++) { + Station station = stationList.get(h); + + hx = (int) (station.hrap_x - hrap_grid.hrap_minx); + hy = (int) (station.hrap_y - hrap_grid.hrap_miny); + + /* check that station is within the site's area */ + if (hx >= hrap_grid.maxi || hy >= hrap_grid.maxj || (hx < 0) + || (hy < 0)) { + // This station cannot be used, because its coordinates are out + // of range + continue; + } + + // debug only + + int stationCount = binStationCount[hx][hy]; + + double precipValue = pdata[pcpn_day].stn[h].frain[time_pos].data; + + short qualCode = pdata[pcpn_day].stn[h].frain[time_pos].qual; + + // skip if not an acceptable quality code + if (qualCode != SCREENED && qualCode != VERIFIED + && qualCode != TIMEDISTRIBUTED && qualCode != QUESTIONABLE + && qualCode != PARTIAL && qualCode != MANUAL) { + continue; + } + + if ((method == 2) && (station.isoh[isom] <= 0)) // no prism data for + // the station + { + noPrismCount++; + continue; + } + + /* if station value is missing, ignore */ + if (precipValue >= 0.0) { + + int precipIn_h_mm = (int) Math.floor(precipValue * 100.0); + + if (precipIn_h_mm > maxPrecip) { + maxPrecip = precipIn_h_mm; + } + + // we have data and no other station has been assigned to this + // bin yet + if (binStationCount[hx][hy] == 0) { + binStationCount[hx][hy] = 1; + valueGrid[hx][hy] = precipValue; + prismStationGrid[hx][hy] = station.isoh[isom]; + + usableStationCount++; + } + + else if (stationCount > 0) // we have at least 1 value for this + // grid location + { + + double valueGridTotalValue = (valueGrid[hx][hy] * stationCount) + + precipValue; + double prismGridTotalValue = (prismStationGrid[hx][hy] * stationCount) + + station.isoh[isom]; + binStationCount[hx][hy]++; + stationCount++; + + double newGridAvgValue = valueGridTotalValue / stationCount; + double newPrismAvgValue = prismGridTotalValue + / stationCount; + + valueGrid[hx][hy] = newGridAvgValue; + prismStationGrid[hx][hy] = newPrismAvgValue; + + usableStationCount++; + + } // end else + } // end if + + } // end for (h = 0; h < max_stations; h++) + + System.out.println(header + " maxPrecip in hundredths of mm = " + + maxPrecip); + + // System.out.println(header + + // " number of stations missing PRISM data = " + noPrismCount); + // System.out.println(header + " usableStationCount = " + + // usableStationCount); + } + + // --------------------------------------------------------------------------------------- + /* + * get the token value of token mpe_24hr_grid_gen_method. This token will + * determine how we generate the 24hr grid. We can either use the 24hr gage + * values, which is the old way, or we can use four 6hr gage values and add + * them together. + */ + /* there is some problem with the static */ + + private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time, + int numPstations, ArrayList stationList, + Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) { + + /* initialization of the pcp.value */ + for (int i = 0; i < hrap_grid.maxi; i++) { + for (int j = 0; j < hrap_grid.maxj; j++) { + pcp.value[i][j] = 0; + } + } + + boolean save_grids = false; + boolean should_accumulate = true; + + for (int k = 0; k < 4; k++) { + int pcpn_time_internal = k; + + int pcpn_time_step = 0; // means it is one of the 6-hr periods + + render_pcp_internal(pcpn_day, pcpn_time_internal, pcpn_time_step, + numPstations, stationList, hrap_grid, pdata, pcp_in_use, + save_grids, should_accumulate); + + } + + } // end render24hrPcpUsingFour6hr() + + // -------------------------------------------------------------------------- + int adjustWeights(double originalValue, int otherRow, int otherColumn, + int renderingRow, int renderingColumn, Hrap_Grid hrap_grid, + int monthIndex, double[][] prismStationGrid) { + + String header = "RenderPcpBlocking.adjustWeights(): "; + + final double MIN_DISTANCE = 0.00001; + int usedCount = 0; + + double distanceWeight = 0.0; + double weightedValue = 0.0; + + int rowDiff = otherRow - renderingRow; + int colDiff = otherColumn - renderingColumn; + double distanceSquared = (rowDiff * rowDiff) + (colDiff * colDiff); + + // int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist * + // DailyQcUtils.mpe_dqc_grid_max_dist; + + if (distanceSquared < MIN_DISTANCE) { + distanceSquared = MIN_DISTANCE; + } + + /* + * mpe_dqc_grid_max_dist = max distance of influence of a gage in units + * of grid bins + */ + + if (distanceSquared <= maxDistSquared) { + distanceWeight = 1.0 / distanceSquared; + weightedValue = originalValue * distanceWeight; + + // adjust by PRISM factor + if (prismStationGrid[renderingColumn][renderingRow] > 0) { + double prismFactor = (double) hrap_grid.isoh[monthIndex][renderingColumn][renderingRow] + / (prismStationGrid[renderingColumn][renderingRow] * 25.4); + weightedValue *= prismFactor; + + System.out.println(header + " prismFactor > 0 " + prismFactor); + + } + + totalWeightedValue += weightedValue; + totalDistanceWeight += distanceWeight; + + usedCount++; + } + + return usedCount; + } + + // --------------------------------------------------------------------------------------- + +} diff --git a/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpStandard.java b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpStandard.java new file mode 100644 index 0000000000..daa6bb5c59 --- /dev/null +++ b/cave/com.raytheon.viz.mpe/src/com/raytheon/viz/mpe/util/RenderPcpStandard.java @@ -0,0 +1,603 @@ +/** + * 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.mpe.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.raytheon.uf.common.ohd.AppsDefaults; +import com.raytheon.viz.mpe.util.DailyQcUtils.Hrap_Grid; +import com.raytheon.viz.mpe.util.DailyQcUtils.Pcp; +import com.raytheon.viz.mpe.util.DailyQcUtils.Pdata; +import com.raytheon.viz.mpe.util.DailyQcUtils.Station; + +/** + * DESCRIPTION: Maps precipitation station values to an HRAP grid. Produces the + * DailyQC version of the GageOnly analysis. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 11, 2009            snaples     Initial creation
+ * May 02, 2011   8962     snaples     Added render24hrPcpUsingFour6hr() method
+ * 
+ * 
+ * + * @author snaples + * @version 1.0 + */ + +public class RenderPcpStandard { + + private static final int MINIMUM_NEAREST_NEIGHBOR_GAGES = 4; + + private static final int SUFFICIENT_NEAREST_NEIGHBOR_GAGES = 10; + + private static boolean first = true; + + Pcp pcp = DailyQcUtils.pcp; + + /* + * QC codes + */ + private static final int MISSING = -1; + + private static final int STANDARD = 0; + + private static final int SCREENED = 0; + + private static final int FAILED = 1; + + private static final int MANUAL = 2; + + private static final int QUESTIONABLE = 3; + + private static final int PARTIAL = 4; + + private static final int ESTIMATED = 5; + + private static final int TIMEDISTRIBUTED = 6; + + private static final int VERIFIED = 8; + + private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN = "mpe_dqc_grid_render_method"; + + private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist + * DailyQcUtils.mpe_dqc_grid_max_dist; + + private static final double BOGUS_ESTIMATED_GRID_VALUE = -1.0; + + // weighting variables + + // consider making these members of a local variable of an inner class + private double totalWeightedValue = 0; + private double totalDistanceWeight = 0; + + /** + * Converts point precipitation data in struct pdata to hrap grid. The 20 + * closest stations are precalculated for each grid point - this speeds + * computations for data sets with many precipitation points. If there are + * no good precipitation points for a grid point, then a recalculation is + * made using all precipitation points. 1/R**2 interpolation is used. If + * requested, the final interpolation is scaled using seasonal isohyets. The + * grid is saved as a disk file and used later for a raster or vector (HRAP) + * plot. + * + * @param m + * @param k + * @param mk + * @param numPstations + * @param + * @param hrap_grid + * @param pdata + * @param pcp_in_use + */ + + // --------------------------------------------------------------------------------------- + + public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step, + int numPstations, ArrayList precip_stations, + Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) { + + // String header = "RenderPcpStandard.render_pcp_original(): "; + + int isom = DailyQcUtils.isom; + int method = DailyQcUtils.method; + int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors; + int i, j, h, hh, time_pos; + + int usedStationCount = 0; + int totals[] = new int[5]; + + for (i = 0; i < 5; i++) { + totals[i] = 0; + } + + /* + * pcpn_time_step is a function parameter. It specifies whether to + * interpolate 6hr or 24hr HRAP grid + */ + /* + * pcpn_time is a function parameter. It specifies which 6hr HRAP grid + * to generate. It takes 0,1,2,or 3 to represent different 6hr period of + * a day. + */ + /* + * time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for + * 24hr data). This value is used in + * pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to + * retrieve 6hr data or 24hr data. + */ + if (pcpn_time_step == 0) { + time_pos = pcpn_time; // for 6 hour data: 0,1,2,3. + } else { + time_pos = 4; // for 24 hour data + + /* + * in case the 24hr grid rendering is required, we check + * 24hr_grid_gen_method_token() to determine how to generate the + * grid. New Post OB9.2 + */ + + if (getTokenValue24hrGridGenMeth() == 1) { + render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations, + precip_stations, hrap_grid, pdata, pcp_in_use); + return; + } + } + + /* begin to interpolate value for each bin in the HRAP grid */ + /* + * to interpolate, two quantities are needed first: value and distance. + * They are calculated by using the neighboring stations. + */ + for (i = 0; i < hrap_grid.maxi; i++) { + for (j = 0; j < hrap_grid.maxj; j++) { + /* + * Check if the grid cell is covered by an HSA. If not, then do + * not estimate precipitation for it. + */ + if (hrap_grid.owner[i][j] == -1) { + pcp.value[i][j] = 0; + continue; + } + + totalDistanceWeight = 0.0; + totalWeightedValue = 0.0; + usedStationCount = 0; + boolean usedStation = false; + /* + * the following for loop is to calculate two quantities: value + * and distance, which later on, are used to interpret the HRAP + * grid. + */ + /* + * It uses neighbor stations of a HRAP grid bin to calculate + * value and distance. + */ + /* for each neighbor station of the grid bin, do the following */ + + /* For each of the closest stations. */ + for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) { + + // hh is index of stations + + hh = hrap_grid.gage[i][j].index[h]; + + int gageIndex = hh; + + usedStation = processStation(gageIndex, isom, i, j, + pcpn_day, pcpn_time, time_pos, method, + precip_stations, hrap_grid, pdata, pcp_in_use, + false); + + if (usedStation) { + usedStationCount++; + } + + if (usedStationCount == SUFFICIENT_NEAREST_NEIGHBOR_GAGES) { + break; + } + + } + + /* + * end for loop (h = 0; h < mpe_dqc_max_precip_neighbors;h++) + * the above for loop is for each neighbor station. + */ + /* + * the above for loop is to calculate value and distance, which + * later on, are used to interpret the HRAP grid + */ + + /* + * the resulting htotal is the valid number of neighbor stations + * that are used to calculate value and distance, which later + * on, are used to interpret the HRAP grid + */ + + /* + * if there is not enough valid neighbor station, such as + * usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES the code + * below handle this situation. Basically, the code recalculate + * the value and distance using all the stations -- see the for + * (h = 0; h < max_stations; h++) loop below. + */ + + if (usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES) { + + totalWeightedValue = 0.0; + totalDistanceWeight = 0.0; + usedStationCount = 0; + + for (h = 0; h < numPstations; h++) { + + int gageIndex = h; + + usedStation = processStation(gageIndex, isom, i, j, + pcpn_day, pcpn_time, time_pos, method, + precip_stations, hrap_grid, pdata, pcp_in_use, + true); + + if (usedStation) { + usedStationCount++; + } + + } + + }/* + * end the handling of special case : if (usedStationCount < + * MINIMUM_NEAREST_NEIGHBOR_GAGES), + */ + /* which means there are not enough neighboring stations */ + + // found no usable gages + if (usedStationCount == 0) { + pcp.value[i][j] = 0; + } + + else { + + pcp.value[i][j] = (int) (totalWeightedValue + / totalDistanceWeight * 100.0); + } + + if (pcp.value[i][j] < .01) { + pcp.value[i][j] = 0; + } + + } // end for (j = 0; j < hrap_grid.maxj; j++) { + } // end for (i = 0; i < hrap_grid.maxi; i++) { + + if (pcpn_time_step == 0) { + time_pos = pcpn_day * 4 + 3 - pcpn_time; + } else { + time_pos = 40 + pcpn_day; + } + // notice that time_pos is a variable defined inside the function, and + // its value do not need to be limited as 0,1,2,3,or 4. Here it is + // assigned with bigger numbers. + // time_pos = 40 + pcpn_day; + + // pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2 + // option + // = -1 --grids for this time period not rendered (initialization value) + pcp_in_use[time_pos] = 1; + + ReadQPFGrids rqp = new ReadQPFGrids(); + rqp.write_file("pcp", time_pos, pcp); + } + + private boolean processStation(int gageIndex, int isom, int col, int row, + int pcpn_day, int pcpn_time, int time_pos, int method, + ArrayList stationList, Hrap_Grid hrap_grid, Pdata[] pdata, + int[] pcp_in_use, boolean checkDistance) { + boolean usedStation = false; + + Station station = stationList.get(gageIndex); + + float value = pdata[pcpn_day].stn[gageIndex].frain[time_pos].data; + + if (value < 0) { + return usedStation;// false + } + + int qualityCode = pdata[pcpn_day].stn[gageIndex].frain[time_pos].qual; + + if (qualityCode != 0 && qualityCode != 8 && qualityCode != 6 + && qualityCode != 3 && qualityCode != 4 && qualityCode != 2) { + return usedStation; // false + } + + if (method == 2 && station.isoh[isom] <= 0) { + return usedStation; // false + } + + /* + * determine distance between grid bin and the station in question of + * the grid and station in question + */ + double distanceX = (col + (hrap_grid.hrap_minx - station.hrap_x)); + double distanceY = (row + (hrap_grid.hrap_miny - station.hrap_y)); + + double distanceSquared = (distanceX * distanceX) + + (distanceY * distanceY); + + if (distanceSquared < .00001) { + distanceSquared = .00001; + } + + if (checkDistance) { + if (distanceSquared > maxDistSquared) // too far away, don't use the + // station + { + return usedStation; // false, bail out, don't adjust weight with + // this reading + } + } + + double distanceWeight = 1 / distanceSquared; + double weightedValue = value * distanceWeight; + + float prismValue = station.isoh[isom]; + + if (method == 2 && prismValue > 0) { + weightedValue = weightedValue * hrap_grid.isoh[isom][col][row] + / (prismValue * 25.4); + } + + totalWeightedValue += weightedValue; + totalDistanceWeight += distanceWeight; + + usedStation = true; + return usedStation; + + } + + // --------------------------------------------------------------------------------------- + /* + * get the token value of token mpe_24hr_grid_gen_method. This token will + * determine how we generate the 24hr grid. We can either use the 24hr gage + * values, which is the old way, or we can use four 6hr gage values and add + * them together. + */ + /* there is some problem with the static */ + + /** + * @param pcpn_day + * @param pcpn_time + * @param numPstations + * @param precip_stations + * @param hrap_grid + * @param pdata + * @param pcp_in_use + */ + private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time, + int numPstations, ArrayList precip_stations, + Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) { + + int i, j, k, h, hh, time_pos; + boolean usedStation = false; + int isom = DailyQcUtils.isom; + int method = DailyQcUtils.method; + int totals[] = new int[5]; + int all_total = 0; + int neighbor_total = 0; + + int usedStationCount; + + for (i = 0; i < 5; i++) { + totals[i] = 0; + } + + /* + * pcpn_time_step is function parameter. It specifies whether to + * interpolate 6hr or 24hr HRAP grid + */ + /* + * pcpn_time is a function parameter. It specifies which 6hr HRAP grid + * to generate. It takes 0,1,2,or 3 to represent different 6hr period of + * a day. + */ + /* + * time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for + * 24hr data). This value is used in + * pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to + * retrieve 6hr data or 24hr data. + */ + + /* initialization of the pcp.value */ + for (i = 0; i < hrap_grid.maxi; i++) { + for (j = 0; j < hrap_grid.maxj; j++) { + pcp.value[i][j] = 0; + } + } + + /* + * begin to interpolate 4 6hr grids. At the end of each iteration, the + * calculated interpolation value is added to pcp.value[i][j]. + */ + /* + * time_pos is assigned a value of 0,1,2,or 3 (for four 6hr data). This + * value is used in pdata[pcpn_day].stn[hh].frain[time_pos].data to + * retrieve 6hr data. + */ + for (k = 0; k < 4; k++) { + time_pos = k; /* for 6 hour data: 0, 1,2,3. */ + + /* begin to interpolate value for each bin in the HRAP grid */ + /* + * to interpolate, two quantities are needed first: value and + * distance. They are calculated by using the neighboring stations. + */ + + for (i = 0; i < hrap_grid.maxi; i++) { + for (j = 0; j < hrap_grid.maxj; j++) { + /* + * Check if the grid cell is covered by an HSA. If not, then + * do not estimate precipitation for it. + */ + if (hrap_grid.owner[i][j] == -1) { + pcp.value[i][j] = 0; + continue; + } + + totalDistanceWeight = 0.0; + totalWeightedValue = 0.0; + usedStationCount = 0; + + /* + * for each neighbor station of the grid bin, do the + * following + */ + int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors; + + for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) { + hh = hrap_grid.gage[i][j].index[h];/* + * hh is index of + * stations + */ + int gageIndex = hh; + + usedStation = processStation(gageIndex, isom, i, j, + pcpn_day, pcpn_time, time_pos, method, + precip_stations, hrap_grid, pdata, pcp_in_use, + false); + + if (usedStation) { + usedStationCount++; + } + + if (usedStationCount == SUFFICIENT_NEAREST_NEIGHBOR_GAGES) { + break; + } + + } + + if (usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES) { + + // not enough gages, so extend search to all gages + totalWeightedValue = 0.0; + totalDistanceWeight = 0.0; + usedStationCount = 0; + + for (h = 0; h < numPstations; h++) { + + int gageIndex = h; + + usedStation = processStation(gageIndex, isom, i, j, + pcpn_day, pcpn_time, time_pos, method, + precip_stations, hrap_grid, pdata, + pcp_in_use, false); + + if (usedStation) { + usedStationCount++; + } + + } + neighbor_total++; + } + + if (usedStationCount != 0) { + pcp.value[i][j] += (int) ((totalWeightedValue / totalDistanceWeight) * 100); + } + + /* + * if (pcp.value[i][j] < .01) { pcp.value[i][j] = 0; } + */ + all_total++; + + } /* end of for loop (j = 0; j < hrap_grid.maxj; j++) */ + } /* end of for loop (i = 0; i < hrap_grid.maxi; i++) */ + /* At this moment, the interpretation of HRAP grid is done */ + + }/* + * end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP + * grid. + */ + + /* final adjustment of the pcp.value */ + for (i = 0; i < hrap_grid.maxi; i++) { + for (j = 0; j < hrap_grid.maxj; j++) { + + if (pcp.value[i][j] < .01) { // this doesn't really make sense, + // since this is an integer + pcp.value[i][j] = 0; + } + } + } + + /* time_pos = pcpn_day * 4 + 3 - pcpn_time; */ + time_pos = 40 + pcpn_day; + + /* + * pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2 + * option = -1 --grids for this time period not rendered (initialization + * value) + */ + pcp_in_use[time_pos] = 1; + + /* + * results of grid rendering routines (render_t, render_t6, render_pcp, + * render_z) are written to scratch files using the write_file routine. + * scratch file is stored in the scratch directory. + */ + ReadQPFGrids rqp = new ReadQPFGrids(); + rqp.write_file("pcp", time_pos, pcp); + + } // end render24hrPcpUsingFour6hr() + + // --------------------------------------------------------------------------------------- + int getTokenValue24hrGridGenMeth() { + + int token_of_24hr_grid_gen_method = 0; + + if (first == true) { + String tokenName = "mpe_dqc_24hr_precip_grid_meth"; + + String dqc24hrPrecipMeth; + + // char message[GAGEQC_MESSAGE_LEN] = { '\0' }; + + AppsDefaults appsDefaults = AppsDefaults.getInstance(); + dqc24hrPrecipMeth = appsDefaults.getToken(tokenName); + + if (dqc24hrPrecipMeth != null) { + /* allowed token values: (ACCUM_6HR, USE_24HR) */ + if (dqc24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) { + token_of_24hr_grid_gen_method = 1; + } + } + first = false; + } + + return token_of_24hr_grid_gen_method; + } + + // ----------------------------------------------------------------------------------- + +} diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/command/ProductQueryJob.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/command/ProductQueryJob.java index 97c99ad177..d3e08acae2 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/command/ProductQueryJob.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/command/ProductQueryJob.java @@ -20,8 +20,9 @@ package com.raytheon.viz.texteditor.command; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -46,6 +47,7 @@ import com.raytheon.viz.texteditor.util.TextEditorUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jan 18, 2013 rferrel Initial creation + * Aug 23, 2013 DR 16514 D. Friedman Fix accum/cancel logic. * * * @@ -59,82 +61,53 @@ public class ProductQueryJob extends Job { private final IProductQueryCallback callback; - /** - * flag to indicate request accumulate. - */ - private boolean accumulate; - /** * List queries to perform. */ private final List requests; + /** + * Set of queries main thread is waiting for. + */ + private final Set expected; + /** * Transport to use for the queries. */ private final IQueryTransport queryTransport; - /** - * Flag to indicate cancel is being performed. - */ - private final AtomicBoolean canceled; - public ProductQueryJob(IProductQueryCallback callback) { super("Product Query"); setSystem(true); this.callback = callback; - accumulate = false; requests = new ArrayList(); + expected = new HashSet(); queryTransport = TextEditorUtil.getTextDbsrvTransport(); - canceled = new AtomicBoolean(false); } /** - * Add request to queue and determine what needs to be done to schedule the - * request. + * Add request to queue. If not an incremental update, cancel + * existing requests. * * @param command * @param isObsUpdated - */ - public synchronized void addRequest(ICommand command, boolean isObsUpdated) { - Request request = new Request(command, isObsUpdated); - if (accumulate) { - requests.add(request); - if (getState() == Job.NONE) { - schedule(); - } - } else { - requests.clear(); - requests.add(request); - if (getState() == Job.NONE) { - schedule(); - } else { - cancel(); - } - } - } - - public boolean isAccumulate() { - return accumulate; - } - - /** - * When set to true requests will accumulate and be processed in the order - * received; otherwise the queue is purged and any current request is - * canceled if a new request is received. - * * @param accumulate */ - public void setAccumulate(boolean accumulate) { - if (this.accumulate != accumulate) { - synchronized (this) { - requests.clear(); - if (getState() != Job.NONE) { - cancel(); - } - this.accumulate = accumulate; - } + public synchronized void addRequest(ICommand command, boolean isObsUpdated, + boolean accumulate) { + Request request = new Request(command, isObsUpdated); + if (! accumulate && ! isObsUpdated) { + // Cancel existing requests. + expected.clear(); + requests.clear(); } + requests.add(request); + expected.add(request); + schedule(); + } + + public boolean isExpectingRequests() { + return ! expected.isEmpty(); } /* @@ -149,65 +122,44 @@ public class ProductQueryJob extends Job { return Status.OK_STATUS; } - Request request = null; - try { - while (true) { - synchronized (this) { - if (requests.size() > 0) { - request = requests.remove(0); - } else { - break; - } + while (true) { + final Request request; + synchronized (this) { + if (requests.size() > 0) { + request = requests.remove(0); + } else { + break; } + } + List prodList = null; + try { try { - final ICommand command = request.getCommand(); - final boolean isObsUpdated = request.isObsUpdated(); - final List prodList = command - .executeCommand(queryTransport); - // User may have canceled during long query. - if (!canceled.get()) { - VizApp.runAsync(new Runnable() { - - @Override - public void run() { - callback.requestDone(command, prodList, - isObsUpdated); - } - }); - } else { - break; - } + prodList = request.getCommand(). + executeCommand(queryTransport); } catch (CommandFailedException e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); - if (!canceled.get()) { - VizApp.runAsync(new Runnable() { - - @Override - public void run() { - callback.requestDone(null, null, false); - } - }); - } } + } finally { + final List resultProdList = prodList; + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + if (expected.remove(request) && resultProdList != null) { + callback.requestDone(request.getCommand(), resultProdList, + request.isObsUpdated()); + } else { + callback.requestDone(null, null, false); + } + } + }); } - } finally { - canceled.set(false); } return Status.OK_STATUS; } - /* - * (non-Javadoc) - * - * @see org.eclipse.core.runtime.jobs.Job#canceling() - */ - @Override - protected void canceling() { - canceled.set(true); - } - /* * Class to hold the query command and isObsUpdated flag needed for the * query and its callback. diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java index c0f981d6e1..279929692d 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java @@ -329,6 +329,8 @@ import com.raytheon.viz.ui.dialogs.SWTMessageBox; * set the highlight colors. * 23Jul2013 2176 jsanchez Added a new confirmation message for emergency warnings. * 25July2013 15733 GHull Read font and color prefs from TextEditorCfg. + * 23Aug2013 DR 16514 D. Friedman Fix handling of completed product requests. Do not change + * command history or close browser window for "update obs". * * * @@ -1101,11 +1103,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, */ private boolean overwriteMode = false; - /** - * flag to indicate it a product request is from the GUI or an updated ob. - */ - private final AtomicInteger updateCount = new AtomicInteger(0); - /** * The expire notification when editing a warn gen product. */ @@ -3105,12 +3102,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, accumChkBtn = new Button(topBtnRowComp, SWT.CHECK); accumChkBtn.setText("Accum"); accumChkBtn.setLayoutData(rd); - accumChkBtn.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - productQueryJob.setAccumulate(accumChkBtn.getSelection()); - } - }); // Add the Update Observation check button. rd = new RowData(BUTTON_WIDTH, BUTTON_HEIGHT); @@ -3994,6 +3985,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // return textColorsCfg; // } + private void setDefaultTextColor(TextEditorCfg txtClrCfg) { textBackground = new Color(shell.getDisplay(), txtClrCfg.getTextBackgroundColor()); @@ -5930,12 +5922,15 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, return; } - if (browser != null) { - browser.close(); - browser = null; + if (! isObsUpdated) { + if (browser != null) { + browser.close(); + browser = null; + } + + commandHistory.addCommand(command); } - commandHistory.addCommand(command); statusBarLabel.setText("Loading " + TextEditorUtil.getCommandText(command)); statusBarLabel.update(); @@ -5944,7 +5939,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, if (queryTransport == null) { queryTransport = TextEditorUtil.getTextDbsrvTransport(); } - productQueryJob.addRequest(command, isObsUpdated); + productQueryJob.addRequest(command, isObsUpdated, + accumChkBtn.getSelection()); } /** @@ -6025,7 +6021,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, stripWMOHeaders(prod); } - if (updateCount.get() > 0) { + if (isObsUpdated) { updateDisplayedProduct(prod); } else { setDisplayedProduct(prod); @@ -6120,13 +6116,15 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, private void postExecute(boolean hasAttachment, boolean enterEditor, boolean validExecuteCommand, String attachedFilename) { if (!this.isDisposed()) { - if (hasAttachment) { - statusBarLabel.setText("Attachment: " + attachedFilename); - } else { - statusBarLabel.setText(""); + if (! productQueryJob.isExpectingRequests()) { + if (hasAttachment) { + statusBarLabel.setText("Attachment: " + attachedFilename); + } else { + statusBarLabel.setText(""); + } + statusBarLabel.update(); + setBusy(false); } - statusBarLabel.update(); - setBusy(false); // Automatically open the editor window with returned data. if (enterEditor) { enterEditor(); @@ -6505,7 +6503,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, @Override public void setAccumulation(boolean flag) { this.accumChkBtn.setSelection(flag); - productQueryJob.setAccumulate(flag); } /* @@ -6992,7 +6989,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, // retrieved for display in this text editor dialog // instance. TextDisplayModel.getInstance().setStdTextProduct(token, product); - updateCount.addAndGet(-1); } /* @@ -7343,7 +7339,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener, msgPIL = ""; } if (isObsDisplayed(msgPIL)) { - updateCount.addAndGet(1); ICommand command = CommandFactory.getAfosCommand(msgPIL); UpdateObsRun run = new UpdateObsRun(command); VizApp.runSync(run); diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/AffectedAreas.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/AffectedAreas.java index 34feef9d55..aab49a0848 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/AffectedAreas.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/AffectedAreas.java @@ -32,6 +32,7 @@ import java.util.List; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Dec 11, 2007 #601 chammack Initial Creation. + * Aug 19, 2013 2177 jsanchez Removed suppress attribute. * * * @@ -49,11 +50,6 @@ public class AffectedAreas { */ protected List partOfArea; - /** - * The partOfArea to suppress (e.g. "ns") - */ - protected String suppress; - /** The notation of the area affected (e.g. "COUNTY") */ protected String areaNotation; @@ -89,17 +85,15 @@ public class AffectedAreas { public String getName() { return name; } - /** - * @param name - * the name to set + * @param name + * the name to set */ public void setName(String name) { this.name = name; } - /** * @return the areaNotation */ diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java index 7c7b4e5d7b..90e1542724 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java @@ -46,7 +46,6 @@ import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.warngen.gui.WarngenLayer; -import com.raytheon.viz.warngen.suppress.SuppressMap; import com.raytheon.viz.warngen.util.Abbreviation; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.prep.PreparedGeometry; @@ -74,6 +73,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometry; * Nov 9, 2012 DR 15430 D. Friedman Extracted method converFeAreaToPartList. * Apr 29, 2013 1955 jsanchez Ignored comparing the geometry's user data when finding intersected areas. * May 2, 2013 1963 jsanchez Updated method to determine partOfArea. + * Aug 19, 2013 2177 jsanchez Used portionsUtil to calculate area portion descriptions. * * * @author chammack @@ -89,13 +89,15 @@ public class Area { */ public static final double DEFAULT_PORTION_TOLERANCE = 0.60; - private Area() { + private PortionsUtil portionsUtil; + public Area(PortionsUtil portionsUtil) { + this.portionsUtil = portionsUtil; } - public static AffectedAreas[] findAffectedAreas( - WarngenConfiguration config, Geometry polygon, - Geometry warningArea, String localizedSite) throws VizException { + public AffectedAreas[] findAffectedAreas(WarngenConfiguration config, + Geometry polygon, Geometry warningArea, String localizedSite) + throws VizException { // --- Begin argument checking --- Validate.notNull(config.getGeospatialConfig().getAreaSource(), @@ -113,7 +115,7 @@ public class Area { localizedSite, geoms); } - private static AffectedAreas[] findAffectedAreas( + private AffectedAreas[] findAffectedAreas( AreaSourceConfiguration areaConfig, GeospatialConfiguration geospatialConfig, Geometry polygon, String localizedSite, List geoms) throws VizException { @@ -183,7 +185,6 @@ public class Area { area.stateabbr = regionFeature.attributes.get(areaNotationField) .toString(); area.size = regionGeom.getArea(); - area.suppress = suppressType(areaSource, area.stateabbr, area.fips); Object tzData = regionFeature.attributes.get(timezonePathcastField); @@ -219,9 +220,16 @@ public class Area { double tolerCheck = regionGeom.getArea() * DEFAULT_PORTION_TOLERANCE; if (areaIntersection < tolerCheck) { - area.partOfArea = GisUtil - .asStringList(GisUtil.calculatePortion(regionGeom, - intersection, true, true)); + try { + String entityID = area.stateabbr + areaSource.charAt(0) + + area.fips.substring(2); + area.partOfArea = GisUtil.asStringList(portionsUtil + .getPortions(entityID, regionGeom, intersection, + true)); + } catch (Exception e) { + statusHandler.error("Unable to calculate part of area for " + + area.name, e); + } } // Search the parent region @@ -277,10 +285,9 @@ public class Area { * @return * @throws VizException */ - public static Map findInsectingAreas( - WarngenConfiguration config, Geometry warnPolygon, - Geometry warnArea, String localizedSite, WarngenLayer warngenLayer) - throws VizException { + public Map findInsectingAreas(WarngenConfiguration config, + Geometry warnPolygon, Geometry warnArea, String localizedSite, + WarngenLayer warngenLayer) throws VizException { Map areasMap = new HashMap(); String hatchedAreaSource = config.getHatchedAreaSource() @@ -311,18 +318,6 @@ public class Area { } - private static String suppressType(String areaSource, String state, - String fips) { - String retVal = SuppressMap.NONE; - String type = areaSource.equalsIgnoreCase("zone") ? "Z" : "C"; - - if (state != null && fips != null) { - String key = state + type + fips.substring(2); - retVal = SuppressMap.getInstance().getType(key); - } - return retVal; - } - public static List converFeAreaToPartList(String feArea) { final List partList = new ArrayList(); if (feArea == null) { diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/CoverageConstants.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/CoverageConstants.java new file mode 100644 index 0000000000..f4bdae56b1 --- /dev/null +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/CoverageConstants.java @@ -0,0 +1,178 @@ +/** + * 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.warngen.gis; + +/** + * Port of A1 constants applied to a grid to determine county or zone portions. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 5, 2013  2177       jsanchez     Initial creation
+ * 
+ * 
+ * + * @author jsanchez + * @version 1.0 + */ + +public class CoverageConstants { + + public static final int XSOUTH = 0x0001; + + public static final int SOUTH = 0x0002; + + public static final int NORTH = 0x0040; + + public static final int XNORTH = 0x0080; + + public static final int CENTER_NS = 0x0018; + + public static final int CENTRAL_NS = 0x0024; + + public static final int XWEST = 0x0100; + + public static final int WEST = 0x0200; + + public static final int EAST = 0x4000; + + public static final int XEAST = 0x8000; + + public static final int CENTER_EW = 0x1800; + + public static final int CENTRAL_EW = 0x2400; + + public static final int SOUTHERN = 0x0003; + + public static final int NORTHERN = 0x00C0; + + public static final int WESTERN = 0x0300; + + public static final int EASTERN = 0xC000; + + public static final int SOUTHSIDE = 0x000F; + + public static final int NORTHSIDE = 0x00F0; + + public static final int WESTSIDE = 0x0F00; + + public static final int EASTSIDE = 0xF000; + + public static final int EXTREME = 0x8181; + + public static final int NOT_EXTREME = 0x7E7E; + + public static final int EXTREME_NS = 0x0081; + + public static final int EXTREME_EW = 0x8100; + + public static final int CENTRAL = 0x2424; + + public static final int CENTER = 0x1818; + + public static final int NOT_CENTRAL = 0xC3C3; + + public static final int NORTH_SOUTH = 0x00FF; + + public static final int EAST_WEST = 0xFF00; + + public static final int NNE = 0x0001; + + public static final int ENE = 0x0002; + + public static final int ESE = 0x0004; + + public static final int SSE = 0x0008; + + public static final int SSW = 0x0010; + + public static final int WSW = 0x0020; + + public static final int WNW = 0x0040; + + public static final int NNW = 0x0080; + + public static final int EXTREME_YES = 0xFFFF00; + + public static final int EXTREME_NO = 0x00FF; + + public static final int EXTREME_CORNER = 0xFF0000; + + public static int[] NS_MASK = new int[256]; + + public static int[] EW_MASK = new int[256]; + + static { + int i; + + NS_MASK[0] = 0; + for (i = 1; i < 256; i++) { + if (i < 87) { + NS_MASK[i] = XSOUTH | SOUTH; + } else if (i > 167) { + NS_MASK[i] = XNORTH | NORTH; + } else if (i < 106) { + NS_MASK[i] = SOUTH; + } else if (i > 148) { + NS_MASK[i] = NORTH; + } else if (i < 118) { + NS_MASK[i] = CENTRAL_NS | SOUTH; + } else if (i > 138) { + NS_MASK[i] = CENTRAL_NS | NORTH; + } else if (i < 127) { + NS_MASK[i] = CENTER_NS | CENTRAL_NS | SOUTH; + } else if (i > 127) { + NS_MASK[i] = CENTER_NS | CENTRAL_NS | NORTH; + } else { + NS_MASK[i] = CENTER_NS | CENTRAL_NS; + } + } + + EW_MASK[0] = 0; + for (i = 1; i < 256; i++) { + if (i < 87) { + EW_MASK[i] = XWEST | WEST; + } else if (i > 167) { + EW_MASK[i] = XEAST | EAST; + } else if (i < 106) { + EW_MASK[i] = WEST; + } else if (i > 145) { + EW_MASK[i] = EAST; + } else if (i < 118) { + EW_MASK[i] = CENTRAL_EW | WEST; + } else if (i > 138) { + EW_MASK[i] = CENTRAL_EW | EAST; + } else if (i < 127) { + EW_MASK[i] = CENTER_EW | CENTRAL_EW | WEST; + } else if (i > 127) { + EW_MASK[i] = CENTER_EW | CENTRAL_EW | EAST; + } else { + EW_MASK[i] = CENTER_EW | CENTRAL_EW; + } + } + } + + private CoverageConstants() { + + } +} diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/EntityData.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/EntityData.java new file mode 100644 index 0000000000..44d2311829 --- /dev/null +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/EntityData.java @@ -0,0 +1,65 @@ +/** + * 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.warngen.gis; + +/** + * Simple port of an A1 struct created by GridUtil and used by PortionsUtil. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 5, 2013  2177      jsanchez     Initial creation
+ * 
+ * 
+ * + * @author jsanchez + * @version 1.0 + */ + +public class EntityData { + + private int meanMask = 0; + + private int coverageMask = 0; + + private int octants = 0; + + public EntityData(int meanMask, int coverageMask, int octants) { + this.meanMask = meanMask; + this.coverageMask = coverageMask; + this.octants = octants; + } + + public int getMeanMask() { + return meanMask; + } + + public int getCoverageMask() { + return coverageMask; + } + + public int getOctants() { + return octants; + } + +} diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GridUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GridUtil.java new file mode 100644 index 0000000000..061ac1b73d --- /dev/null +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/GridUtil.java @@ -0,0 +1,616 @@ +/** + * 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.warngen.gis; + +import java.util.ArrayList; +import java.util.List; + +import org.geotools.coverage.grid.GeneralGridGeometry; +import org.geotools.coverage.grid.GridGeometry2D; +import org.geotools.referencing.operation.DefaultMathTransformFactory; +import org.opengis.coverage.grid.GridEnvelope; +import org.opengis.metadata.spatial.PixelOrientation; +import org.opengis.referencing.operation.MathTransform; + +import com.raytheon.uf.common.dataplugin.warning.util.GeometryUtil; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.viz.warngen.gui.WarngenLayer; +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.CoordinateSequence; +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.geom.prep.PreparedGeometry; +import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; + +/** + * Converts the county or zone and the intersecting warning area to grids. The + * county or zone is also weighted to determine the northern, southern, eastern, + * and western parts of the county or zone. Most of the code is ported from A1 + * to create an EntityData object that will be used by PortionsUtil to determine + * the applicable impacted portions of a county or zone. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 5, 2013            jsanchez     Initial creation
+ * 
+ * 
+ * + * @author jsanchez + * @version 1.0 + */ + +public class GridUtil { + + private int ny = 0; + + private int nx = 0; + + private int[] ewGrid; + + private int[] nsGrid; + + private byte[] warnedAreaGrid; + + private byte[] countyOrZoneGrid; + + private WarngenLayer layer; + + private MathTransform latLonToContour, contourToLatLon; + + public GridUtil(WarngenLayer layer, GeneralGridGeometry localGridGeometry, + MathTransform localToLatLon) throws Exception { + this.layer = layer; + + GridEnvelope range = localGridGeometry.getGridRange(); + this.nx = range.getHigh(0); + this.ny = range.getHigh(1); + + org.opengis.geometry.Envelope ge = localGridGeometry.getEnvelope(); + contourToLatLon = new DefaultMathTransformFactory() + .createConcatenatedTransform(new GridGeometry2D(range, ge) + .getGridToCRS(PixelOrientation.CENTER), localToLatLon); + latLonToContour = contourToLatLon.inverse(); + + ewGrid = new int[nx * ny]; + nsGrid = new int[nx * ny]; + } + + /** + * Converts the countyOrZone geometry and the warnedArea into grids and sets + * the appropriate data in an EntityData object. + * + * @param countyOrZone + * @param warnedArea + * @return + * @throws Exception + */ + public EntityData calculateGrids(Geometry countyOrZone, Geometry warnedArea) + throws Exception { + countyOrZoneGrid = toByteArray(countyOrZone); + warnedAreaGrid = toByteArray(warnedArea); + int[] bounds = awips1FinishAreaEntity(); + EntityData entityData = finishDefineArea(bounds); + return entityData; + } + + /** + * Converts the geometry into a byte array that is expected by ported A1 + * code. + * + * @param geometry + * @return + * @throws VizException + */ + private byte[] toByteArray(Geometry geometry) throws VizException { + byte[] bytes = new byte[nx * ny]; + float[][] floatData = toFloatData(geometry); + + // Rotates grid + int k = 0; + for (int j = ny - 1; j >= 0; j--) { + for (int i = 0; i < nx; i++) { + if (floatData[i][j] == 1) { + bytes[k] = 1; + } + k++; + } + } + + return bytes; + } + + /** + * Converts the geometry into a 2-D float array. + * + * @param geometry + * @return + * @throws VizException + */ + private float[][] toFloatData(Geometry geometry) throws VizException { + Geometry contoured = layer.convertGeom(geometry, latLonToContour); + List geomList = new ArrayList( + contoured.getNumGeometries()); + GeometryUtil.buildGeometryList(geomList, contoured); + List prepped = new ArrayList( + geomList.size()); + for (Geometry g : geomList) { + prepped.add(PreparedGeometryFactory.prepare(g)); + } + + GeometryFactory gf = geometry.getFactory(); + Point point = gf.createPoint(new Coordinate(0, 0)); + CoordinateSequence pointCS = point.getCoordinateSequence(); + float[][] contourAreaData = new float[nx][ny]; + for (PreparedGeometry geom : prepped) { + Envelope env = geom.getGeometry().getEnvelopeInternal(); + int startX = (int) env.getMinX(); + int startY = (int) env.getMinY(); + int width = (int) env.getMaxX(); + int height = (int) env.getMaxY(); + if (startX < 0 || width > nx || startY < 0 || height > ny) { + continue; + } + startX = Math.max(0, startX - 1); + startY = Math.max(0, startY - 1); + width = Math.min(nx, width + 1); + height = Math.min(ny, height + 1); + for (int x = startX; x < width; ++x) { + for (int y = startY; y < height; ++y) { + + pointCS.setOrdinate(0, 0, x); + pointCS.setOrdinate(0, 1, y); + point.geometryChanged(); + if (contourAreaData[x][y] == 0.0f && geom.intersects(point)) { + contourAreaData[x][y] = 1.0f; + } + } + } + + } + + return contourAreaData; + } + + /** + * Ported only the logic from A1 code + * GeoEntityLookupTable::finishDefineArea() that calculates the meanMask, + * coverageMask,and octants for an entity (i.e. county or zone). + * + * @param countyOrZone + * @param warnedArea + * @return + */ + private EntityData finishDefineArea(int[] bounds) { + int meanMask = 0; + int coverageMask = 0; + int octants = 0; + + int ewCount = 0; + int nsCount = 0; + int ewTotal = 0; + int nsTotal = 0; + + int k = 0; + int min_i = bounds[0]; + int max_i = bounds[1]; + int min_j = bounds[2]; + int max_j = bounds[3]; + for (int j = min_j; j < max_j; j++) { + k = nx * j + min_i; + for (int i = min_i; i < max_i; i++, k++) { + if (warnedAreaGrid[k] == 1) { + int e = countyOrZoneGrid[k]; + + int ii = ewGrid[k]; + int jj = nsGrid[k]; + + if (ii == 0 && jj == 0) { + continue; + } + ewTotal += ii; + if (ii > 0) { + ewCount++; + } + nsTotal += jj; + if (jj > 0) { + nsCount++; + } + int m = CoverageConstants.EW_MASK[ii] + | CoverageConstants.NS_MASK[jj]; + coverageMask |= m; + if ((m & CoverageConstants.CENTRAL) == CoverageConstants.CENTRAL) { + continue; + } + if (ii == 0) { + ii = 127; + } + if (jj == 0) { + jj = 127; + } + if (ii < 127) { + if (jj < 127) { + e = (ii > jj ? CoverageConstants.SSW + : CoverageConstants.WSW); + } else { + e = (ii > 254 - jj ? CoverageConstants.NNW + : CoverageConstants.WNW); + } + } else { + if (jj < 127) { + e = (ii < 254 - jj ? CoverageConstants.SSE + : CoverageConstants.ESE); + } else { + e = (ii < jj ? CoverageConstants.NNE + : CoverageConstants.ENE); + } + } + if ((m & CoverageConstants.EXTREME_NS) > 0) { + e <<= 8; + } + if ((m & CoverageConstants.EXTREME_EW) > 0) { + e <<= 8; + } + octants |= e; + } else { + warnedAreaGrid[k] = 0; + } + + } + } + + if (ewCount > 0) { + ewTotal = (ewTotal + ewCount / 2) / ewCount; + } + if (nsCount > 0) { + nsTotal = (nsTotal + nsCount / 2) / nsCount; + } + + meanMask = CoverageConstants.NS_MASK[nsTotal] + | CoverageConstants.EW_MASK[ewTotal]; + return new EntityData(meanMask, coverageMask, octants); + } + + /** + * Calculates the _ewGrid and _nsGrid via A1 ~~ mAgIc ~~ + */ + private int[] awips1FinishAreaEntity() { + + final double EXTREME_FRAC = 0.1; + final double MIN_EXTREME = 87; + final double MAX_EXTREME = 167; + + int k = 0; + int ii, jj; + + /* + * identify those points on the boundary of the entity so we can shrink + * from there + */ + int i_mean = 0; + int j_mean = 0; + int new_tot = 0; + int ii_mean = 0; + int jj_mean = 0; + int min_i = Integer.MAX_VALUE; + int min_j = Integer.MAX_VALUE; + int max_i = Integer.MIN_VALUE; + int max_j = Integer.MIN_VALUE; + + for (jj = 0; jj < ny; jj++) { + k = nx * jj; + for (ii = 0; ii < nx; ii++, k++) { + // If the entity is not 1 then it's not part of the county or + // zone area. + if (countyOrZoneGrid[k] != 1) { + continue; + } + + if (ii > max_i) { + max_i = ii; + } + + if (ii < min_i) { + min_i = ii; + } + + if (jj > max_j) { + max_j = jj; + } + if (jj < min_j) { + min_j = jj; + } + ++new_tot; + ii_mean += ii; + jj_mean += jj; + + } + + } + + /* + * restablish some things that might have changed since the first time + * they were calculated. + */ + // if (!outside) { + ii_mean /= new_tot; + jj_mean /= new_tot; + i_mean = ii_mean; + j_mean = jj_mean; + // }/*endif*/ + + /* assign correct base for directional computation */ + // I changed this from ii_mean to this + double i_base = (min_i + max_i) / 2; + // I changed this from jj_mean to this + double j_base = (min_j + max_j) / 2; + + /* + * calculate needed rotation factors for computation of amount each + * point is north and east of centroid + */ + double x_intcpg = 0.5; + double y_intcpg = 0.5; + + double dx = 1, dy = 1; + double x = (i_base - x_intcpg); + double y = (j_base - y_intcpg); + + // Below is some code from the original A1 code. I assumed that x_intcpg + // to be 0.5 to avoid porting all the methods in gelt_maker.c. + // xy_to_ll(&x,&y,&lat,&lon,&my_proj); + // lat01=lat+0.1; + // ll_to_xy(&lat01,&lon,&dx,&dy,&my_proj); + // dx -= x; + + dy -= y; + + double mag = Math.sqrt(dx * dx + dy * dy); + dx /= mag; + dy /= mag; + double erot_i = -dy; + double erot_j = -dx; + + double nrot_i = dx; + double nrot_j = dy; + + int[] ew_hist = new int[nx * ny]; + int[] ns_hist = new int[nx * ny]; + + /* Calculate north/south & east/west offsets, create histogram of these. */ + // TODO I did not fully implement the histograms as used in a1. Using + // the histograms created index out of bounds errors. If the field is + // unhappy with the portions, then porting the histograms needs to be + // re-investigated. + int ns1 = 0, ns2 = 0, ew1 = 0, ew2 = 0; + int np_n = 0, np_s = 0, np_e = 0, np_w = 0; + ns_hist[0] = 0; + ew_hist[0] = 0; + for (jj = min_j; jj < max_j; jj++) { + k = nx * jj + min_i; + for (ii = min_i; ii < max_i; ii++, k++) { + // If the entity is not 1 then it's not part of the county or + // zone area. + if (countyOrZoneGrid[k] != 1) { + continue; + } + double di = ii - i_base; + double dj = jj - j_base; + + double dns = (int) (nrot_i * di + nrot_j * dj); + while (ns1 > dns) { + // ns_hist[--ns1] = 0; + --ns1; + } + + while (ns2 < dns) { + // ns_hist[++ns2] = 0; + ++ns2; + } + // ns_hist[(int) dns]++; + + double dew = (int) (erot_i * di + erot_j * dj); + while (ew1 > dew) { + // ew_hist[--ew1] = 0; + --ew1; + } + while (ew2 < dew) { + // ew_hist[++ew2] = 0; + ++ew2; + } + // ew_hist[(int) dew]++; + + if (dew < 0) { + np_w++; + } + if (dew > 0) { + np_e++; + } + if (dns < 0) { + np_s++; + } + if (dns > 0) { + np_n++; + } + }/* end for */ + }/* end for */ + + /* + * Transform n-s & e-w offsets into normalized distances north and + * south. This is done based on a preferred fraction of each area that + * is "extreme". + */ + + // a lot of assumptions were made here. therefore, not everything in + // this part was fully ported. + double target = np_w * EXTREME_FRAC; + // for (ii = 0, k = ew1; k < -1 && ii < target; k++) { + // ii += ew_hist[k]; + // } + // if (ii / target > 1.5) { + // k--; + // } + // if (k < ew1) { + // k = ew1; + // } + + k = ew1; + double mu_w = (MIN_EXTREME - 127) / (k + 0.5); + + target = np_e * EXTREME_FRAC; + // for (ii = 0, k = ew2; k > 1 && ii < target; k--) { + // ii += ew_hist[k]; + // } + // if (ii / target > 1.5) { + // k++; + // } + // if (k > ew2) { + // k = ew2; + // } + + k = ew2; + double mu_e = (MAX_EXTREME - 127) / (k - 0.5); + + target = np_s * EXTREME_FRAC; + // for (ii = 0, k = ns1; k < -1 && ii < target; k++) { + // ii += ns_hist[k]; + // } + // if (ii / target > 1.5) { + // k--; + // } + // if (k < ns1) { + // k = ns1; + // } + + k = ns1;// TODO - REPLACE WITH ABOVE + double mu_s = (MIN_EXTREME - 127) / (k + 0.5); + + target = np_n * EXTREME_FRAC; + // for (ii = 0, k = ns2; k > 1 && ii < target; k--) { + // ii += ns_hist[k]; + // } + // if (ii / target > 1.5) { + // k++; + // } + // if (k > ns2) { + // k = ns2; + // } + + k = ns2; + double mu_n = (MAX_EXTREME - 127) / (k - 0.5); + + for (jj = min_j; jj < max_j; jj++) { + k = nx * jj + min_i; + for (ii = min_i; ii < max_i; ii++, k++) { + // If the entity is not 1 then it's not part of the county or + // zone area. + if (countyOrZoneGrid[k] != 1) { + ewGrid[k] = 0; + nsGrid[k] = 0; + continue; + } + + double di = ii - i_base; + double dj = jj - j_base; + double dns = (int) (nrot_i * di + nrot_j * dj); + double dew = (int) (erot_i * di + erot_j * dj); + int c_ns2 = (int) (dns); + int c_ew2 = (int) (dew); + + if (c_ew2 < 0) { + dx = c_ew2 * mu_w; + } else { + dx = c_ew2 * mu_e; + } + + if (dx > 127) { + dx = 127; + } + + if (dx < -127) { + dx = -127; + } + + ewGrid[k] = (int) (127 + (int) (dx)); + + if (c_ns2 < 0) { + dy = c_ns2 * mu_s; + } else { + dy = c_ns2 * mu_n; + } + + if (dy > 127) { + dy = 127; + } + + if (dy < -127) { + dy = -127; + } + + nsGrid[k] = (int) (127 + (int) (dy)); + } + } + // System.out.println("-----------------------------------"); + // printGrids(countyOrZoneGrid, min_i, max_i, min_j, max_j); + // System.out.println("-----------------------------------"); + // printGrids(_currentArea, min_i, max_i, min_j, max_j); + // System.out.println("-------------- EAST WEST ---------------------"); + // printGrids(ewGrid, min_i, max_i, min_j, max_j); + // System.out.println("-------------- NORTH SOUTH ---------------------"); + // printGrids(nsGrid, min_i, max_i, min_j, max_j); + // System.out.println("north/south - east/west done"); + return new int[] { min_i, max_i, min_j, max_j }; + + } + + // For debugging and view the grid in ascii format. + private void printGrids(int[] grid, int min_i, int max_i, int min_j, + int max_j) { + int k = 0; + for (int jj = min_j; jj < max_j; jj++) { + k = nx * jj + min_i; + for (int ii = min_i; ii < max_i; ii++) { + System.out.print((int) grid[k]); + k++; + } + System.out.println("-"); + } + } + + // For debugging and view the grid in ascii format. + private void printGrids(byte[] grid, int min_i, int max_i, int min_j, + int max_j) { + int k = 0; + for (int jj = min_j; jj < max_j; jj++) { + k = nx * jj + min_i; + for (int ii = min_i; ii < max_i; ii++) { + System.out.print((int) grid[k]); + k++; + } + System.out.println("-"); + } + } + +} diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PortionsUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PortionsUtil.java new file mode 100644 index 0000000000..a5188b95d6 --- /dev/null +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PortionsUtil.java @@ -0,0 +1,471 @@ +/** + * 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.warngen.gis; + +import java.util.EnumSet; +import java.util.List; +import java.util.Map; + +import com.raytheon.viz.warngen.gis.GisUtil.Direction; +import com.raytheon.viz.warngen.gui.WarngenLayer; +import com.vividsolutions.jts.geom.Geometry; + +/** + * Port of A1 code that determines the portions of the county or zone + * descriptions, such as NORTHWEST. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 5, 2013  2177       jsanchez     Initial creation
+ * 
+ * 
+ * + * @author jsanchez + * @version 1.0 + */ + +public class PortionsUtil { + + private GridUtil gridUtil; + + public PortionsUtil(WarngenLayer layer) throws Exception { + gridUtil = new GridUtil(layer, layer.getLocalGridGeometry(), + layer.getlocalToLatLon()); + } + + /** + * Determines the the appropriate portion description for the warnedArea + * intersecting the countyOrZone. + * + * @param entityID + * @param countyOrZone + * @param warnedArea + * @param useExtreme + * @return + * @throws Exception + */ + public EnumSet getPortions(String entityID, + Geometry countyOrZone, Geometry warnedArea, boolean useExtreme) + throws Exception { + countyOrZone.getUserData(); + EntityData entityData = gridUtil.calculateGrids(countyOrZone, + warnedArea); + EnumSet portions = getAreaDesc(entityData.getMeanMask(), + entityData.getCoverageMask(), entityData.getOctants(), + useExtreme); + return suppressPortions(entityID, portions); + } + + /** + * Looks up if the designated entity ID has an suppressed directions. For + * example, a county or zone may not need to include the north and sound + * direction description if it was included in the area.suppress file. + * + * @param entityID + * @param portions + * @return + */ + private EnumSet suppressPortions(String entityID, + EnumSet portions) { + Map> suppressedCounties = SuppressMap + .getInstance().getAreas(); + if (entityID != null && suppressedCounties != null + && !suppressedCounties.isEmpty()) { + List suppressedDirections = suppressedCounties + .get(entityID.toUpperCase()); + if (suppressedDirections != null && !suppressedDirections.isEmpty()) { + portions.removeAll(suppressedDirections); + } + } + + return portions; + } + + /** + * Port from A1 code of GeoEntityLookupTable::getAreaDesc. + * + * @param meanMask + * @param areaMask + * @param octants + * @param exYes + */ + private static EnumSet getAreaDesc(int meanMask, int areaMask, + int octants, boolean exYes) { + EnumSet portions = EnumSet.noneOf(Direction.class); + + // Test for case where we cannot do portions + if (meanMask == 0 || areaMask == 0) { + return portions; + } + + // The next block of code is the original port of A1 code but prevented + // producing the correct result: + // Test for case where area is completely within one subsection. + // if (meanMask == areaMask) { + // return getPointDesc(meanMask, exYes); + // } + + // Test for central by not being near adjacent borders. + if (octants == 0 + || ((octants & CoverageConstants.EXTREME_YES) == 0) + && (meanMask & CoverageConstants.CENTER) == CoverageConstants.CENTER) { + portions.add(Direction.CENTRAL); + return portions; + } + + if ((octants & 0xFFFF) == 0xFFFF) { + return portions; + } + + // Identify quadrants in use, q is typical, qq is diagonal. + int xoctant = octants >> 8; + int xxoctant = octants >> 16; + int nn, ss, ee, ww, ne, nw, se, sw; + nn = ss = ee = ww = ne = nw = se = sw = 0; + int omerge = xxoctant | xoctant | octants; + if ((omerge & (CoverageConstants.NNE | CoverageConstants.ENE)) > 0) { + ne = 1; + } + if ((omerge & (CoverageConstants.SSE | CoverageConstants.ESE)) > 0) { + se = 1; + } + if ((omerge & (CoverageConstants.NNW | CoverageConstants.WNW)) > 0) { + nw = 1; + } + if ((omerge & (CoverageConstants.SSW | CoverageConstants.WSW)) > 0) { + sw = 1; + } + if ((omerge & (CoverageConstants.NNE | CoverageConstants.NNW)) > 0) { + nn = 1; + } + if ((omerge & (CoverageConstants.SSE | CoverageConstants.SSW)) > 0) { + ss = 1; + } + if ((omerge & (CoverageConstants.WNW | CoverageConstants.WSW)) > 0) { + ww = 1; + } + if ((omerge & (CoverageConstants.ENE | CoverageConstants.ESE)) > 0) { + ee = 1; + } + if ((areaMask & CoverageConstants.NORTH_SOUTH) == 0) { + nn = ss = ne = nw = se = sw = 0; + } + if ((areaMask & CoverageConstants.EAST_WEST) == 0) { + ee = ww = ne = nw = se = sw = 0; + } + int q = ne + nw + se + sw; + int qq = nn + ss + ee + ww; + + // Identify extremes in use. + int nnx, ssx, eex, wwx; + nnx = ssx = eex = wwx = 0; + if ((areaMask & CoverageConstants.XNORTH) > 0) { + nnx = 1; + } + if ((areaMask & CoverageConstants.XSOUTH) > 0) { + ssx = 1; + } + if ((areaMask & CoverageConstants.XWEST) > 0) { + wwx = 1; + } + if ((areaMask & CoverageConstants.XEAST) > 0) { + eex = 1; + } + int xxx = nnx + ssx + eex + wwx; + + // Modify masks based on whether we can use extreme. + if ((octants & CoverageConstants.EXTREME_NO) > 0 + && (areaMask & CoverageConstants.EXTREME) > 0) { + areaMask &= CoverageConstants.NOT_EXTREME; + meanMask &= CoverageConstants.NOT_EXTREME; + } + + // Possible case of a stripe across the middle + if (q == 0) { + ;// Only one direction encoded + } else if (q == 2 && nw == se || q == 2 && ne == sw || qq == 2 + && nn == ss || qq == 2 && ee == ww) { + if ((meanMask & CoverageConstants.CENTRAL) == CoverageConstants.CENTRAL + || nnx == ssx && wwx == eex) { + portions.add(Direction.CENTRAL); + return portions; + } + return getPointDesc2(meanMask, exYes, nn, ss, ee, ww); + } + + // Modify masks based on whether we can use central. + if (xxx > 2 || nnx != ssx && wwx != eex) { + areaMask &= CoverageConstants.NOT_CENTRAL; + meanMask &= CoverageConstants.NOT_CENTRAL; + } + + // Another possible case of a stripe across the middle. + if (q == 4 && (meanMask & CoverageConstants.CENTER) > 0) { + portions.add(Direction.CENTRAL); + return portions; + } + + // All quadrants in use. + if (q == 4 && qq == 4) { + return EnumSet.noneOf(Direction.class); + } + + // Only one typical quadrant in use. + if (q == 1) { + // if (ne == 1) { + // portions.add(Direction.NORTH); + // portions.add(Direction.EAST); + // } else if (nw == 1) { + // portions.add(Direction.NORTH); + // portions.add(Direction.WEST); + // } else if (se == 1) { + // portions.add(Direction.SOUTH); + // portions.add(Direction.EAST); + // } else if (sw == 1) { + // portions.add(Direction.SOUTH); + // portions.add(Direction.WEST); + // } + // return portions; + return getPointDesc2(meanMask, exYes, nn, ss, ee, ww); + } + + // Further modify masks based on whether we can use central. + if (xxx >= 2) { + areaMask &= CoverageConstants.NOT_CENTRAL; + meanMask &= CoverageConstants.NOT_CENTRAL; + } + + // No more than two quadrants of any kind in use, or all quadrants. + if (q < 3 && qq < 3) { + if (nnx != ssx && wwx != eex + || (meanMask & CoverageConstants.CENTRAL) > 0) { + return getPointDesc2(meanMask, exYes, nn, ss, ee, ww); + + } else { + return getPointDesc2(areaMask, exYes, nn, ss, ee, ww); + } + } + + // Three typical quadrants in use. + if (q == 3 && qq != 3) { + + if (ne == 0) { + // The next line is the original port of A1 code but prevented + // producing the correct result: + // if (ne == 0 && (xxoctant & (SSW | WSW)) > 0) { + portions.add(Direction.SOUTH); + portions.add(Direction.WEST); + + } else if (se == 0) { + // The next line is the original port of A1 code but prevented + // producing the correct result: + // } else if (se == 0 && (xxoctant & (NNW | WNW)) > 0) { + portions.add(Direction.NORTH); + portions.add(Direction.WEST); + + } else if (nw == 0) { + // The next line is the original port of A1 code but prevented + // producing the correct result: + // } else if (nw == 0 && (xxoctant & (SSE | ESE)) > 0) { + portions.add(Direction.SOUTH); + portions.add(Direction.EAST); + + } else if (sw == 0) { + // The next line is the original port of A1 code but prevented + // producing the correct result: + // } else if (sw == 0 && (xxoctant & (NNE | ENE)) > 0) { + portions.add(Direction.NORTH); + portions.add(Direction.EAST); + } + // The next line is the original port of A1 code but prevented + // producing the correct result: + // return getPointDesc(meanMask, exYes); + } + + // Three diagonal quadrants in use. + if (qq == 3 && portions.isEmpty()) { + if (nn == 0) { + portions.add(Direction.SOUTH); + } else if (ss == 0) { + portions.add(Direction.NORTH); + } else if (ww == 0) { + portions.add(Direction.EAST); + } else if (ee == 0) { + portions.add(Direction.WEST); + } + } + + // add extreme for three quadrant case. + if (!portions.isEmpty()) { + if (exYes && ((areaMask & CoverageConstants.EXTREME)) > 0) { + portions.add(Direction.EXTREME); + } + return portions; + } + + // All of either type of quadrant in use. + if (q == 4 || qq == 4) { + return EnumSet.noneOf(Direction.class); + } + + // Case of a pure simple direction. + nn = areaMask & CoverageConstants.NORTHERN; + ss = areaMask & CoverageConstants.SOUTHERN; + ee = areaMask & CoverageConstants.EASTERN; + ww = areaMask & CoverageConstants.WESTERN; + if (ss > 0 && nn > 0 || q == 0) { + if (ee == 0 && ww > 0) { + portions.add(Direction.WEST); + } + if (ww == 0 && ee > 0) { + portions.add(Direction.EAST); + } + } else if (ee > 0 && ww > 0 || q == 0) { + if (nn == 0 && ss > 0) { + portions.add(Direction.SOUTH); + } + if (ss == 0 && nn > 0) { + portions.add(Direction.NORTH); + } + } + + // add extreme for simple direction case. + if (!portions.isEmpty()) { + if (exYes && ((areaMask & CoverageConstants.EXTREME)) > 0) { + portions.add(Direction.EXTREME); + } + return portions; + } + + // Catch with the point descriptor one last time + return getPointDesc2(meanMask, exYes, nn, ss, ee, ww); + } + + /** + * Port from A1 code of GeoEntityLookupTable::getPointDesc. + * + * @param mask + * @param exYes + * @return + */ + private static EnumSet getPointDesc(int mask, boolean exYes) { + EnumSet portions = EnumSet.noneOf(Direction.class); + + if (mask == 0) { + return portions; + } + + int cc = mask & CoverageConstants.CENTRAL; + if (cc == CoverageConstants.CENTRAL) { + portions.add(Direction.CENTRAL); + return portions; + } + + if ((mask & CoverageConstants.NORTH_SOUTH) == 0) { + ; + } else if ((mask & CoverageConstants.SOUTHERN) == (mask & CoverageConstants.NORTH_SOUTH)) { + portions.add(Direction.SOUTH); + } else if ((mask & CoverageConstants.NORTHERN) == (mask & CoverageConstants.NORTH_SOUTH)) { + portions.add(Direction.NORTH); + } + + if ((mask & CoverageConstants.EAST_WEST) == 0) { + ; + } else if ((mask & CoverageConstants.WESTERN) == (mask & CoverageConstants.EAST_WEST)) { + portions.add(Direction.WEST); + } else if ((mask & CoverageConstants.EASTERN) == (mask & CoverageConstants.EAST_WEST)) { + portions.add(Direction.EAST); + } + + if (portions.isEmpty()) { + return portions; + } + + if (cc != 0) { + portions.add(Direction.CENTRAL); + } + + if (exYes && ((int) (mask & CoverageConstants.EXTREME) > 0)) { + portions.add(Direction.EXTREME); + } + + return portions; + } + + /** + * This method is not a direct port from A1. The original getPointDesc did + * not produce the expected results. This method is a modified version of + * getPointDesct that uses the calculated qq values instead of just the + * meanMask. + * + * @param mask + * @param exYes + * @return + */ + private static EnumSet getPointDesc2(int mask, boolean exYes, + int nn, int ss, int ee, int ww) { + EnumSet portions = EnumSet.noneOf(Direction.class); + + if (mask == 0) { + return portions; + } + + int counter = 0; + if (nn > 0 && ss > 0) { + ; + } else if (ss > 0) { + portions.add(Direction.SOUTH); + counter++; + } else if (nn > 0) { + portions.add(Direction.NORTH); + counter++; + } + + if (ee > 0 && ww > 0) { + ; + } else if (ww > 0) { + portions.add(Direction.WEST); + counter++; + } else if (ee > 0) { + portions.add(Direction.EAST); + counter++; + } + + if (portions.isEmpty()) { + return portions; + } + + int cc = mask & CoverageConstants.CENTRAL; + boolean useCentral = counter < 2; + if (useCentral && cc != 0) { + portions.add(Direction.CENTRAL); + } + + if (exYes && ((int) (mask & CoverageConstants.EXTREME) > 0)) { + portions.add(Direction.EXTREME); + } + + return portions; + } +} diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/suppress/SuppressMap.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/SuppressMap.java similarity index 55% rename from cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/suppress/SuppressMap.java rename to cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/SuppressMap.java index 45e27a2771..83de8980aa 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/suppress/SuppressMap.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/SuppressMap.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.viz.warngen.suppress; +package com.raytheon.viz.warngen.gis; import java.io.BufferedReader; import java.io.File; @@ -25,7 +25,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -38,9 +41,11 @@ import com.raytheon.uf.common.localization.PathManagerFactory; 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.core.localization.LocalizationManager; +import com.raytheon.viz.warngen.gis.GisUtil.Direction; /** - * TODO Add Description + * Creates a map of all the site's area suppress files. * *
  * 
@@ -48,6 +53,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Aug 2, 2010            jsanchez     Initial creation
+ * Aug 15,2013  2177      jsanchez     Refactored.
  * 
  * 
* @@ -66,16 +72,26 @@ public class SuppressMap { private static final Pattern ugcPattern = Pattern .compile("[A-Z]{2}[CZ][0-9]{3}"); - public static final String NORTH_SOUTH = "NS"; + private static final List NORTH_SOUTH = Arrays.asList( + Direction.NORTH, Direction.SOUTH); - public static final String EAST_WEST = "EW"; + private static final List EAST_WEST = Arrays.asList( + Direction.EAST, Direction.WEST); - public static final String NONE = "NONE"; + private static final List ALL = Arrays.asList(Direction.NORTH, + Direction.SOUTH, Direction.EAST, Direction.WEST, Direction.CENTRAL, + Direction.EXTREME); - public static final String ALL = "ALL"; + private static Map>> suppressMap = new HashMap>>(); - private Map suppressMap = new HashMap(); + private SuppressMap() { + } + + /** + * + * @return an instance of the SuppressMap object. + */ public static SuppressMap getInstance() { if (instance == null) { instance = new SuppressMap(); @@ -83,64 +99,82 @@ public class SuppressMap { return instance; } - private SuppressMap() { - readFile(); + /** + * Returns the suppressed area map for the current localized site. + * + * @return + */ + public Map> getAreas() { + String threeLetterSiteID = LocalizationManager.getInstance() + .getCurrentSite(); + Map> areas = suppressMap.get(threeLetterSiteID); + + if (areas == null) { + areas = new HashMap>(); + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationContext lc = pm.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + File file = pm.getFile(lc, AREA_SUPPRESS_FILENAME); + loadFile(file, areas); + } + + return areas; } - private void readFile() { - // load site - IPathManager pathMgr = PathManagerFactory.getPathManager(); - LocalizationContext lc = pathMgr.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - File file = pathMgr.getFile(lc, AREA_SUPPRESS_FILENAME); - loadFile(file, suppressMap); - } - - private void loadFile(File file, Map aliasMap) { + /** + * Loads the areas map with the suppress information in the file + * + * @param file + * @param areas + */ + private void loadFile(File file, Map> areas) { if ((file != null) && file.exists()) { Matcher m = null; + BufferedReader fis = null; try { - BufferedReader fis = new BufferedReader(new InputStreamReader( + fis = new BufferedReader(new InputStreamReader( new FileInputStream(file))); + String line = null; try { while ((line = fis.readLine()) != null) { m = ugcPattern.matcher(line); if (m.find()) { - String dataKey = m.group(); - String data = ALL; + List suppressedDirections = new ArrayList(); + String ugc = m.group(); if (line.indexOf("ns") > 5) { - data = NORTH_SOUTH; + suppressedDirections = NORTH_SOUTH; } else if (line.indexOf("ew") > 5) { - data = EAST_WEST; + suppressedDirections = EAST_WEST; + } else { + suppressedDirections = ALL; } - aliasMap.put(dataKey, data); + areas.put(ugc, suppressedDirections); } } } catch (IOException e) { - // TODO Auto-generated catch block. Please revise as - // appropriate. statusHandler.handle(Priority.PROBLEM, "Could not read counties file: " + AREA_SUPPRESS_FILENAME, e); } } catch (FileNotFoundException e) { - // TODO Auto-generated catch block. Please revise as - // appropriate. statusHandler.handle(Priority.PROBLEM, "Failed to find counties file: " + AREA_SUPPRESS_FILENAME, e); + } finally { + + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + statusHandler.handle(Priority.PROBLEM, + "Error trying to close buffered reader ", e); + } + + } } } } - - public String getType(String key) { - if (suppressMap.containsKey(key)) { - return suppressMap.get(key); - } else { - return NONE; - } - } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java index 12b5db47ca..64761c6405 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/FollowupData.java @@ -20,7 +20,7 @@ package com.raytheon.viz.warngen.gui; import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord; -import com.raytheon.uf.common.dataplugin.warning.WarningRecord; +import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction; import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.util.TimeUtil; @@ -37,20 +37,21 @@ import com.raytheon.uf.common.time.util.TimeUtil; * May 7, 2013 1973 rferrel Changes to properly display Issue Time. * Jul 22, 2013 2176 jsanchez Added EMER to the display string in the update list. * Aug 7, 2013 2243 jsanchez Set all the attributes of an AbstractWarningRecord and added an expiration string. Removed calendar object. + * Aug 15,2013 2243 jsanchez Improved the expiration string off by one minute. Fixed for practice mode. * Aug 15,2013 2243 jsanchez Improved the expiration string off by one minute. * * * @author rferrel * @version 1.0 */ -public class FollowupData extends WarningRecord { +public class FollowupData extends AbstractWarningRecord { private static final long serialVersionUID = 1L; /** * String displayed in the drop down update list. */ - private String displayString; + private final String displayString; /** * String used to test if this object is equivalent to one of the updated @@ -61,10 +62,10 @@ public class FollowupData extends WarningRecord { /** * Information string used when the follow up is no longer valid or allowed. */ - private String expirationString; + private final String expirationString; public FollowupData(WarningAction action, AbstractWarningRecord record) { - super((WarningRecord) record); + super(record); setAct(action.toString()); displayString = createDisplayString(action, record); @@ -191,4 +192,13 @@ public class FollowupData extends WarningRecord { return expirationString; } + /* + * (non-Javadoc) + * + * @see com.raytheon.uf.common.dataplugin.PluginDataObject#getPluginName() + */ + @Override + public String getPluginName() { + return "followupwarning"; + } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenAction.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenAction.java index 1f3acfd098..f2a27ce707 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenAction.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenAction.java @@ -26,6 +26,7 @@ import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.tools.GenericToolsResourceData; import com.raytheon.uf.viz.core.rsc.tools.action.AbstractGenericToolAction; +import com.raytheon.viz.ui.input.EditableManager; /** * Simple action for loading the warngen layer @@ -38,6 +39,7 @@ import com.raytheon.uf.viz.core.rsc.tools.action.AbstractGenericToolAction; * May 4, 2010 mschenke Initial creation * Oct 10, 2010 6990 Qinglu Lin Used D. Friedman short solution, * with minor changes. + * Aug 15, 2013 DR 16418 D. Friedman Always show the dialog. * * * @@ -65,16 +67,16 @@ public class WarngenAction extends AbstractGenericToolAction { for (IDisplayPane pane : getSelectedPanes()) { for (ResourcePair rp : pane.getDescriptor().getResourceList()) { if (rp.getResource() instanceof WarngenLayer) { + EditableManager.makeEditable(rp.getResource(), true); ((WarngenLayer) rp.getResource()) - .showDialog(((WarngenLayer) rp.getResource()) - .isEditable()); + .showDialog(true); return (WarngenLayer) rp.getResource(); } } } WarngenLayer layer = super.getResource(loadProperties, descriptor); - layer.createDialog(); + layer.showDialog(true); return layer; } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java index 02b319c787..6525feec70 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenDialog.java @@ -52,9 +52,11 @@ import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; @@ -82,6 +84,7 @@ import com.raytheon.viz.texteditor.util.VtecUtil; import com.raytheon.viz.ui.EditorUtil; import com.raytheon.viz.ui.dialogs.CaveSWTDialog; import com.raytheon.viz.ui.dialogs.ICloseCallback; +import com.raytheon.viz.ui.input.EditableManager; import com.raytheon.viz.warngen.Activator; import com.raytheon.viz.warngen.WarngenConstants; import com.raytheon.viz.warngen.comm.WarningSender; @@ -144,6 +147,7 @@ import com.vividsolutions.jts.geom.Polygon; * Jul 16, 2013 DR 16387 Qinglu Lin Reset totalSegments for each followup product. * Jul 29, 2013 DR 16352 D. Friedman Move 'result' to okPressed(). * Aug 6, 2013 2243 jsanchez Refreshed the follow up list every minute. + * Aug 15, 2013 DR 16418 D. Friedman Make dialog visibility match editable state. * * * @author chammack @@ -306,6 +310,14 @@ public class WarngenDialog extends CaveSWTDialog implements */ @Override protected void initializeComponents(Shell shell) { + shell.addListener(SWT.Close, new Listener() { + @Override + public void handleEvent(Event event) { + event.doit = false; + closePressed(); + } + }); + Composite mainComposite = new Composite(shell, SWT.NONE); GridLayout gl = new GridLayout(1, false); gl.verticalSpacing = 2; @@ -1256,7 +1268,8 @@ public class WarngenDialog extends CaveSWTDialog implements * Action for Close button */ private void closePressed() { - close(); + EditableManager.makeEditable(warngenLayer, false); + hide(); } /** @@ -2194,6 +2207,8 @@ public class WarngenDialog extends CaveSWTDialog implements } // Move above parent shell if we are showing it shell.moveAbove(getParent()); + } else { + shell.setVisible(false); } } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index e43d9ff3cb..a7e1d400cb 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -49,6 +49,9 @@ import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.ui.PlatformUI; +import org.geotools.coverage.grid.GeneralGridEnvelope; +import org.geotools.coverage.grid.GeneralGridGeometry; +import org.geotools.geometry.GeneralEnvelope; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.GeodeticCalculator; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -57,7 +60,6 @@ import org.opengis.referencing.operation.MathTransform; import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord; import com.raytheon.uf.common.dataplugin.warning.WarningRecord.WarningAction; import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration; -import com.raytheon.uf.common.dataplugin.warning.config.AreaSourceConfiguration.AreaType; import com.raytheon.uf.common.dataplugin.warning.config.BulletActionGroup; import com.raytheon.uf.common.dataplugin.warning.config.DialogConfiguration; import com.raytheon.uf.common.dataplugin.warning.config.GridSpacing; @@ -185,6 +187,7 @@ import com.vividsolutions.jts.io.WKTReader; * 07/26/2013 DR 16376 Qinglu Lin Moved adjustVertex() and computeSlope() to PolygonUtil; removed calculateDistance(); * updated AreaHatcher's run(). * 07/26/2013 DR 16450 D. Friedman Fix logic errors when frame count is one. + * 08/19/2013 2177 jsanchez Set a GeneralGridGeometry object in the GeospatialDataList. * * * @author mschenke @@ -212,24 +215,28 @@ public class WarngenLayer extends AbstractStormTrackResource { IExtent localExtent; int nx, ny; + + GeneralGridGeometry localGridGeometry; } private static class GeospatialDataAccessor { GeospatialDataList geoData; + AreaSourceConfiguration areaConfig; public GeospatialDataAccessor(GeospatialDataList geoData, AreaSourceConfiguration areaConfig) { if (geoData == null || areaConfig == null) { - throw new IllegalArgumentException("GeospatialDataAccessor must not be null"); + throw new IllegalArgumentException( + "GeospatialDataAccessor must not be null"); } this.geoData = geoData; this.areaConfig = areaConfig; } /** - * Build the geometry area that intersects the cwa filter for the polygon in - * local projection space + * Build the geometry area that intersects the cwa filter for the + * polygon in local projection space * * @param polygon * polygon to intersect with in lat/lon space @@ -243,8 +250,8 @@ public class WarngenLayer extends AbstractStormTrackResource { PreparedGeometry prepGeom = (PreparedGeometry) r.attributes .get(GeospatialDataList.LOCAL_PREP_GEOM); try { - Geometry intersection = GeometryUtil.intersection(polygon, - prepGeom); + Geometry intersection = GeometryUtil.intersection( + polygon, prepGeom); if (intersection.isEmpty()) { continue; } @@ -407,7 +414,8 @@ public class WarngenLayer extends AbstractStormTrackResource { } try { - warningPolygon = PolygonUtil.removeDuplicateCoordinate(warningPolygon); + warningPolygon = PolygonUtil + .removeDuplicateCoordinate(warningPolygon); Polygon hatched = polygonUtil.hatchWarningArea( warningPolygon, removeCounties(warningArea, @@ -425,27 +433,37 @@ public class WarngenLayer extends AbstractStormTrackResource { LinearRing lr = gf.createLinearRing(coords); hatchedArea = gf.createPolygon(lr, null); int adjustPolygon_counter = 0; - while (!hatchedArea.isValid() && adjustPolygon_counter < 1) { - System.out.println("Calling adjustPolygon #" + adjustPolygon_counter); + while (!hatchedArea.isValid() + && adjustPolygon_counter < 1) { + System.out.println("Calling adjustPolygon #" + + adjustPolygon_counter); PolygonUtil.adjustPolygon(coords); PolygonUtil.round(coords, 2); - coords = PolygonUtil.removeDuplicateCoordinate(coords); - coords = PolygonUtil.removeOverlaidLinesegments(coords); + coords = PolygonUtil + .removeDuplicateCoordinate(coords); + coords = PolygonUtil + .removeOverlaidLinesegments(coords); lr = gf.createLinearRing(coords); hatchedArea = gf.createPolygon(lr, null); adjustPolygon_counter += 1; } int counter = 0; if (!hatchedArea.isValid() && counter < 2) { - System.out.println("calling adjustVertex & alterVertexes: loop #" + counter); + System.out + .println("calling adjustVertex & alterVertexes: loop #" + + counter); int adjustVertex_counter = 0; lr = gf.createLinearRing(coords); hatchedArea = gf.createPolygon(lr, null); - while (!hatchedArea.isValid() && adjustVertex_counter < 5) { - System.out.println(" Calling adjustVertex #" + adjustVertex_counter); + while (!hatchedArea.isValid() + && adjustVertex_counter < 5) { + System.out.println(" Calling adjustVertex #" + + adjustVertex_counter); coords = PolygonUtil.adjustVertex(coords); - coords = PolygonUtil.removeDuplicateCoordinate(coords); - coords = PolygonUtil.removeOverlaidLinesegments(coords); + coords = PolygonUtil + .removeDuplicateCoordinate(coords); + coords = PolygonUtil + .removeOverlaidLinesegments(coords); lr = gf.createLinearRing(coords); hatchedArea = gf.createPolygon(lr, null); adjustVertex_counter += 1; @@ -453,10 +471,14 @@ public class WarngenLayer extends AbstractStormTrackResource { int inner_counter = 0; System.out.println(""); while (!hatchedArea.isValid() && inner_counter < 5) { - System.out.println(" Calling alterVertexes #" + inner_counter); + System.out + .println(" Calling alterVertexes #" + + inner_counter); coords = PolygonUtil.alterVertexes(coords); - coords = PolygonUtil.removeDuplicateCoordinate(coords); - coords = PolygonUtil.removeOverlaidLinesegments(coords); + coords = PolygonUtil + .removeDuplicateCoordinate(coords); + coords = PolygonUtil + .removeOverlaidLinesegments(coords); lr = gf.createLinearRing(coords); hatchedArea = gf.createPolygon(lr, null); inner_counter += 1; @@ -674,8 +696,7 @@ public class WarngenLayer extends AbstractStormTrackResource { displayState.angle = 0; displayState.speed = 0; } else if (checkStormTrackData(data = ToolsDataManager - .getInstance() - .getStormTrackData())) { + .getInstance().getStormTrackData())) { displayState.angle = adjustAngle(data.getMotionDirection()); displayState.speed = knotToMeterPerSec.convert(data .getMotionSpeed()); @@ -995,8 +1016,8 @@ public class WarngenLayer extends AbstractStormTrackResource { } if (config != null) { init(config); - displayState.setInitiallyMotionless( - this.configuration.isTrackEnabled() == false + displayState.setInitiallyMotionless(this.configuration + .isTrackEnabled() == false || this.configuration.getPathcastConfig() == null); } } @@ -1044,9 +1065,11 @@ public class WarngenLayer extends AbstractStormTrackResource { + (System.currentTimeMillis() - t0) + "ms"); } - /** Adds geospatial data to siteMap and timezoneMap for the given - * template configuration. This must not have any site effects on the - * currently loaded template or the current product being edited. + /** + * Adds geospatial data to siteMap and timezoneMap for the given template + * configuration. This must not have any site effects on the currently + * loaded template or the current product being edited. + * * @param config */ private void loadGeodataForConfiguration(WarngenConfiguration config) { @@ -1083,7 +1106,6 @@ public class WarngenLayer extends AbstractStormTrackResource { Coordinate c = new GeometryFactory() .buildGeometry(geoms).getCentroid() .getCoordinate(); - gData.latLonToLocal = MapUtil .getTransformFromLatLon(MapUtil .constructStereographic( @@ -1146,6 +1168,18 @@ public class WarngenLayer extends AbstractStormTrackResource { gData.nx = nx; gData.ny = ny; + GeneralGridEnvelope range = new GeneralGridEnvelope( + new int[] { 0, 0 }, new int[] { gData.nx, + gData.ny }, false); + GeneralEnvelope ge = new GeneralEnvelope(new double[] { + gData.localExtent.getMinX(), + gData.localExtent.getMaxY() }, new double[] { + gData.localExtent.getMaxX(), + gData.localExtent.getMinY() }); + + gData.localGridGeometry = new GeneralGridGeometry( + range, ge); + System.out.println("Time to lookup geospatial data " + (System.currentTimeMillis() - tq0)); siteMap.put(currKey, gData); @@ -1188,6 +1222,14 @@ public class WarngenLayer extends AbstractStormTrackResource { return new GeospatialData[0]; } + public GeneralGridGeometry getLocalGridGeometry() { + return geoData.localGridGeometry; + } + + public MathTransform getlocalToLatLon() { + return geoData.localToLatLon; + } + private GeospatialDataList getGeodataList(String areaSource, String localizedSite) { String key = areaSource + "." + localizedSite; @@ -1303,7 +1345,8 @@ public class WarngenLayer extends AbstractStormTrackResource { * Returns a set of UGCs for each area in the CWA that intersects the given * polygon. */ - public Set getUgcsForCountyWatches(Polygon polygon) throws Exception { + public Set getUgcsForCountyWatches(Polygon polygon) + throws Exception { GeospatialDataAccessor gda = getCountyGeospatialDataAcessor(); Set ugcs = new HashSet(); for (String fips : gda.getAllFipsInArea(gda.buildArea(polygon))) { @@ -1321,17 +1364,20 @@ public class WarngenLayer extends AbstractStormTrackResource { return ugcs; } - private GeospatialDataAccessor getCountyGeospatialDataAcessor() throws Exception { + private GeospatialDataAccessor getCountyGeospatialDataAcessor() + throws Exception { GeospatialDataList gdl = searchCountyGeospatialDataAccessor(); if (gdl == null) { // Cause county geospatial data to be loaded // TODO: Should not be referencing tornadoWarning. - WarngenConfiguration torConfig = WarngenConfiguration.loadConfig("tornadoWarning", getLocalizedSite()); + WarngenConfiguration torConfig = WarngenConfiguration.loadConfig( + "tornadoWarning", getLocalizedSite()); loadGeodataForConfiguration(torConfig); gdl = searchCountyGeospatialDataAccessor(); } - // TODO: There should be some way to get the "county" configuration by name + // TODO: There should be some way to get the "county" configuration by + // name // independent of a template AreaSourceConfiguration areaConfig = new AreaSourceConfiguration(); areaConfig.setFipsField("FIPS"); @@ -1341,7 +1387,8 @@ public class WarngenLayer extends AbstractStormTrackResource { private GeospatialDataList searchCountyGeospatialDataAccessor() { synchronized (siteMap) { - for (Map.Entry entry : siteMap.entrySet()) { + for (Map.Entry entry : siteMap + .entrySet()) { String[] keyParts = entry.getKey().split("\\."); if (keyParts.length == 2 && "county".equalsIgnoreCase(keyParts[0]) @@ -1938,8 +1985,8 @@ public class WarngenLayer extends AbstractStormTrackResource { return; } if (warningAction == null || warningAction == WarningAction.NEW) { - if ((configuration.isTrackEnabled() == false || - configuration.getPathcastConfig() == null) + if ((configuration.isTrackEnabled() == false || configuration + .getPathcastConfig() == null) && !this.displayState.isNonstationary() && this.displayState.displayType != DisplayType.POLY) { createSquare(); @@ -2271,8 +2318,8 @@ public class WarngenLayer extends AbstractStormTrackResource { } Point point = displayState.dragMePoint; - if (motdir != null && motspd != null && - (motspd != 0 || configuration.isTrackEnabled())) { + if (motdir != null && motspd != null + && (motspd != 0 || configuration.isTrackEnabled())) { displayState.setInitiallyMotionless(false); displayState.angle = adjustAngle(motdir); displayState.speed = knotToMeterPerSec.convert(motspd); @@ -2325,10 +2372,9 @@ public class WarngenLayer extends AbstractStormTrackResource { if (m.find()) { int hour = Integer.parseInt(m.group(1)); int minute = Integer.parseInt(m.group(2)); - frameTime = TimeUtil.timeOfDayToAbsoluteTime( - hour * TimeUtil.SECONDS_PER_HOUR + - minute * TimeUtil.SECONDS_PER_MINUTE, - warnRecord.getIssueTime()); + frameTime = TimeUtil.timeOfDayToAbsoluteTime(hour + * TimeUtil.SECONDS_PER_HOUR + minute + * TimeUtil.SECONDS_PER_MINUTE, warnRecord.getIssueTime()); } else { frameTime = warnRecord.getIssueTime(); } @@ -2376,8 +2422,7 @@ public class WarngenLayer extends AbstractStormTrackResource { FramesInfo info = descriptor.getFramesInfo(); int currentFrame = trackUtil.getCurrentFrame(info); int frameCount = trackUtil.getFrameCount(info); - if (currentFrame == frameCount - 1 - || ! displayState.isNonstationary()) { + if (currentFrame == frameCount - 1 || !displayState.isNonstationary()) { return coordinate; } DataTime[] datatimes = trackUtil.getDataTimes(info); @@ -2686,7 +2731,8 @@ public class WarngenLayer extends AbstractStormTrackResource { getFips(f)); if (tmp.isEmpty()) { String fip = getFips(f); - if (fip != null && uniqueFip != null && fip.equals(uniqueFip)) { + if (fip != null && uniqueFip != null + && fip.equals(uniqueFip)) { updateWarnedAreas(true); } break; @@ -2769,8 +2815,7 @@ public class WarngenLayer extends AbstractStormTrackResource { if (areaHatcher != null) { Polygon polygon = state.getWarningPolygon(); polygon = tryToIntersectWithOriginalPolygon(polygon); - areaHatcher.hatchArea(polygon, - state.getWarningArea(), + areaHatcher.hatchArea(polygon, state.getWarningArea(), state.getOldWarningPolygon()); } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java index f46990fcd3..8ce0946894 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenUIManager.java @@ -65,6 +65,7 @@ import com.vividsolutions.jts.geom.Polygon; * when c2 is null for "case SINGLE_POINT" in move(). * Mar 28, 2013 DR 15974 D. Friedman Do not track removed GIDs. * Jun 25, 2013 DR 16013 Qinglu Lin Called setUniqueFip() in handleMouseUp(). + * Aug 15, 2013 DR 16418 D. Friedman Only raise dialog if editable. Don't call featureEdit if not editable. * * * @@ -131,7 +132,9 @@ public class WarngenUIManager extends InputAdapter { */ @Override public boolean handleMouseDown(int x, int y, int button) { - warngenLayer.showDialog(true); + if (warngenLayer.isEditable()) { + warngenLayer.showDialog(true); + } lastMouseX = x; lastMouseY = y; if (!handleInput || warngenLayer.isBoxEditable() == false) { @@ -207,7 +210,7 @@ public class WarngenUIManager extends InputAdapter { return super.handleMouseUp(x, y, mouseButton); } - if (mouseButton == 3 && menuMove == false) { + if (mouseButton == 3 && menuMove == false && warngenLayer.isEditable()) { Coordinate c = container.translateClick(x, y); WarngenUIState state = warngenLayer.getWarngenState(); boolean geomsEqual = true; diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java index 36158e6bfe..a951233d94 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/template/TemplateRunner.java @@ -98,6 +98,7 @@ import com.raytheon.viz.warngen.gis.Area; import com.raytheon.viz.warngen.gis.ClosestPointComparator; import com.raytheon.viz.warngen.gis.GisUtil; import com.raytheon.viz.warngen.gis.PathCast; +import com.raytheon.viz.warngen.gis.PortionsUtil; import com.raytheon.viz.warngen.gis.Wx; import com.raytheon.viz.warngen.gui.BackupData; import com.raytheon.viz.warngen.gui.FollowupData; @@ -154,6 +155,7 @@ import com.vividsolutions.jts.io.WKTReader; * May 10, 2013 1951 rjpeter Updated ugcZones references * May 30, 2013 DR 16237 D. Friedman Fix watch query. * Jun 18, 2013 2118 njensen Only calculate pathcast if it's actually used + * Aug 19, 2013 2177 jsanchez Passed PortionsUtil to Area class. * * * @author njensen @@ -301,17 +303,18 @@ public class TemplateRunner { AffectedAreas[] cancelareas = null; Map intersectAreas = null; Wx wx = null; + Area area = new Area(new PortionsUtil(warngenLayer)); long wwaMNDTime = 0l; try { t0 = System.currentTimeMillis(); - areas = Area.findAffectedAreas(config, warnPolygon, warningArea, + areas = area.findAffectedAreas(config, warnPolygon, warningArea, threeLetterSiteId); System.out.println("Time to get areas = " + (System.currentTimeMillis() - t0)); context.put(config.getHatchedAreaSource().getVariable(), areas); t0 = System.currentTimeMillis(); - intersectAreas = Area.findInsectingAreas(config, warnPolygon, + intersectAreas = area.findInsectingAreas(config, warnPolygon, warningArea, threeLetterSiteId, warngenLayer); System.out.println("Time to get intersecting areas = " + (System.currentTimeMillis() - t0)); @@ -324,10 +327,11 @@ public class TemplateRunner { double minSize = 1.0E-3d; if ((areas != null) && (areas.length > 0)) { Set timeZones = new HashSet(); - for (AffectedAreas area : areas) { - if (area.getTimezone() != null) { + for (AffectedAreas affectedAreas : areas) { + if (affectedAreas.getTimezone() != null) { // Handles counties that span two time zones - String oneLetterTimeZones = area.getTimezone().trim(); + String oneLetterTimeZones = affectedAreas.getTimezone() + .trim(); oneLetterTZ = new String[oneLetterTimeZones.length()]; if (oneLetterTimeZones.length() == 1) { timeZones.add(String.valueOf(oneLetterTimeZones @@ -799,14 +803,14 @@ public class TemplateRunner { Geometry removedAreas = warngenLayer.getWarningAreaForGids( oldGids, oldWarningArea); if (removedAreas.isEmpty() == false) { - cancelareas = Area.findAffectedAreas(config, + cancelareas = area.findAffectedAreas(config, oldWarn.getGeometry(), removedAreas, threeLetterSiteId); for (int i = 0; i < cancelareas.length; i++) { - for (AffectedAreas area : areas) { + for (AffectedAreas affectedAreas : areas) { if ((cancelareas[i] != null) && cancelareas[i].getFips().equals( - area.getFips())) { + affectedAreas.getFips())) { cancelareas[i] = null; } } @@ -824,7 +828,7 @@ public class TemplateRunner { // This may not be efficient enough. Is it possible that // a removed intersected county be in the affected // intersected county. Need an example to fully test. - Map intersectRemovedAreas = Area + Map intersectRemovedAreas = area .findInsectingAreas(config, warnPolygon, removedAreas, threeLetterSiteId, warngenLayer); diff --git a/deltaScripts/13.5.2/addBufrmosDataURI.sh b/deltaScripts/13.5.2/addBufrmosDataURI.sh new file mode 100644 index 0000000000..b1ee9118d6 --- /dev/null +++ b/deltaScripts/13.5.2/addBufrmosDataURI.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# DR #2275 - this script is needd to add the dataURI column back into the +# bufrmosavn and bufrmoshpc tables. + +PSQL="/awips2/psql/bin/psql" + +${PSQL} -U awips -d metadata -c "ALTER TABLE bufrmosavn ADD COLUMN datauri character varying(255);" +if [ $? -ne 0 ]; then + echo "ERROR: Failed to drop dataURI column for bufrmosavn" + echo "FATAL: The update has failed." + exit 1 + fi +${PSQL} -U awips -d metadata -c "ALTER TABLE bufrmoshpc ADD COLUMN datauri character varying(255);" +if [ $? -ne 0 ]; then + echo "ERROR: Failed to add dataURI column for bufrmoshpc" + echo "FATAL: The update has failed." + exit 1 + fi +${PSQL} -U awips -d metadata -c "VACUUM FULL ANALYZE bufrmosavn" +${PSQL} -U awips -d metadata -c "VACUUM FULL ANALYZE bufrmoshpc" + +echo "INFO: dataURI columns added successfully" diff --git a/edexOsgi/build.edex/opt/db/ddl/ncep/loadSnap.sql b/edexOsgi/build.edex/opt/db/ddl/ncep/loadSnap.sql index 749139e5d4..81010d51c9 100644 --- a/edexOsgi/build.edex/opt/db/ddl/ncep/loadSnap.sql +++ b/edexOsgi/build.edex/opt/db/ddl/ncep/loadSnap.sql @@ -21330,1910 +21330,6 @@ YQV00227, 9,210NNW_YQV ,54.48,-104.77, 2 YQV00228, 9,220NNW_YQV ,54.63,-104.89, 2 YQV00229, 9,230NNW_YQV ,54.78,-105.01, 2 YQV00230, 9,240NNW_YQV ,54.93,-105.13, 2 -ANN00000, 9,ANN ,0.00,0.00, 1 -ANN00001, 9,20N_ANN ,0.33,0.00, 2 -ANN00002, 9,30N_ANN ,0.50,0.00, 2 -ANN00003, 9,40N_ANN ,0.67,0.00, 2 -ANN00004, 9,50N_ANN ,0.83,0.00, 2 -ANN00005, 9,60N_ANN ,1.00,0.00, 2 -ANN00006, 9,70N_ANN ,1.17,0.00, 2 -ANN00007, 9,80N_ANN ,1.33,0.00, 2 -ANN00008, 9,90N_ANN ,1.50,0.00, 2 -ANN00009, 9,100N_ANN ,1.67,0.00, 2 -ANN00010, 9,110N_ANN ,1.83,0.00, 2 -ANN00011, 9,120N_ANN ,2.00,0.00, 2 -ANN00012, 9,130N_ANN ,2.17,0.00, 2 -ANN00013, 9,140N_ANN ,2.33,0.00, 2 -ANN00014, 9,150N_ANN ,2.50,0.00, 2 -ANN00015, 9,160N_ANN ,2.66,0.00, 2 -ANN00016, 9,170N_ANN ,2.83,0.00, 2 -ANN00017, 9,180N_ANN ,3.00,0.00, 2 -ANN00018, 9,190N_ANN ,3.16,0.00, 2 -ANN00019, 9,200N_ANN ,3.33,0.00, 2 -ANN00020, 9,210N_ANN ,3.50,0.00, 2 -ANN00021, 9,220N_ANN ,3.66,0.00, 2 -ANN00022, 9,230N_ANN ,3.83,0.00, 2 -ANN00023, 9,240N_ANN ,4.00,0.00, 2 -ANN00024, 9,250N_ANN ,4.16,0.00, 2 -ANN00025, 9,20NNE_ANN ,0.31,0.13, 2 -ANN00026, 9,30NNE_ANN ,0.46,0.19, 2 -ANN00027, 9,40NNE_ANN ,0.62,0.25, 2 -ANN00028, 9,50NNE_ANN ,0.77,0.32, 2 -ANN00029, 9,60NNE_ANN ,0.92,0.38, 2 -ANN00030, 9,70NNE_ANN ,1.08,0.45, 2 -ANN00031, 9,80NNE_ANN ,1.23,0.51, 2 -ANN00032, 9,90NNE_ANN ,1.38,0.57, 2 -ANN00033, 9,100NNE_ANN ,1.54,0.64, 2 -ANN00034, 9,110NNE_ANN ,1.69,0.70, 2 -ANN00035, 9,120NNE_ANN ,1.85,0.77, 2 -ANN00036, 9,130NNE_ANN ,2.00,0.83, 2 -ANN00037, 9,140NNE_ANN ,2.15,0.89, 2 -ANN00038, 9,150NNE_ANN ,2.31,0.96, 2 -ANN00039, 9,160NNE_ANN ,2.46,1.02, 2 -ANN00040, 9,170NNE_ANN ,2.62,1.08, 2 -ANN00041, 9,180NNE_ANN ,2.77,1.15, 2 -ANN00042, 9,190NNE_ANN ,2.92,1.21, 2 -ANN00043, 9,200NNE_ANN ,3.08,1.28, 2 -ANN00044, 9,210NNE_ANN ,3.23,1.34, 2 -ANN00045, 9,220NNE_ANN ,3.38,1.40, 2 -ANN00046, 9,230NNE_ANN ,3.54,1.47, 2 -ANN00047, 9,240NNE_ANN ,3.69,1.53, 2 -ANN00048, 9,20NE_ANN ,0.24,0.24, 2 -ANN00049, 9,30NE_ANN ,0.35,0.35, 2 -ANN00050, 9,40NE_ANN ,0.47,0.47, 2 -ANN00051, 9,50NE_ANN ,0.59,0.59, 2 -ANN00052, 9,60NE_ANN ,0.71,0.71, 2 -ANN00053, 9,70NE_ANN ,0.82,0.82, 2 -ANN00054, 9,80NE_ANN ,0.94,0.94, 2 -ANN00055, 9,90NE_ANN ,1.06,1.06, 2 -ANN00056, 9,100NE_ANN ,1.18,1.18, 2 -ANN00057, 9,110NE_ANN ,1.30,1.30, 2 -ANN00058, 9,120NE_ANN ,1.41,1.41, 2 -ANN00059, 9,130NE_ANN ,1.53,1.53, 2 -ANN00060, 9,140NE_ANN ,1.65,1.65, 2 -ANN00061, 9,150NE_ANN ,1.77,1.77, 2 -ANN00062, 9,160NE_ANN ,1.88,1.88, 2 -ANN00063, 9,170NE_ANN ,2.00,2.00, 2 -ANN00064, 9,180NE_ANN ,2.12,2.12, 2 -ANN00065, 9,190NE_ANN ,2.24,2.24, 2 -ANN00066, 9,200NE_ANN ,2.35,2.36, 2 -ANN00067, 9,210NE_ANN ,2.47,2.47, 2 -ANN00068, 9,220NE_ANN ,2.59,2.59, 2 -ANN00069, 9,230NE_ANN ,2.71,2.71, 2 -ANN00070, 9,240NE_ANN ,2.83,2.83, 2 -ANN00071, 9,250NE_ANN ,2.94,2.95, 2 -ANN00072, 9,20NW_ANN ,0.24,-0.24, 2 -ANN00073, 9,30NW_ANN ,0.35,-0.35, 2 -ANN00074, 9,40NW_ANN ,0.47,-0.47, 2 -ANN00075, 9,50NW_ANN ,0.59,-0.59, 2 -ANN00076, 9,60NW_ANN ,0.71,-0.71, 2 -ANN00077, 9,70NW_ANN ,0.82,-0.82, 2 -ANN00078, 9,80NW_ANN ,0.94,-0.94, 2 -ANN00079, 9,90NW_ANN ,1.06,-1.06, 2 -ANN00080, 9,100NW_ANN ,1.18,-1.18, 2 -ANN00081, 9,110NW_ANN ,1.30,-1.30, 2 -ANN00082, 9,120NW_ANN ,1.41,-1.41, 2 -ANN00083, 9,130NW_ANN ,1.53,-1.53, 2 -ANN00084, 9,140NW_ANN ,1.65,-1.65, 2 -ANN00085, 9,150NW_ANN ,1.77,-1.77, 2 -ANN00086, 9,160NW_ANN ,1.88,-1.88, 2 -ANN00087, 9,170NW_ANN ,2.00,-2.00, 2 -ANN00088, 9,180NW_ANN ,2.12,-2.12, 2 -ANN00089, 9,190NW_ANN ,2.24,-2.24, 2 -ANN00090, 9,200NW_ANN ,2.35,-2.36, 2 -ANN00091, 9,210NW_ANN ,2.47,-2.47, 2 -ANN00092, 9,220NW_ANN ,2.59,-2.59, 2 -ANN00093, 9,230NW_ANN ,2.71,-2.71, 2 -ANN00094, 9,240NW_ANN ,2.83,-2.83, 2 -ANN00095, 9,250NW_ANN ,2.94,-2.95, 2 -ANN00096, 9,20NNW_ANN ,0.31,-0.13, 2 -ANN00097, 9,30NNW_ANN ,0.46,-0.19, 2 -ANN00098, 9,40NNW_ANN ,0.62,-0.25, 2 -ANN00099, 9,50NNW_ANN ,0.77,-0.32, 2 -ANN00100, 9,60NNW_ANN ,0.92,-0.38, 2 -ANN00101, 9,70NNW_ANN ,1.08,-0.45, 2 -ANN00102, 9,80NNW_ANN ,1.23,-0.51, 2 -ANN00103, 9,90NNW_ANN ,1.38,-0.57, 2 -ANN00104, 9,100NNW_ANN ,1.54,-0.64, 2 -ANN00105, 9,110NNW_ANN ,1.69,-0.70, 2 -ANN00106, 9,120NNW_ANN ,1.85,-0.77, 2 -ANN00107, 9,130NNW_ANN ,2.00,-0.83, 2 -ANN00108, 9,140NNW_ANN ,2.15,-0.89, 2 -ANN00109, 9,150NNW_ANN ,2.31,-0.96, 2 -ANN00110, 9,160NNW_ANN ,2.46,-1.02, 2 -ANN00111, 9,170NNW_ANN ,2.62,-1.08, 2 -ANN00112, 9,180NNW_ANN ,2.77,-1.15, 2 -ANN00113, 9,190NNW_ANN ,2.92,-1.21, 2 -ANN00114, 9,200NNW_ANN ,3.08,-1.28, 2 -ANN00115, 9,210NNW_ANN ,3.23,-1.34, 2 -ANN00116, 9,220NNW_ANN ,3.38,-1.40, 2 -ANN00117, 9,230NNW_ANN ,3.54,-1.47, 2 -ANN00118, 9,240NNW_ANN ,3.69,-1.53, 2 -LVD00000, 9,LVD ,0.00,0.00, 1 -LVD00001, 9,20N_LVD ,0.33,0.00, 2 -LVD00002, 9,30N_LVD ,0.50,0.00, 2 -LVD00003, 9,40N_LVD ,0.67,0.00, 2 -LVD00004, 9,50N_LVD ,0.83,0.00, 2 -LVD00005, 9,60N_LVD ,1.00,0.00, 2 -LVD00006, 9,70N_LVD ,1.17,0.00, 2 -LVD00007, 9,80N_LVD ,1.33,0.00, 2 -LVD00008, 9,90N_LVD ,1.50,0.00, 2 -LVD00009, 9,100N_LVD ,1.67,0.00, 2 -LVD00010, 9,110N_LVD ,1.83,0.00, 2 -LVD00011, 9,120N_LVD ,2.00,0.00, 2 -LVD00012, 9,130N_LVD ,2.17,0.00, 2 -LVD00013, 9,140N_LVD ,2.33,0.00, 2 -LVD00014, 9,150N_LVD ,2.50,0.00, 2 -LVD00015, 9,160N_LVD ,2.66,0.00, 2 -LVD00016, 9,170N_LVD ,2.83,0.00, 2 -LVD00017, 9,180N_LVD ,3.00,0.00, 2 -LVD00018, 9,190N_LVD ,3.16,0.00, 2 -LVD00019, 9,200N_LVD ,3.33,0.00, 2 -LVD00020, 9,210N_LVD ,3.50,0.00, 2 -LVD00021, 9,220N_LVD ,3.66,0.00, 2 -LVD00022, 9,230N_LVD ,3.83,0.00, 2 -LVD00023, 9,240N_LVD ,4.00,0.00, 2 -LVD00024, 9,250N_LVD ,4.16,0.00, 2 -LVD00025, 9,20NNE_LVD ,0.31,0.13, 2 -LVD00026, 9,30NNE_LVD ,0.46,0.19, 2 -LVD00027, 9,40NNE_LVD ,0.62,0.25, 2 -LVD00028, 9,50NNE_LVD ,0.77,0.32, 2 -LVD00029, 9,60NNE_LVD ,0.92,0.38, 2 -LVD00030, 9,70NNE_LVD ,1.08,0.45, 2 -LVD00031, 9,80NNE_LVD ,1.23,0.51, 2 -LVD00032, 9,90NNE_LVD ,1.38,0.57, 2 -LVD00033, 9,100NNE_LVD ,1.54,0.64, 2 -LVD00034, 9,110NNE_LVD ,1.69,0.70, 2 -LVD00035, 9,120NNE_LVD ,1.85,0.77, 2 -LVD00036, 9,130NNE_LVD ,2.00,0.83, 2 -LVD00037, 9,140NNE_LVD ,2.15,0.89, 2 -LVD00038, 9,150NNE_LVD ,2.31,0.96, 2 -LVD00039, 9,160NNE_LVD ,2.46,1.02, 2 -LVD00040, 9,170NNE_LVD ,2.62,1.08, 2 -LVD00041, 9,180NNE_LVD ,2.77,1.15, 2 -LVD00042, 9,190NNE_LVD ,2.92,1.21, 2 -LVD00043, 9,200NNE_LVD ,3.08,1.28, 2 -LVD00044, 9,210NNE_LVD ,3.23,1.34, 2 -LVD00045, 9,220NNE_LVD ,3.38,1.40, 2 -LVD00046, 9,230NNE_LVD ,3.54,1.47, 2 -LVD00047, 9,240NNE_LVD ,3.69,1.53, 2 -LVD00048, 9,20NE_LVD ,0.24,0.24, 2 -LVD00049, 9,30NE_LVD ,0.35,0.35, 2 -LVD00050, 9,40NE_LVD ,0.47,0.47, 2 -LVD00051, 9,50NE_LVD ,0.59,0.59, 2 -LVD00052, 9,60NE_LVD ,0.71,0.71, 2 -LVD00053, 9,70NE_LVD ,0.82,0.82, 2 -LVD00054, 9,80NE_LVD ,0.94,0.94, 2 -LVD00055, 9,90NE_LVD ,1.06,1.06, 2 -LVD00056, 9,100NE_LVD ,1.18,1.18, 2 -LVD00057, 9,110NE_LVD ,1.30,1.30, 2 -LVD00058, 9,120NE_LVD ,1.41,1.41, 2 -LVD00059, 9,130NE_LVD ,1.53,1.53, 2 -LVD00060, 9,140NE_LVD ,1.65,1.65, 2 -LVD00061, 9,150NE_LVD ,1.77,1.77, 2 -LVD00062, 9,160NE_LVD ,1.88,1.88, 2 -LVD00063, 9,170NE_LVD ,2.00,2.00, 2 -LVD00064, 9,180NE_LVD ,2.12,2.12, 2 -LVD00065, 9,190NE_LVD ,2.24,2.24, 2 -LVD00066, 9,200NE_LVD ,2.35,2.36, 2 -LVD00067, 9,210NE_LVD ,2.47,2.47, 2 -LVD00068, 9,220NE_LVD ,2.59,2.59, 2 -LVD00069, 9,230NE_LVD ,2.71,2.71, 2 -LVD00070, 9,240NE_LVD ,2.83,2.83, 2 -LVD00071, 9,250NE_LVD ,2.94,2.95, 2 -LVD00072, 9,20NW_LVD ,0.24,-0.24, 2 -LVD00073, 9,30NW_LVD ,0.35,-0.35, 2 -LVD00074, 9,40NW_LVD ,0.47,-0.47, 2 -LVD00075, 9,50NW_LVD ,0.59,-0.59, 2 -LVD00076, 9,60NW_LVD ,0.71,-0.71, 2 -LVD00077, 9,70NW_LVD ,0.82,-0.82, 2 -LVD00078, 9,80NW_LVD ,0.94,-0.94, 2 -LVD00079, 9,90NW_LVD ,1.06,-1.06, 2 -LVD00080, 9,100NW_LVD ,1.18,-1.18, 2 -LVD00081, 9,110NW_LVD ,1.30,-1.30, 2 -LVD00082, 9,120NW_LVD ,1.41,-1.41, 2 -LVD00083, 9,130NW_LVD ,1.53,-1.53, 2 -LVD00084, 9,140NW_LVD ,1.65,-1.65, 2 -LVD00085, 9,150NW_LVD ,1.77,-1.77, 2 -LVD00086, 9,160NW_LVD ,1.88,-1.88, 2 -LVD00087, 9,170NW_LVD ,2.00,-2.00, 2 -LVD00088, 9,180NW_LVD ,2.12,-2.12, 2 -LVD00089, 9,190NW_LVD ,2.24,-2.24, 2 -LVD00090, 9,200NW_LVD ,2.35,-2.36, 2 -LVD00091, 9,210NW_LVD ,2.47,-2.47, 2 -LVD00092, 9,220NW_LVD ,2.59,-2.59, 2 -LVD00093, 9,230NW_LVD ,2.71,-2.71, 2 -LVD00094, 9,240NW_LVD ,2.83,-2.83, 2 -LVD00095, 9,250NW_LVD ,2.94,-2.95, 2 -LVD00096, 9,20NNW_LVD ,0.31,-0.13, 2 -LVD00097, 9,30NNW_LVD ,0.46,-0.19, 2 -LVD00098, 9,40NNW_LVD ,0.62,-0.25, 2 -LVD00099, 9,50NNW_LVD ,0.77,-0.32, 2 -LVD00100, 9,60NNW_LVD ,0.92,-0.38, 2 -LVD00101, 9,70NNW_LVD ,1.08,-0.45, 2 -LVD00102, 9,80NNW_LVD ,1.23,-0.51, 2 -LVD00103, 9,90NNW_LVD ,1.38,-0.57, 2 -LVD00104, 9,100NNW_LVD ,1.54,-0.64, 2 -LVD00105, 9,110NNW_LVD ,1.69,-0.70, 2 -LVD00106, 9,120NNW_LVD ,1.85,-0.77, 2 -LVD00107, 9,130NNW_LVD ,2.00,-0.83, 2 -LVD00108, 9,140NNW_LVD ,2.15,-0.89, 2 -LVD00109, 9,150NNW_LVD ,2.31,-0.96, 2 -LVD00110, 9,160NNW_LVD ,2.46,-1.02, 2 -LVD00111, 9,170NNW_LVD ,2.62,-1.08, 2 -LVD00112, 9,180NNW_LVD ,2.77,-1.15, 2 -LVD00113, 9,190NNW_LVD ,2.92,-1.21, 2 -LVD00114, 9,200NNW_LVD ,3.08,-1.28, 2 -LVD00115, 9,210NNW_LVD ,3.23,-1.34, 2 -LVD00116, 9,220NNW_LVD ,3.38,-1.40, 2 -LVD00117, 9,230NNW_LVD ,3.54,-1.47, 2 -LVD00118, 9,240NNW_LVD ,3.69,-1.53, 2 -BKA00000, 9,BKA ,0.00,0.00, 1 -BKA00001, 9,20N_BKA ,0.33,0.00, 2 -BKA00002, 9,30N_BKA ,0.50,0.00, 2 -BKA00003, 9,40N_BKA ,0.67,0.00, 2 -BKA00004, 9,50N_BKA ,0.83,0.00, 2 -BKA00005, 9,60N_BKA ,1.00,0.00, 2 -BKA00006, 9,70N_BKA ,1.17,0.00, 2 -BKA00007, 9,80N_BKA ,1.33,0.00, 2 -BKA00008, 9,90N_BKA ,1.50,0.00, 2 -BKA00009, 9,100N_BKA ,1.67,0.00, 2 -BKA00010, 9,110N_BKA ,1.83,0.00, 2 -BKA00011, 9,120N_BKA ,2.00,0.00, 2 -BKA00012, 9,130N_BKA ,2.17,0.00, 2 -BKA00013, 9,140N_BKA ,2.33,0.00, 2 -BKA00014, 9,150N_BKA ,2.50,0.00, 2 -BKA00015, 9,160N_BKA ,2.66,0.00, 2 -BKA00016, 9,170N_BKA ,2.83,0.00, 2 -BKA00017, 9,180N_BKA ,3.00,0.00, 2 -BKA00018, 9,190N_BKA ,3.16,0.00, 2 -BKA00019, 9,200N_BKA ,3.33,0.00, 2 -BKA00020, 9,210N_BKA ,3.50,0.00, 2 -BKA00021, 9,220N_BKA ,3.66,0.00, 2 -BKA00022, 9,230N_BKA ,3.83,0.00, 2 -BKA00023, 9,240N_BKA ,4.00,0.00, 2 -BKA00024, 9,250N_BKA ,4.16,0.00, 2 -BKA00025, 9,20NNE_BKA ,0.31,0.13, 2 -BKA00026, 9,30NNE_BKA ,0.46,0.19, 2 -BKA00027, 9,40NNE_BKA ,0.62,0.25, 2 -BKA00028, 9,50NNE_BKA ,0.77,0.32, 2 -BKA00029, 9,60NNE_BKA ,0.92,0.38, 2 -BKA00030, 9,70NNE_BKA ,1.08,0.45, 2 -BKA00031, 9,80NNE_BKA ,1.23,0.51, 2 -BKA00032, 9,90NNE_BKA ,1.38,0.57, 2 -BKA00033, 9,100NNE_BKA ,1.54,0.64, 2 -BKA00034, 9,110NNE_BKA ,1.69,0.70, 2 -BKA00035, 9,120NNE_BKA ,1.85,0.77, 2 -BKA00036, 9,130NNE_BKA ,2.00,0.83, 2 -BKA00037, 9,140NNE_BKA ,2.15,0.89, 2 -BKA00038, 9,150NNE_BKA ,2.31,0.96, 2 -BKA00039, 9,160NNE_BKA ,2.46,1.02, 2 -BKA00040, 9,170NNE_BKA ,2.62,1.08, 2 -BKA00041, 9,180NNE_BKA ,2.77,1.15, 2 -BKA00042, 9,190NNE_BKA ,2.92,1.21, 2 -BKA00043, 9,200NNE_BKA ,3.08,1.28, 2 -BKA00044, 9,210NNE_BKA ,3.23,1.34, 2 -BKA00045, 9,220NNE_BKA ,3.38,1.40, 2 -BKA00046, 9,230NNE_BKA ,3.54,1.47, 2 -BKA00047, 9,240NNE_BKA ,3.69,1.53, 2 -BKA00048, 9,20NE_BKA ,0.24,0.24, 2 -BKA00049, 9,30NE_BKA ,0.35,0.35, 2 -BKA00050, 9,40NE_BKA ,0.47,0.47, 2 -BKA00051, 9,50NE_BKA ,0.59,0.59, 2 -BKA00052, 9,60NE_BKA ,0.71,0.71, 2 -BKA00053, 9,70NE_BKA ,0.82,0.82, 2 -BKA00054, 9,80NE_BKA ,0.94,0.94, 2 -BKA00055, 9,90NE_BKA ,1.06,1.06, 2 -BKA00056, 9,100NE_BKA ,1.18,1.18, 2 -BKA00057, 9,110NE_BKA ,1.30,1.30, 2 -BKA00058, 9,120NE_BKA ,1.41,1.41, 2 -BKA00059, 9,130NE_BKA ,1.53,1.53, 2 -BKA00060, 9,140NE_BKA ,1.65,1.65, 2 -BKA00061, 9,150NE_BKA ,1.77,1.77, 2 -BKA00062, 9,160NE_BKA ,1.88,1.88, 2 -BKA00063, 9,170NE_BKA ,2.00,2.00, 2 -BKA00064, 9,180NE_BKA ,2.12,2.12, 2 -BKA00065, 9,190NE_BKA ,2.24,2.24, 2 -BKA00066, 9,200NE_BKA ,2.35,2.36, 2 -BKA00067, 9,210NE_BKA ,2.47,2.47, 2 -BKA00068, 9,220NE_BKA ,2.59,2.59, 2 -BKA00069, 9,230NE_BKA ,2.71,2.71, 2 -BKA00070, 9,240NE_BKA ,2.83,2.83, 2 -BKA00071, 9,250NE_BKA ,2.94,2.95, 2 -BKA00072, 9,20NW_BKA ,0.24,-0.24, 2 -BKA00073, 9,30NW_BKA ,0.35,-0.35, 2 -BKA00074, 9,40NW_BKA ,0.47,-0.47, 2 -BKA00075, 9,50NW_BKA ,0.59,-0.59, 2 -BKA00076, 9,60NW_BKA ,0.71,-0.71, 2 -BKA00077, 9,70NW_BKA ,0.82,-0.82, 2 -BKA00078, 9,80NW_BKA ,0.94,-0.94, 2 -BKA00079, 9,90NW_BKA ,1.06,-1.06, 2 -BKA00080, 9,100NW_BKA ,1.18,-1.18, 2 -BKA00081, 9,110NW_BKA ,1.30,-1.30, 2 -BKA00082, 9,120NW_BKA ,1.41,-1.41, 2 -BKA00083, 9,130NW_BKA ,1.53,-1.53, 2 -BKA00084, 9,140NW_BKA ,1.65,-1.65, 2 -BKA00085, 9,150NW_BKA ,1.77,-1.77, 2 -BKA00086, 9,160NW_BKA ,1.88,-1.88, 2 -BKA00087, 9,170NW_BKA ,2.00,-2.00, 2 -BKA00088, 9,180NW_BKA ,2.12,-2.12, 2 -BKA00089, 9,190NW_BKA ,2.24,-2.24, 2 -BKA00090, 9,200NW_BKA ,2.35,-2.36, 2 -BKA00091, 9,210NW_BKA ,2.47,-2.47, 2 -BKA00092, 9,220NW_BKA ,2.59,-2.59, 2 -BKA00093, 9,230NW_BKA ,2.71,-2.71, 2 -BKA00094, 9,240NW_BKA ,2.83,-2.83, 2 -BKA00095, 9,250NW_BKA ,2.94,-2.95, 2 -BKA00096, 9,20NNW_BKA ,0.31,-0.13, 2 -BKA00097, 9,30NNW_BKA ,0.46,-0.19, 2 -BKA00098, 9,40NNW_BKA ,0.62,-0.25, 2 -BKA00099, 9,50NNW_BKA ,0.77,-0.32, 2 -BKA00100, 9,60NNW_BKA ,0.92,-0.38, 2 -BKA00101, 9,70NNW_BKA ,1.08,-0.45, 2 -BKA00102, 9,80NNW_BKA ,1.23,-0.51, 2 -BKA00103, 9,90NNW_BKA ,1.38,-0.57, 2 -BKA00104, 9,100NNW_BKA ,1.54,-0.64, 2 -BKA00105, 9,110NNW_BKA ,1.69,-0.70, 2 -BKA00106, 9,120NNW_BKA ,1.85,-0.77, 2 -BKA00107, 9,130NNW_BKA ,2.00,-0.83, 2 -BKA00108, 9,140NNW_BKA ,2.15,-0.89, 2 -BKA00109, 9,150NNW_BKA ,2.31,-0.96, 2 -BKA00110, 9,160NNW_BKA ,2.46,-1.02, 2 -BKA00111, 9,170NNW_BKA ,2.62,-1.08, 2 -BKA00112, 9,180NNW_BKA ,2.77,-1.15, 2 -BKA00113, 9,190NNW_BKA ,2.92,-1.21, 2 -BKA00114, 9,200NNW_BKA ,3.08,-1.28, 2 -BKA00115, 9,210NNW_BKA ,3.23,-1.34, 2 -BKA00116, 9,220NNW_BKA ,3.38,-1.40, 2 -BKA00117, 9,230NNW_BKA ,3.54,-1.47, 2 -BKA00118, 9,240NNW_BKA ,3.69,-1.53, 2 -SSR00000, 9,SSR ,0.00,0.00, 1 -SSR00001, 9,20N_SSR ,0.33,0.00, 2 -SSR00002, 9,30N_SSR ,0.50,0.00, 2 -SSR00003, 9,40N_SSR ,0.67,0.00, 2 -SSR00004, 9,50N_SSR ,0.83,0.00, 2 -SSR00005, 9,60N_SSR ,1.00,0.00, 2 -SSR00006, 9,70N_SSR ,1.17,0.00, 2 -SSR00007, 9,80N_SSR ,1.33,0.00, 2 -SSR00008, 9,90N_SSR ,1.50,0.00, 2 -SSR00009, 9,100N_SSR ,1.67,0.00, 2 -SSR00010, 9,110N_SSR ,1.83,0.00, 2 -SSR00011, 9,120N_SSR ,2.00,0.00, 2 -SSR00012, 9,130N_SSR ,2.17,0.00, 2 -SSR00013, 9,140N_SSR ,2.33,0.00, 2 -SSR00014, 9,150N_SSR ,2.50,0.00, 2 -SSR00015, 9,160N_SSR ,2.66,0.00, 2 -SSR00016, 9,170N_SSR ,2.83,0.00, 2 -SSR00017, 9,180N_SSR ,3.00,0.00, 2 -SSR00018, 9,190N_SSR ,3.16,0.00, 2 -SSR00019, 9,200N_SSR ,3.33,0.00, 2 -SSR00020, 9,210N_SSR ,3.50,0.00, 2 -SSR00021, 9,220N_SSR ,3.66,0.00, 2 -SSR00022, 9,230N_SSR ,3.83,0.00, 2 -SSR00023, 9,240N_SSR ,4.00,0.00, 2 -SSR00024, 9,250N_SSR ,4.16,0.00, 2 -SSR00025, 9,20NNE_SSR ,0.31,0.13, 2 -SSR00026, 9,30NNE_SSR ,0.46,0.19, 2 -SSR00027, 9,40NNE_SSR ,0.62,0.25, 2 -SSR00028, 9,50NNE_SSR ,0.77,0.32, 2 -SSR00029, 9,60NNE_SSR ,0.92,0.38, 2 -SSR00030, 9,70NNE_SSR ,1.08,0.45, 2 -SSR00031, 9,80NNE_SSR ,1.23,0.51, 2 -SSR00032, 9,90NNE_SSR ,1.38,0.57, 2 -SSR00033, 9,100NNE_SSR ,1.54,0.64, 2 -SSR00034, 9,110NNE_SSR ,1.69,0.70, 2 -SSR00035, 9,120NNE_SSR ,1.85,0.77, 2 -SSR00036, 9,130NNE_SSR ,2.00,0.83, 2 -SSR00037, 9,140NNE_SSR ,2.15,0.89, 2 -SSR00038, 9,150NNE_SSR ,2.31,0.96, 2 -SSR00039, 9,160NNE_SSR ,2.46,1.02, 2 -SSR00040, 9,170NNE_SSR ,2.62,1.08, 2 -SSR00041, 9,180NNE_SSR ,2.77,1.15, 2 -SSR00042, 9,190NNE_SSR ,2.92,1.21, 2 -SSR00043, 9,200NNE_SSR ,3.08,1.28, 2 -SSR00044, 9,210NNE_SSR ,3.23,1.34, 2 -SSR00045, 9,220NNE_SSR ,3.38,1.40, 2 -SSR00046, 9,230NNE_SSR ,3.54,1.47, 2 -SSR00047, 9,240NNE_SSR ,3.69,1.53, 2 -SSR00048, 9,20NE_SSR ,0.24,0.24, 2 -SSR00049, 9,30NE_SSR ,0.35,0.35, 2 -SSR00050, 9,40NE_SSR ,0.47,0.47, 2 -SSR00051, 9,50NE_SSR ,0.59,0.59, 2 -SSR00052, 9,60NE_SSR ,0.71,0.71, 2 -SSR00053, 9,70NE_SSR ,0.82,0.82, 2 -SSR00054, 9,80NE_SSR ,0.94,0.94, 2 -SSR00055, 9,90NE_SSR ,1.06,1.06, 2 -SSR00056, 9,100NE_SSR ,1.18,1.18, 2 -SSR00057, 9,110NE_SSR ,1.30,1.30, 2 -SSR00058, 9,120NE_SSR ,1.41,1.41, 2 -SSR00059, 9,130NE_SSR ,1.53,1.53, 2 -SSR00060, 9,140NE_SSR ,1.65,1.65, 2 -SSR00061, 9,150NE_SSR ,1.77,1.77, 2 -SSR00062, 9,160NE_SSR ,1.88,1.88, 2 -SSR00063, 9,170NE_SSR ,2.00,2.00, 2 -SSR00064, 9,180NE_SSR ,2.12,2.12, 2 -SSR00065, 9,190NE_SSR ,2.24,2.24, 2 -SSR00066, 9,200NE_SSR ,2.35,2.36, 2 -SSR00067, 9,210NE_SSR ,2.47,2.47, 2 -SSR00068, 9,220NE_SSR ,2.59,2.59, 2 -SSR00069, 9,230NE_SSR ,2.71,2.71, 2 -SSR00070, 9,240NE_SSR ,2.83,2.83, 2 -SSR00071, 9,250NE_SSR ,2.94,2.95, 2 -SSR00072, 9,20NW_SSR ,0.24,-0.24, 2 -SSR00073, 9,30NW_SSR ,0.35,-0.35, 2 -SSR00074, 9,40NW_SSR ,0.47,-0.47, 2 -SSR00075, 9,50NW_SSR ,0.59,-0.59, 2 -SSR00076, 9,60NW_SSR ,0.71,-0.71, 2 -SSR00077, 9,70NW_SSR ,0.82,-0.82, 2 -SSR00078, 9,80NW_SSR ,0.94,-0.94, 2 -SSR00079, 9,90NW_SSR ,1.06,-1.06, 2 -SSR00080, 9,100NW_SSR ,1.18,-1.18, 2 -SSR00081, 9,110NW_SSR ,1.30,-1.30, 2 -SSR00082, 9,120NW_SSR ,1.41,-1.41, 2 -SSR00083, 9,130NW_SSR ,1.53,-1.53, 2 -SSR00084, 9,140NW_SSR ,1.65,-1.65, 2 -SSR00085, 9,150NW_SSR ,1.77,-1.77, 2 -SSR00086, 9,160NW_SSR ,1.88,-1.88, 2 -SSR00087, 9,170NW_SSR ,2.00,-2.00, 2 -SSR00088, 9,180NW_SSR ,2.12,-2.12, 2 -SSR00089, 9,190NW_SSR ,2.24,-2.24, 2 -SSR00090, 9,200NW_SSR ,2.35,-2.36, 2 -SSR00091, 9,210NW_SSR ,2.47,-2.47, 2 -SSR00092, 9,220NW_SSR ,2.59,-2.59, 2 -SSR00093, 9,230NW_SSR ,2.71,-2.71, 2 -SSR00094, 9,240NW_SSR ,2.83,-2.83, 2 -SSR00095, 9,250NW_SSR ,2.94,-2.95, 2 -SSR00096, 9,20NNW_SSR ,0.31,-0.13, 2 -SSR00097, 9,30NNW_SSR ,0.46,-0.19, 2 -SSR00098, 9,40NNW_SSR ,0.62,-0.25, 2 -SSR00099, 9,50NNW_SSR ,0.77,-0.32, 2 -SSR00100, 9,60NNW_SSR ,0.92,-0.38, 2 -SSR00101, 9,70NNW_SSR ,1.08,-0.45, 2 -SSR00102, 9,80NNW_SSR ,1.23,-0.51, 2 -SSR00103, 9,90NNW_SSR ,1.38,-0.57, 2 -SSR00104, 9,100NNW_SSR ,1.54,-0.64, 2 -SSR00105, 9,110NNW_SSR ,1.69,-0.70, 2 -SSR00106, 9,120NNW_SSR ,1.85,-0.77, 2 -SSR00107, 9,130NNW_SSR ,2.00,-0.83, 2 -SSR00108, 9,140NNW_SSR ,2.15,-0.89, 2 -SSR00109, 9,150NNW_SSR ,2.31,-0.96, 2 -SSR00110, 9,160NNW_SSR ,2.46,-1.02, 2 -SSR00111, 9,170NNW_SSR ,2.62,-1.08, 2 -SSR00112, 9,180NNW_SSR ,2.77,-1.15, 2 -SSR00113, 9,190NNW_SSR ,2.92,-1.21, 2 -SSR00114, 9,200NNW_SSR ,3.08,-1.28, 2 -SSR00115, 9,210NNW_SSR ,3.23,-1.34, 2 -SSR00116, 9,220NNW_SSR ,3.38,-1.40, 2 -SSR00117, 9,230NNW_SSR ,3.54,-1.47, 2 -SSR00118, 9,240NNW_SSR ,3.69,-1.53, 2 -JNU00000, 9,JNU ,0.00,0.00, 1 -JNU00001, 9,20N_JNU ,0.33,0.00, 2 -JNU00002, 9,30N_JNU ,0.50,0.00, 2 -JNU00003, 9,40N_JNU ,0.67,0.00, 2 -JNU00004, 9,50N_JNU ,0.83,0.00, 2 -JNU00005, 9,60N_JNU ,1.00,0.00, 2 -JNU00006, 9,70N_JNU ,1.17,0.00, 2 -JNU00007, 9,80N_JNU ,1.33,0.00, 2 -JNU00008, 9,90N_JNU ,1.50,0.00, 2 -JNU00009, 9,100N_JNU ,1.67,0.00, 2 -JNU00010, 9,110N_JNU ,1.83,0.00, 2 -JNU00011, 9,120N_JNU ,2.00,0.00, 2 -JNU00012, 9,130N_JNU ,2.17,0.00, 2 -JNU00013, 9,140N_JNU ,2.33,0.00, 2 -JNU00014, 9,150N_JNU ,2.50,0.00, 2 -JNU00015, 9,160N_JNU ,2.66,0.00, 2 -JNU00016, 9,170N_JNU ,2.83,0.00, 2 -JNU00017, 9,180N_JNU ,3.00,0.00, 2 -JNU00018, 9,190N_JNU ,3.16,0.00, 2 -JNU00019, 9,200N_JNU ,3.33,0.00, 2 -JNU00020, 9,210N_JNU ,3.50,0.00, 2 -JNU00021, 9,220N_JNU ,3.66,0.00, 2 -JNU00022, 9,230N_JNU ,3.83,0.00, 2 -JNU00023, 9,240N_JNU ,4.00,0.00, 2 -JNU00024, 9,250N_JNU ,4.16,0.00, 2 -JNU00025, 9,20NNE_JNU ,0.31,0.13, 2 -JNU00026, 9,30NNE_JNU ,0.46,0.19, 2 -JNU00027, 9,40NNE_JNU ,0.62,0.25, 2 -JNU00028, 9,50NNE_JNU ,0.77,0.32, 2 -JNU00029, 9,60NNE_JNU ,0.92,0.38, 2 -JNU00030, 9,70NNE_JNU ,1.08,0.45, 2 -JNU00031, 9,80NNE_JNU ,1.23,0.51, 2 -JNU00032, 9,90NNE_JNU ,1.38,0.57, 2 -JNU00033, 9,100NNE_JNU ,1.54,0.64, 2 -JNU00034, 9,110NNE_JNU ,1.69,0.70, 2 -JNU00035, 9,120NNE_JNU ,1.85,0.77, 2 -JNU00036, 9,130NNE_JNU ,2.00,0.83, 2 -JNU00037, 9,140NNE_JNU ,2.15,0.89, 2 -JNU00038, 9,150NNE_JNU ,2.31,0.96, 2 -JNU00039, 9,160NNE_JNU ,2.46,1.02, 2 -JNU00040, 9,170NNE_JNU ,2.62,1.08, 2 -JNU00041, 9,180NNE_JNU ,2.77,1.15, 2 -JNU00042, 9,190NNE_JNU ,2.92,1.21, 2 -JNU00043, 9,200NNE_JNU ,3.08,1.28, 2 -JNU00044, 9,210NNE_JNU ,3.23,1.34, 2 -JNU00045, 9,220NNE_JNU ,3.38,1.40, 2 -JNU00046, 9,230NNE_JNU ,3.54,1.47, 2 -JNU00047, 9,240NNE_JNU ,3.69,1.53, 2 -JNU00048, 9,20NE_JNU ,0.24,0.24, 2 -JNU00049, 9,30NE_JNU ,0.35,0.35, 2 -JNU00050, 9,40NE_JNU ,0.47,0.47, 2 -JNU00051, 9,50NE_JNU ,0.59,0.59, 2 -JNU00052, 9,60NE_JNU ,0.71,0.71, 2 -JNU00053, 9,70NE_JNU ,0.82,0.82, 2 -JNU00054, 9,80NE_JNU ,0.94,0.94, 2 -JNU00055, 9,90NE_JNU ,1.06,1.06, 2 -JNU00056, 9,100NE_JNU ,1.18,1.18, 2 -JNU00057, 9,110NE_JNU ,1.30,1.30, 2 -JNU00058, 9,120NE_JNU ,1.41,1.41, 2 -JNU00059, 9,130NE_JNU ,1.53,1.53, 2 -JNU00060, 9,140NE_JNU ,1.65,1.65, 2 -JNU00061, 9,150NE_JNU ,1.77,1.77, 2 -JNU00062, 9,160NE_JNU ,1.88,1.88, 2 -JNU00063, 9,170NE_JNU ,2.00,2.00, 2 -JNU00064, 9,180NE_JNU ,2.12,2.12, 2 -JNU00065, 9,190NE_JNU ,2.24,2.24, 2 -JNU00066, 9,200NE_JNU ,2.35,2.36, 2 -JNU00067, 9,210NE_JNU ,2.47,2.47, 2 -JNU00068, 9,220NE_JNU ,2.59,2.59, 2 -JNU00069, 9,230NE_JNU ,2.71,2.71, 2 -JNU00070, 9,240NE_JNU ,2.83,2.83, 2 -JNU00071, 9,250NE_JNU ,2.94,2.95, 2 -JNU00072, 9,20NW_JNU ,0.24,-0.24, 2 -JNU00073, 9,30NW_JNU ,0.35,-0.35, 2 -JNU00074, 9,40NW_JNU ,0.47,-0.47, 2 -JNU00075, 9,50NW_JNU ,0.59,-0.59, 2 -JNU00076, 9,60NW_JNU ,0.71,-0.71, 2 -JNU00077, 9,70NW_JNU ,0.82,-0.82, 2 -JNU00078, 9,80NW_JNU ,0.94,-0.94, 2 -JNU00079, 9,90NW_JNU ,1.06,-1.06, 2 -JNU00080, 9,100NW_JNU ,1.18,-1.18, 2 -JNU00081, 9,110NW_JNU ,1.30,-1.30, 2 -JNU00082, 9,120NW_JNU ,1.41,-1.41, 2 -JNU00083, 9,130NW_JNU ,1.53,-1.53, 2 -JNU00084, 9,140NW_JNU ,1.65,-1.65, 2 -JNU00085, 9,150NW_JNU ,1.77,-1.77, 2 -JNU00086, 9,160NW_JNU ,1.88,-1.88, 2 -JNU00087, 9,170NW_JNU ,2.00,-2.00, 2 -JNU00088, 9,180NW_JNU ,2.12,-2.12, 2 -JNU00089, 9,190NW_JNU ,2.24,-2.24, 2 -JNU00090, 9,200NW_JNU ,2.35,-2.36, 2 -JNU00091, 9,210NW_JNU ,2.47,-2.47, 2 -JNU00092, 9,220NW_JNU ,2.59,-2.59, 2 -JNU00093, 9,230NW_JNU ,2.71,-2.71, 2 -JNU00094, 9,240NW_JNU ,2.83,-2.83, 2 -JNU00095, 9,250NW_JNU ,2.94,-2.95, 2 -JNU00096, 9,20NNW_JNU ,0.31,-0.13, 2 -JNU00097, 9,30NNW_JNU ,0.46,-0.19, 2 -JNU00098, 9,40NNW_JNU ,0.62,-0.25, 2 -JNU00099, 9,50NNW_JNU ,0.77,-0.32, 2 -JNU00100, 9,60NNW_JNU ,0.92,-0.38, 2 -JNU00101, 9,70NNW_JNU ,1.08,-0.45, 2 -JNU00102, 9,80NNW_JNU ,1.23,-0.51, 2 -JNU00103, 9,90NNW_JNU ,1.38,-0.57, 2 -JNU00104, 9,100NNW_JNU ,1.54,-0.64, 2 -JNU00105, 9,110NNW_JNU ,1.69,-0.70, 2 -JNU00106, 9,120NNW_JNU ,1.85,-0.77, 2 -JNU00107, 9,130NNW_JNU ,2.00,-0.83, 2 -JNU00108, 9,140NNW_JNU ,2.15,-0.89, 2 -JNU00109, 9,150NNW_JNU ,2.31,-0.96, 2 -JNU00110, 9,160NNW_JNU ,2.46,-1.02, 2 -JNU00111, 9,170NNW_JNU ,2.62,-1.08, 2 -JNU00112, 9,180NNW_JNU ,2.77,-1.15, 2 -JNU00113, 9,190NNW_JNU ,2.92,-1.21, 2 -JNU00114, 9,200NNW_JNU ,3.08,-1.28, 2 -JNU00115, 9,210NNW_JNU ,3.23,-1.34, 2 -JNU00116, 9,220NNW_JNU ,3.38,-1.40, 2 -JNU00117, 9,230NNW_JNU ,3.54,-1.47, 2 -JNU00118, 9,240NNW_JNU ,3.69,-1.53, 2 -YAK00000, 9,YAK ,0.00,0.00, 1 -YAK00001, 9,20N_YAK ,0.33,0.00, 2 -YAK00002, 9,30N_YAK ,0.50,0.00, 2 -YAK00003, 9,40N_YAK ,0.67,0.00, 2 -YAK00004, 9,50N_YAK ,0.83,0.00, 2 -YAK00005, 9,60N_YAK ,1.00,0.00, 2 -YAK00006, 9,70N_YAK ,1.17,0.00, 2 -YAK00007, 9,80N_YAK ,1.33,0.00, 2 -YAK00008, 9,90N_YAK ,1.50,0.00, 2 -YAK00009, 9,100N_YAK ,1.67,0.00, 2 -YAK00010, 9,110N_YAK ,1.83,0.00, 2 -YAK00011, 9,120N_YAK ,2.00,0.00, 2 -YAK00012, 9,130N_YAK ,2.17,0.00, 2 -YAK00013, 9,140N_YAK ,2.33,0.00, 2 -YAK00014, 9,150N_YAK ,2.50,0.00, 2 -YAK00015, 9,160N_YAK ,2.66,0.00, 2 -YAK00016, 9,170N_YAK ,2.83,0.00, 2 -YAK00017, 9,180N_YAK ,3.00,0.00, 2 -YAK00018, 9,190N_YAK ,3.16,0.00, 2 -YAK00019, 9,200N_YAK ,3.33,0.00, 2 -YAK00020, 9,210N_YAK ,3.50,0.00, 2 -YAK00021, 9,220N_YAK ,3.66,0.00, 2 -YAK00022, 9,230N_YAK ,3.83,0.00, 2 -YAK00023, 9,240N_YAK ,4.00,0.00, 2 -YAK00024, 9,250N_YAK ,4.16,0.00, 2 -YAK00025, 9,20NNE_YAK ,0.31,0.13, 2 -YAK00026, 9,30NNE_YAK ,0.46,0.19, 2 -YAK00027, 9,40NNE_YAK ,0.62,0.25, 2 -YAK00028, 9,50NNE_YAK ,0.77,0.32, 2 -YAK00029, 9,60NNE_YAK ,0.92,0.38, 2 -YAK00030, 9,70NNE_YAK ,1.08,0.45, 2 -YAK00031, 9,80NNE_YAK ,1.23,0.51, 2 -YAK00032, 9,90NNE_YAK ,1.38,0.57, 2 -YAK00033, 9,100NNE_YAK ,1.54,0.64, 2 -YAK00034, 9,110NNE_YAK ,1.69,0.70, 2 -YAK00035, 9,120NNE_YAK ,1.85,0.77, 2 -YAK00036, 9,130NNE_YAK ,2.00,0.83, 2 -YAK00037, 9,140NNE_YAK ,2.15,0.89, 2 -YAK00038, 9,150NNE_YAK ,2.31,0.96, 2 -YAK00039, 9,160NNE_YAK ,2.46,1.02, 2 -YAK00040, 9,170NNE_YAK ,2.62,1.08, 2 -YAK00041, 9,180NNE_YAK ,2.77,1.15, 2 -YAK00042, 9,190NNE_YAK ,2.92,1.21, 2 -YAK00043, 9,200NNE_YAK ,3.08,1.28, 2 -YAK00044, 9,210NNE_YAK ,3.23,1.34, 2 -YAK00045, 9,220NNE_YAK ,3.38,1.40, 2 -YAK00046, 9,230NNE_YAK ,3.54,1.47, 2 -YAK00047, 9,240NNE_YAK ,3.69,1.53, 2 -YAK00048, 9,20NE_YAK ,0.24,0.24, 2 -YAK00049, 9,30NE_YAK ,0.35,0.35, 2 -YAK00050, 9,40NE_YAK ,0.47,0.47, 2 -YAK00051, 9,50NE_YAK ,0.59,0.59, 2 -YAK00052, 9,60NE_YAK ,0.71,0.71, 2 -YAK00053, 9,70NE_YAK ,0.82,0.82, 2 -YAK00054, 9,80NE_YAK ,0.94,0.94, 2 -YAK00055, 9,90NE_YAK ,1.06,1.06, 2 -YAK00056, 9,100NE_YAK ,1.18,1.18, 2 -YAK00057, 9,110NE_YAK ,1.30,1.30, 2 -YAK00058, 9,120NE_YAK ,1.41,1.41, 2 -YAK00059, 9,130NE_YAK ,1.53,1.53, 2 -YAK00060, 9,140NE_YAK ,1.65,1.65, 2 -YAK00061, 9,150NE_YAK ,1.77,1.77, 2 -YAK00062, 9,160NE_YAK ,1.88,1.88, 2 -YAK00063, 9,170NE_YAK ,2.00,2.00, 2 -YAK00064, 9,180NE_YAK ,2.12,2.12, 2 -YAK00065, 9,190NE_YAK ,2.24,2.24, 2 -YAK00066, 9,200NE_YAK ,2.35,2.36, 2 -YAK00067, 9,210NE_YAK ,2.47,2.47, 2 -YAK00068, 9,220NE_YAK ,2.59,2.59, 2 -YAK00069, 9,230NE_YAK ,2.71,2.71, 2 -YAK00070, 9,240NE_YAK ,2.83,2.83, 2 -YAK00071, 9,250NE_YAK ,2.94,2.95, 2 -YAK00072, 9,20NW_YAK ,0.24,-0.24, 2 -YAK00073, 9,30NW_YAK ,0.35,-0.35, 2 -YAK00074, 9,40NW_YAK ,0.47,-0.47, 2 -YAK00075, 9,50NW_YAK ,0.59,-0.59, 2 -YAK00076, 9,60NW_YAK ,0.71,-0.71, 2 -YAK00077, 9,70NW_YAK ,0.82,-0.82, 2 -YAK00078, 9,80NW_YAK ,0.94,-0.94, 2 -YAK00079, 9,90NW_YAK ,1.06,-1.06, 2 -YAK00080, 9,100NW_YAK ,1.18,-1.18, 2 -YAK00081, 9,110NW_YAK ,1.30,-1.30, 2 -YAK00082, 9,120NW_YAK ,1.41,-1.41, 2 -YAK00083, 9,130NW_YAK ,1.53,-1.53, 2 -YAK00084, 9,140NW_YAK ,1.65,-1.65, 2 -YAK00085, 9,150NW_YAK ,1.77,-1.77, 2 -YAK00086, 9,160NW_YAK ,1.88,-1.88, 2 -YAK00087, 9,170NW_YAK ,2.00,-2.00, 2 -YAK00088, 9,180NW_YAK ,2.12,-2.12, 2 -YAK00089, 9,190NW_YAK ,2.24,-2.24, 2 -YAK00090, 9,200NW_YAK ,2.35,-2.36, 2 -YAK00091, 9,210NW_YAK ,2.47,-2.47, 2 -YAK00092, 9,220NW_YAK ,2.59,-2.59, 2 -YAK00093, 9,230NW_YAK ,2.71,-2.71, 2 -YAK00094, 9,240NW_YAK ,2.83,-2.83, 2 -YAK00095, 9,250NW_YAK ,2.94,-2.95, 2 -YAK00096, 9,20NNW_YAK ,0.31,-0.13, 2 -YAK00097, 9,30NNW_YAK ,0.46,-0.19, 2 -YAK00098, 9,40NNW_YAK ,0.62,-0.25, 2 -YAK00099, 9,50NNW_YAK ,0.77,-0.32, 2 -YAK00100, 9,60NNW_YAK ,0.92,-0.38, 2 -YAK00101, 9,70NNW_YAK ,1.08,-0.45, 2 -YAK00102, 9,80NNW_YAK ,1.23,-0.51, 2 -YAK00103, 9,90NNW_YAK ,1.38,-0.57, 2 -YAK00104, 9,100NNW_YAK ,1.54,-0.64, 2 -YAK00105, 9,110NNW_YAK ,1.69,-0.70, 2 -YAK00106, 9,120NNW_YAK ,1.85,-0.77, 2 -YAK00107, 9,130NNW_YAK ,2.00,-0.83, 2 -YAK00108, 9,140NNW_YAK ,2.15,-0.89, 2 -YAK00109, 9,150NNW_YAK ,2.31,-0.96, 2 -YAK00110, 9,160NNW_YAK ,2.46,-1.02, 2 -YAK00111, 9,170NNW_YAK ,2.62,-1.08, 2 -YAK00112, 9,180NNW_YAK ,2.77,-1.15, 2 -YAK00113, 9,190NNW_YAK ,2.92,-1.21, 2 -YAK00114, 9,200NNW_YAK ,3.08,-1.28, 2 -YAK00115, 9,210NNW_YAK ,3.23,-1.34, 2 -YAK00116, 9,220NNW_YAK ,3.38,-1.40, 2 -YAK00117, 9,230NNW_YAK ,3.54,-1.47, 2 -YAK00118, 9,240NNW_YAK ,3.69,-1.53, 2 -MDO00000, 9,MDO ,0.00,0.00, 1 -MDO00001, 9,20N_MDO ,0.33,0.00, 2 -MDO00002, 9,30N_MDO ,0.50,0.00, 2 -MDO00003, 9,40N_MDO ,0.67,0.00, 2 -MDO00004, 9,50N_MDO ,0.83,0.00, 2 -MDO00005, 9,60N_MDO ,1.00,0.00, 2 -MDO00006, 9,70N_MDO ,1.17,0.00, 2 -MDO00007, 9,80N_MDO ,1.33,0.00, 2 -MDO00008, 9,90N_MDO ,1.50,0.00, 2 -MDO00009, 9,100N_MDO ,1.67,0.00, 2 -MDO00010, 9,110N_MDO ,1.83,0.00, 2 -MDO00011, 9,120N_MDO ,2.00,0.00, 2 -MDO00012, 9,130N_MDO ,2.17,0.00, 2 -MDO00013, 9,140N_MDO ,2.33,0.00, 2 -MDO00014, 9,150N_MDO ,2.50,0.00, 2 -MDO00015, 9,160N_MDO ,2.66,0.00, 2 -MDO00016, 9,170N_MDO ,2.83,0.00, 2 -MDO00017, 9,180N_MDO ,3.00,0.00, 2 -MDO00018, 9,190N_MDO ,3.16,0.00, 2 -MDO00019, 9,200N_MDO ,3.33,0.00, 2 -MDO00020, 9,210N_MDO ,3.50,0.00, 2 -MDO00021, 9,220N_MDO ,3.66,0.00, 2 -MDO00022, 9,230N_MDO ,3.83,0.00, 2 -MDO00023, 9,240N_MDO ,4.00,0.00, 2 -MDO00024, 9,250N_MDO ,4.16,0.00, 2 -MDO00025, 9,20NNE_MDO ,0.31,0.13, 2 -MDO00026, 9,30NNE_MDO ,0.46,0.19, 2 -MDO00027, 9,40NNE_MDO ,0.62,0.25, 2 -MDO00028, 9,50NNE_MDO ,0.77,0.32, 2 -MDO00029, 9,60NNE_MDO ,0.92,0.38, 2 -MDO00030, 9,70NNE_MDO ,1.08,0.45, 2 -MDO00031, 9,80NNE_MDO ,1.23,0.51, 2 -MDO00032, 9,90NNE_MDO ,1.38,0.57, 2 -MDO00033, 9,100NNE_MDO ,1.54,0.64, 2 -MDO00034, 9,110NNE_MDO ,1.69,0.70, 2 -MDO00035, 9,120NNE_MDO ,1.85,0.77, 2 -MDO00036, 9,130NNE_MDO ,2.00,0.83, 2 -MDO00037, 9,140NNE_MDO ,2.15,0.89, 2 -MDO00038, 9,150NNE_MDO ,2.31,0.96, 2 -MDO00039, 9,160NNE_MDO ,2.46,1.02, 2 -MDO00040, 9,170NNE_MDO ,2.62,1.08, 2 -MDO00041, 9,180NNE_MDO ,2.77,1.15, 2 -MDO00042, 9,190NNE_MDO ,2.92,1.21, 2 -MDO00043, 9,200NNE_MDO ,3.08,1.28, 2 -MDO00044, 9,210NNE_MDO ,3.23,1.34, 2 -MDO00045, 9,220NNE_MDO ,3.38,1.40, 2 -MDO00046, 9,230NNE_MDO ,3.54,1.47, 2 -MDO00047, 9,240NNE_MDO ,3.69,1.53, 2 -MDO00048, 9,20NE_MDO ,0.24,0.24, 2 -MDO00049, 9,30NE_MDO ,0.35,0.35, 2 -MDO00050, 9,40NE_MDO ,0.47,0.47, 2 -MDO00051, 9,50NE_MDO ,0.59,0.59, 2 -MDO00052, 9,60NE_MDO ,0.71,0.71, 2 -MDO00053, 9,70NE_MDO ,0.82,0.82, 2 -MDO00054, 9,80NE_MDO ,0.94,0.94, 2 -MDO00055, 9,90NE_MDO ,1.06,1.06, 2 -MDO00056, 9,100NE_MDO ,1.18,1.18, 2 -MDO00057, 9,110NE_MDO ,1.30,1.30, 2 -MDO00058, 9,120NE_MDO ,1.41,1.41, 2 -MDO00059, 9,130NE_MDO ,1.53,1.53, 2 -MDO00060, 9,140NE_MDO ,1.65,1.65, 2 -MDO00061, 9,150NE_MDO ,1.77,1.77, 2 -MDO00062, 9,160NE_MDO ,1.88,1.88, 2 -MDO00063, 9,170NE_MDO ,2.00,2.00, 2 -MDO00064, 9,180NE_MDO ,2.12,2.12, 2 -MDO00065, 9,190NE_MDO ,2.24,2.24, 2 -MDO00066, 9,200NE_MDO ,2.35,2.36, 2 -MDO00067, 9,210NE_MDO ,2.47,2.47, 2 -MDO00068, 9,220NE_MDO ,2.59,2.59, 2 -MDO00069, 9,230NE_MDO ,2.71,2.71, 2 -MDO00070, 9,240NE_MDO ,2.83,2.83, 2 -MDO00071, 9,250NE_MDO ,2.94,2.95, 2 -MDO00072, 9,20NW_MDO ,0.24,-0.24, 2 -MDO00073, 9,30NW_MDO ,0.35,-0.35, 2 -MDO00074, 9,40NW_MDO ,0.47,-0.47, 2 -MDO00075, 9,50NW_MDO ,0.59,-0.59, 2 -MDO00076, 9,60NW_MDO ,0.71,-0.71, 2 -MDO00077, 9,70NW_MDO ,0.82,-0.82, 2 -MDO00078, 9,80NW_MDO ,0.94,-0.94, 2 -MDO00079, 9,90NW_MDO ,1.06,-1.06, 2 -MDO00080, 9,100NW_MDO ,1.18,-1.18, 2 -MDO00081, 9,110NW_MDO ,1.30,-1.30, 2 -MDO00082, 9,120NW_MDO ,1.41,-1.41, 2 -MDO00083, 9,130NW_MDO ,1.53,-1.53, 2 -MDO00084, 9,140NW_MDO ,1.65,-1.65, 2 -MDO00085, 9,150NW_MDO ,1.77,-1.77, 2 -MDO00086, 9,160NW_MDO ,1.88,-1.88, 2 -MDO00087, 9,170NW_MDO ,2.00,-2.00, 2 -MDO00088, 9,180NW_MDO ,2.12,-2.12, 2 -MDO00089, 9,190NW_MDO ,2.24,-2.24, 2 -MDO00090, 9,200NW_MDO ,2.35,-2.36, 2 -MDO00091, 9,210NW_MDO ,2.47,-2.47, 2 -MDO00092, 9,220NW_MDO ,2.59,-2.59, 2 -MDO00093, 9,230NW_MDO ,2.71,-2.71, 2 -MDO00094, 9,240NW_MDO ,2.83,-2.83, 2 -MDO00095, 9,250NW_MDO ,2.94,-2.95, 2 -MDO00096, 9,20NNW_MDO ,0.31,-0.13, 2 -MDO00097, 9,30NNW_MDO ,0.46,-0.19, 2 -MDO00098, 9,40NNW_MDO ,0.62,-0.25, 2 -MDO00099, 9,50NNW_MDO ,0.77,-0.32, 2 -MDO00100, 9,60NNW_MDO ,0.92,-0.38, 2 -MDO00101, 9,70NNW_MDO ,1.08,-0.45, 2 -MDO00102, 9,80NNW_MDO ,1.23,-0.51, 2 -MDO00103, 9,90NNW_MDO ,1.38,-0.57, 2 -MDO00104, 9,100NNW_MDO ,1.54,-0.64, 2 -MDO00105, 9,110NNW_MDO ,1.69,-0.70, 2 -MDO00106, 9,120NNW_MDO ,1.85,-0.77, 2 -MDO00107, 9,130NNW_MDO ,2.00,-0.83, 2 -MDO00108, 9,140NNW_MDO ,2.15,-0.89, 2 -MDO00109, 9,150NNW_MDO ,2.31,-0.96, 2 -MDO00110, 9,160NNW_MDO ,2.46,-1.02, 2 -MDO00111, 9,170NNW_MDO ,2.62,-1.08, 2 -MDO00112, 9,180NNW_MDO ,2.77,-1.15, 2 -MDO00113, 9,190NNW_MDO ,2.92,-1.21, 2 -MDO00114, 9,200NNW_MDO ,3.08,-1.28, 2 -MDO00115, 9,210NNW_MDO ,3.23,-1.34, 2 -MDO00116, 9,220NNW_MDO ,3.38,-1.40, 2 -MDO00117, 9,230NNW_MDO ,3.54,-1.47, 2 -MDO00118, 9,240NNW_MDO ,3.69,-1.53, 2 -JOH00000, 9,JOH ,0.00,0.00, 1 -JOH00001, 9,20N_JOH ,0.33,0.00, 2 -JOH00002, 9,30N_JOH ,0.50,0.00, 2 -JOH00003, 9,40N_JOH ,0.67,0.00, 2 -JOH00004, 9,50N_JOH ,0.83,0.00, 2 -JOH00005, 9,60N_JOH ,1.00,0.00, 2 -JOH00006, 9,70N_JOH ,1.17,0.00, 2 -JOH00007, 9,80N_JOH ,1.33,0.00, 2 -JOH00008, 9,90N_JOH ,1.50,0.00, 2 -JOH00009, 9,100N_JOH ,1.67,0.00, 2 -JOH00010, 9,110N_JOH ,1.83,0.00, 2 -JOH00011, 9,120N_JOH ,2.00,0.00, 2 -JOH00012, 9,130N_JOH ,2.17,0.00, 2 -JOH00013, 9,140N_JOH ,2.33,0.00, 2 -JOH00014, 9,150N_JOH ,2.50,0.00, 2 -JOH00015, 9,160N_JOH ,2.66,0.00, 2 -JOH00016, 9,170N_JOH ,2.83,0.00, 2 -JOH00017, 9,180N_JOH ,3.00,0.00, 2 -JOH00018, 9,190N_JOH ,3.16,0.00, 2 -JOH00019, 9,200N_JOH ,3.33,0.00, 2 -JOH00020, 9,210N_JOH ,3.50,0.00, 2 -JOH00021, 9,220N_JOH ,3.66,0.00, 2 -JOH00022, 9,230N_JOH ,3.83,0.00, 2 -JOH00023, 9,240N_JOH ,4.00,0.00, 2 -JOH00024, 9,250N_JOH ,4.16,0.00, 2 -JOH00025, 9,20NNE_JOH ,0.31,0.13, 2 -JOH00026, 9,30NNE_JOH ,0.46,0.19, 2 -JOH00027, 9,40NNE_JOH ,0.62,0.25, 2 -JOH00028, 9,50NNE_JOH ,0.77,0.32, 2 -JOH00029, 9,60NNE_JOH ,0.92,0.38, 2 -JOH00030, 9,70NNE_JOH ,1.08,0.45, 2 -JOH00031, 9,80NNE_JOH ,1.23,0.51, 2 -JOH00032, 9,90NNE_JOH ,1.38,0.57, 2 -JOH00033, 9,100NNE_JOH ,1.54,0.64, 2 -JOH00034, 9,110NNE_JOH ,1.69,0.70, 2 -JOH00035, 9,120NNE_JOH ,1.85,0.77, 2 -JOH00036, 9,130NNE_JOH ,2.00,0.83, 2 -JOH00037, 9,140NNE_JOH ,2.15,0.89, 2 -JOH00038, 9,150NNE_JOH ,2.31,0.96, 2 -JOH00039, 9,160NNE_JOH ,2.46,1.02, 2 -JOH00040, 9,170NNE_JOH ,2.62,1.08, 2 -JOH00041, 9,180NNE_JOH ,2.77,1.15, 2 -JOH00042, 9,190NNE_JOH ,2.92,1.21, 2 -JOH00043, 9,200NNE_JOH ,3.08,1.28, 2 -JOH00044, 9,210NNE_JOH ,3.23,1.34, 2 -JOH00045, 9,220NNE_JOH ,3.38,1.40, 2 -JOH00046, 9,230NNE_JOH ,3.54,1.47, 2 -JOH00047, 9,240NNE_JOH ,3.69,1.53, 2 -JOH00048, 9,20NE_JOH ,0.24,0.24, 2 -JOH00049, 9,30NE_JOH ,0.35,0.35, 2 -JOH00050, 9,40NE_JOH ,0.47,0.47, 2 -JOH00051, 9,50NE_JOH ,0.59,0.59, 2 -JOH00052, 9,60NE_JOH ,0.71,0.71, 2 -JOH00053, 9,70NE_JOH ,0.82,0.82, 2 -JOH00054, 9,80NE_JOH ,0.94,0.94, 2 -JOH00055, 9,90NE_JOH ,1.06,1.06, 2 -JOH00056, 9,100NE_JOH ,1.18,1.18, 2 -JOH00057, 9,110NE_JOH ,1.30,1.30, 2 -JOH00058, 9,120NE_JOH ,1.41,1.41, 2 -JOH00059, 9,130NE_JOH ,1.53,1.53, 2 -JOH00060, 9,140NE_JOH ,1.65,1.65, 2 -JOH00061, 9,150NE_JOH ,1.77,1.77, 2 -JOH00062, 9,160NE_JOH ,1.88,1.88, 2 -JOH00063, 9,170NE_JOH ,2.00,2.00, 2 -JOH00064, 9,180NE_JOH ,2.12,2.12, 2 -JOH00065, 9,190NE_JOH ,2.24,2.24, 2 -JOH00066, 9,200NE_JOH ,2.35,2.36, 2 -JOH00067, 9,210NE_JOH ,2.47,2.47, 2 -JOH00068, 9,220NE_JOH ,2.59,2.59, 2 -JOH00069, 9,230NE_JOH ,2.71,2.71, 2 -JOH00070, 9,240NE_JOH ,2.83,2.83, 2 -JOH00071, 9,250NE_JOH ,2.94,2.95, 2 -JOH00072, 9,20NW_JOH ,0.24,-0.24, 2 -JOH00073, 9,30NW_JOH ,0.35,-0.35, 2 -JOH00074, 9,40NW_JOH ,0.47,-0.47, 2 -JOH00075, 9,50NW_JOH ,0.59,-0.59, 2 -JOH00076, 9,60NW_JOH ,0.71,-0.71, 2 -JOH00077, 9,70NW_JOH ,0.82,-0.82, 2 -JOH00078, 9,80NW_JOH ,0.94,-0.94, 2 -JOH00079, 9,90NW_JOH ,1.06,-1.06, 2 -JOH00080, 9,100NW_JOH ,1.18,-1.18, 2 -JOH00081, 9,110NW_JOH ,1.30,-1.30, 2 -JOH00082, 9,120NW_JOH ,1.41,-1.41, 2 -JOH00083, 9,130NW_JOH ,1.53,-1.53, 2 -JOH00084, 9,140NW_JOH ,1.65,-1.65, 2 -JOH00085, 9,150NW_JOH ,1.77,-1.77, 2 -JOH00086, 9,160NW_JOH ,1.88,-1.88, 2 -JOH00087, 9,170NW_JOH ,2.00,-2.00, 2 -JOH00088, 9,180NW_JOH ,2.12,-2.12, 2 -JOH00089, 9,190NW_JOH ,2.24,-2.24, 2 -JOH00090, 9,200NW_JOH ,2.35,-2.36, 2 -JOH00091, 9,210NW_JOH ,2.47,-2.47, 2 -JOH00092, 9,220NW_JOH ,2.59,-2.59, 2 -JOH00093, 9,230NW_JOH ,2.71,-2.71, 2 -JOH00094, 9,240NW_JOH ,2.83,-2.83, 2 -JOH00095, 9,250NW_JOH ,2.94,-2.95, 2 -JOH00096, 9,20NNW_JOH ,0.31,-0.13, 2 -JOH00097, 9,30NNW_JOH ,0.46,-0.19, 2 -JOH00098, 9,40NNW_JOH ,0.62,-0.25, 2 -JOH00099, 9,50NNW_JOH ,0.77,-0.32, 2 -JOH00100, 9,60NNW_JOH ,0.92,-0.38, 2 -JOH00101, 9,70NNW_JOH ,1.08,-0.45, 2 -JOH00102, 9,80NNW_JOH ,1.23,-0.51, 2 -JOH00103, 9,90NNW_JOH ,1.38,-0.57, 2 -JOH00104, 9,100NNW_JOH ,1.54,-0.64, 2 -JOH00105, 9,110NNW_JOH ,1.69,-0.70, 2 -JOH00106, 9,120NNW_JOH ,1.85,-0.77, 2 -JOH00107, 9,130NNW_JOH ,2.00,-0.83, 2 -JOH00108, 9,140NNW_JOH ,2.15,-0.89, 2 -JOH00109, 9,150NNW_JOH ,2.31,-0.96, 2 -JOH00110, 9,160NNW_JOH ,2.46,-1.02, 2 -JOH00111, 9,170NNW_JOH ,2.62,-1.08, 2 -JOH00112, 9,180NNW_JOH ,2.77,-1.15, 2 -JOH00113, 9,190NNW_JOH ,2.92,-1.21, 2 -JOH00114, 9,200NNW_JOH ,3.08,-1.28, 2 -JOH00115, 9,210NNW_JOH ,3.23,-1.34, 2 -JOH00116, 9,220NNW_JOH ,3.38,-1.40, 2 -JOH00117, 9,230NNW_JOH ,3.54,-1.47, 2 -JOH00118, 9,240NNW_JOH ,3.69,-1.53, 2 -ODK00000, 9,ODK ,0.00,0.00, 1 -ODK00001, 9,20N_ODK ,0.33,0.00, 2 -ODK00002, 9,30N_ODK ,0.50,0.00, 2 -ODK00003, 9,40N_ODK ,0.67,0.00, 2 -ODK00004, 9,50N_ODK ,0.83,0.00, 2 -ODK00005, 9,60N_ODK ,1.00,0.00, 2 -ODK00006, 9,70N_ODK ,1.17,0.00, 2 -ODK00007, 9,80N_ODK ,1.33,0.00, 2 -ODK00008, 9,90N_ODK ,1.50,0.00, 2 -ODK00009, 9,100N_ODK ,1.67,0.00, 2 -ODK00010, 9,110N_ODK ,1.83,0.00, 2 -ODK00011, 9,120N_ODK ,2.00,0.00, 2 -ODK00012, 9,130N_ODK ,2.17,0.00, 2 -ODK00013, 9,140N_ODK ,2.33,0.00, 2 -ODK00014, 9,150N_ODK ,2.50,0.00, 2 -ODK00015, 9,160N_ODK ,2.66,0.00, 2 -ODK00016, 9,170N_ODK ,2.83,0.00, 2 -ODK00017, 9,180N_ODK ,3.00,0.00, 2 -ODK00018, 9,190N_ODK ,3.16,0.00, 2 -ODK00019, 9,200N_ODK ,3.33,0.00, 2 -ODK00020, 9,210N_ODK ,3.50,0.00, 2 -ODK00021, 9,220N_ODK ,3.66,0.00, 2 -ODK00022, 9,230N_ODK ,3.83,0.00, 2 -ODK00023, 9,240N_ODK ,4.00,0.00, 2 -ODK00024, 9,250N_ODK ,4.16,0.00, 2 -ODK00025, 9,20NNE_ODK ,0.31,0.13, 2 -ODK00026, 9,30NNE_ODK ,0.46,0.19, 2 -ODK00027, 9,40NNE_ODK ,0.62,0.25, 2 -ODK00028, 9,50NNE_ODK ,0.77,0.32, 2 -ODK00029, 9,60NNE_ODK ,0.92,0.38, 2 -ODK00030, 9,70NNE_ODK ,1.08,0.45, 2 -ODK00031, 9,80NNE_ODK ,1.23,0.51, 2 -ODK00032, 9,90NNE_ODK ,1.38,0.57, 2 -ODK00033, 9,100NNE_ODK ,1.54,0.64, 2 -ODK00034, 9,110NNE_ODK ,1.69,0.70, 2 -ODK00035, 9,120NNE_ODK ,1.85,0.77, 2 -ODK00036, 9,130NNE_ODK ,2.00,0.83, 2 -ODK00037, 9,140NNE_ODK ,2.15,0.89, 2 -ODK00038, 9,150NNE_ODK ,2.31,0.96, 2 -ODK00039, 9,160NNE_ODK ,2.46,1.02, 2 -ODK00040, 9,170NNE_ODK ,2.62,1.08, 2 -ODK00041, 9,180NNE_ODK ,2.77,1.15, 2 -ODK00042, 9,190NNE_ODK ,2.92,1.21, 2 -ODK00043, 9,200NNE_ODK ,3.08,1.28, 2 -ODK00044, 9,210NNE_ODK ,3.23,1.34, 2 -ODK00045, 9,220NNE_ODK ,3.38,1.40, 2 -ODK00046, 9,230NNE_ODK ,3.54,1.47, 2 -ODK00047, 9,240NNE_ODK ,3.69,1.53, 2 -ODK00048, 9,20NE_ODK ,0.24,0.24, 2 -ODK00049, 9,30NE_ODK ,0.35,0.35, 2 -ODK00050, 9,40NE_ODK ,0.47,0.47, 2 -ODK00051, 9,50NE_ODK ,0.59,0.59, 2 -ODK00052, 9,60NE_ODK ,0.71,0.71, 2 -ODK00053, 9,70NE_ODK ,0.82,0.82, 2 -ODK00054, 9,80NE_ODK ,0.94,0.94, 2 -ODK00055, 9,90NE_ODK ,1.06,1.06, 2 -ODK00056, 9,100NE_ODK ,1.18,1.18, 2 -ODK00057, 9,110NE_ODK ,1.30,1.30, 2 -ODK00058, 9,120NE_ODK ,1.41,1.41, 2 -ODK00059, 9,130NE_ODK ,1.53,1.53, 2 -ODK00060, 9,140NE_ODK ,1.65,1.65, 2 -ODK00061, 9,150NE_ODK ,1.77,1.77, 2 -ODK00062, 9,160NE_ODK ,1.88,1.88, 2 -ODK00063, 9,170NE_ODK ,2.00,2.00, 2 -ODK00064, 9,180NE_ODK ,2.12,2.12, 2 -ODK00065, 9,190NE_ODK ,2.24,2.24, 2 -ODK00066, 9,200NE_ODK ,2.35,2.36, 2 -ODK00067, 9,210NE_ODK ,2.47,2.47, 2 -ODK00068, 9,220NE_ODK ,2.59,2.59, 2 -ODK00069, 9,230NE_ODK ,2.71,2.71, 2 -ODK00070, 9,240NE_ODK ,2.83,2.83, 2 -ODK00071, 9,250NE_ODK ,2.94,2.95, 2 -ODK00072, 9,20NW_ODK ,0.24,-0.24, 2 -ODK00073, 9,30NW_ODK ,0.35,-0.35, 2 -ODK00074, 9,40NW_ODK ,0.47,-0.47, 2 -ODK00075, 9,50NW_ODK ,0.59,-0.59, 2 -ODK00076, 9,60NW_ODK ,0.71,-0.71, 2 -ODK00077, 9,70NW_ODK ,0.82,-0.82, 2 -ODK00078, 9,80NW_ODK ,0.94,-0.94, 2 -ODK00079, 9,90NW_ODK ,1.06,-1.06, 2 -ODK00080, 9,100NW_ODK ,1.18,-1.18, 2 -ODK00081, 9,110NW_ODK ,1.30,-1.30, 2 -ODK00082, 9,120NW_ODK ,1.41,-1.41, 2 -ODK00083, 9,130NW_ODK ,1.53,-1.53, 2 -ODK00084, 9,140NW_ODK ,1.65,-1.65, 2 -ODK00085, 9,150NW_ODK ,1.77,-1.77, 2 -ODK00086, 9,160NW_ODK ,1.88,-1.88, 2 -ODK00087, 9,170NW_ODK ,2.00,-2.00, 2 -ODK00088, 9,180NW_ODK ,2.12,-2.12, 2 -ODK00089, 9,190NW_ODK ,2.24,-2.24, 2 -ODK00090, 9,200NW_ODK ,2.35,-2.36, 2 -ODK00091, 9,210NW_ODK ,2.47,-2.47, 2 -ODK00092, 9,220NW_ODK ,2.59,-2.59, 2 -ODK00093, 9,230NW_ODK ,2.71,-2.71, 2 -ODK00094, 9,240NW_ODK ,2.83,-2.83, 2 -ODK00095, 9,250NW_ODK ,2.94,-2.95, 2 -ODK00096, 9,20NNW_ODK ,0.31,-0.13, 2 -ODK00097, 9,30NNW_ODK ,0.46,-0.19, 2 -ODK00098, 9,40NNW_ODK ,0.62,-0.25, 2 -ODK00099, 9,50NNW_ODK ,0.77,-0.32, 2 -ODK00100, 9,60NNW_ODK ,0.92,-0.38, 2 -ODK00101, 9,70NNW_ODK ,1.08,-0.45, 2 -ODK00102, 9,80NNW_ODK ,1.23,-0.51, 2 -ODK00103, 9,90NNW_ODK ,1.38,-0.57, 2 -ODK00104, 9,100NNW_ODK ,1.54,-0.64, 2 -ODK00105, 9,110NNW_ODK ,1.69,-0.70, 2 -ODK00106, 9,120NNW_ODK ,1.85,-0.77, 2 -ODK00107, 9,130NNW_ODK ,2.00,-0.83, 2 -ODK00108, 9,140NNW_ODK ,2.15,-0.89, 2 -ODK00109, 9,150NNW_ODK ,2.31,-0.96, 2 -ODK00110, 9,160NNW_ODK ,2.46,-1.02, 2 -ODK00111, 9,170NNW_ODK ,2.62,-1.08, 2 -ODK00112, 9,180NNW_ODK ,2.77,-1.15, 2 -ODK00113, 9,190NNW_ODK ,2.92,-1.21, 2 -ODK00114, 9,200NNW_ODK ,3.08,-1.28, 2 -ODK00115, 9,210NNW_ODK ,3.23,-1.34, 2 -ODK00116, 9,220NNW_ODK ,3.38,-1.40, 2 -ODK00117, 9,230NNW_ODK ,3.54,-1.47, 2 -ODK00118, 9,240NNW_ODK ,3.69,-1.53, 2 -HOM00000, 9,HOM ,0.00,0.00, 1 -HOM00001, 9,20N_HOM ,0.33,0.00, 2 -HOM00002, 9,30N_HOM ,0.50,0.00, 2 -HOM00003, 9,40N_HOM ,0.67,0.00, 2 -HOM00004, 9,50N_HOM ,0.83,0.00, 2 -HOM00005, 9,60N_HOM ,1.00,0.00, 2 -HOM00006, 9,70N_HOM ,1.17,0.00, 2 -HOM00007, 9,80N_HOM ,1.33,0.00, 2 -HOM00008, 9,90N_HOM ,1.50,0.00, 2 -HOM00009, 9,100N_HOM ,1.67,0.00, 2 -HOM00010, 9,110N_HOM ,1.83,0.00, 2 -HOM00011, 9,120N_HOM ,2.00,0.00, 2 -HOM00012, 9,130N_HOM ,2.17,0.00, 2 -HOM00013, 9,140N_HOM ,2.33,0.00, 2 -HOM00014, 9,150N_HOM ,2.50,0.00, 2 -HOM00015, 9,160N_HOM ,2.66,0.00, 2 -HOM00016, 9,170N_HOM ,2.83,0.00, 2 -HOM00017, 9,180N_HOM ,3.00,0.00, 2 -HOM00018, 9,190N_HOM ,3.16,0.00, 2 -HOM00019, 9,200N_HOM ,3.33,0.00, 2 -HOM00020, 9,210N_HOM ,3.50,0.00, 2 -HOM00021, 9,220N_HOM ,3.66,0.00, 2 -HOM00022, 9,230N_HOM ,3.83,0.00, 2 -HOM00023, 9,240N_HOM ,4.00,0.00, 2 -HOM00024, 9,250N_HOM ,4.16,0.00, 2 -HOM00025, 9,20NNE_HOM ,0.31,0.13, 2 -HOM00026, 9,30NNE_HOM ,0.46,0.19, 2 -HOM00027, 9,40NNE_HOM ,0.62,0.25, 2 -HOM00028, 9,50NNE_HOM ,0.77,0.32, 2 -HOM00029, 9,60NNE_HOM ,0.92,0.38, 2 -HOM00030, 9,70NNE_HOM ,1.08,0.45, 2 -HOM00031, 9,80NNE_HOM ,1.23,0.51, 2 -HOM00032, 9,90NNE_HOM ,1.38,0.57, 2 -HOM00033, 9,100NNE_HOM ,1.54,0.64, 2 -HOM00034, 9,110NNE_HOM ,1.69,0.70, 2 -HOM00035, 9,120NNE_HOM ,1.85,0.77, 2 -HOM00036, 9,130NNE_HOM ,2.00,0.83, 2 -HOM00037, 9,140NNE_HOM ,2.15,0.89, 2 -HOM00038, 9,150NNE_HOM ,2.31,0.96, 2 -HOM00039, 9,160NNE_HOM ,2.46,1.02, 2 -HOM00040, 9,170NNE_HOM ,2.62,1.08, 2 -HOM00041, 9,180NNE_HOM ,2.77,1.15, 2 -HOM00042, 9,190NNE_HOM ,2.92,1.21, 2 -HOM00043, 9,200NNE_HOM ,3.08,1.28, 2 -HOM00044, 9,210NNE_HOM ,3.23,1.34, 2 -HOM00045, 9,220NNE_HOM ,3.38,1.40, 2 -HOM00046, 9,230NNE_HOM ,3.54,1.47, 2 -HOM00047, 9,240NNE_HOM ,3.69,1.53, 2 -HOM00048, 9,20NE_HOM ,0.24,0.24, 2 -HOM00049, 9,30NE_HOM ,0.35,0.35, 2 -HOM00050, 9,40NE_HOM ,0.47,0.47, 2 -HOM00051, 9,50NE_HOM ,0.59,0.59, 2 -HOM00052, 9,60NE_HOM ,0.71,0.71, 2 -HOM00053, 9,70NE_HOM ,0.82,0.82, 2 -HOM00054, 9,80NE_HOM ,0.94,0.94, 2 -HOM00055, 9,90NE_HOM ,1.06,1.06, 2 -HOM00056, 9,100NE_HOM ,1.18,1.18, 2 -HOM00057, 9,110NE_HOM ,1.30,1.30, 2 -HOM00058, 9,120NE_HOM ,1.41,1.41, 2 -HOM00059, 9,130NE_HOM ,1.53,1.53, 2 -HOM00060, 9,140NE_HOM ,1.65,1.65, 2 -HOM00061, 9,150NE_HOM ,1.77,1.77, 2 -HOM00062, 9,160NE_HOM ,1.88,1.88, 2 -HOM00063, 9,170NE_HOM ,2.00,2.00, 2 -HOM00064, 9,180NE_HOM ,2.12,2.12, 2 -HOM00065, 9,190NE_HOM ,2.24,2.24, 2 -HOM00066, 9,200NE_HOM ,2.35,2.36, 2 -HOM00067, 9,210NE_HOM ,2.47,2.47, 2 -HOM00068, 9,220NE_HOM ,2.59,2.59, 2 -HOM00069, 9,230NE_HOM ,2.71,2.71, 2 -HOM00070, 9,240NE_HOM ,2.83,2.83, 2 -HOM00071, 9,250NE_HOM ,2.94,2.95, 2 -HOM00072, 9,20NW_HOM ,0.24,-0.24, 2 -HOM00073, 9,30NW_HOM ,0.35,-0.35, 2 -HOM00074, 9,40NW_HOM ,0.47,-0.47, 2 -HOM00075, 9,50NW_HOM ,0.59,-0.59, 2 -HOM00076, 9,60NW_HOM ,0.71,-0.71, 2 -HOM00077, 9,70NW_HOM ,0.82,-0.82, 2 -HOM00078, 9,80NW_HOM ,0.94,-0.94, 2 -HOM00079, 9,90NW_HOM ,1.06,-1.06, 2 -HOM00080, 9,100NW_HOM ,1.18,-1.18, 2 -HOM00081, 9,110NW_HOM ,1.30,-1.30, 2 -HOM00082, 9,120NW_HOM ,1.41,-1.41, 2 -HOM00083, 9,130NW_HOM ,1.53,-1.53, 2 -HOM00084, 9,140NW_HOM ,1.65,-1.65, 2 -HOM00085, 9,150NW_HOM ,1.77,-1.77, 2 -HOM00086, 9,160NW_HOM ,1.88,-1.88, 2 -HOM00087, 9,170NW_HOM ,2.00,-2.00, 2 -HOM00088, 9,180NW_HOM ,2.12,-2.12, 2 -HOM00089, 9,190NW_HOM ,2.24,-2.24, 2 -HOM00090, 9,200NW_HOM ,2.35,-2.36, 2 -HOM00091, 9,210NW_HOM ,2.47,-2.47, 2 -HOM00092, 9,220NW_HOM ,2.59,-2.59, 2 -HOM00093, 9,230NW_HOM ,2.71,-2.71, 2 -HOM00094, 9,240NW_HOM ,2.83,-2.83, 2 -HOM00095, 9,250NW_HOM ,2.94,-2.95, 2 -HOM00096, 9,20NNW_HOM ,0.31,-0.13, 2 -HOM00097, 9,30NNW_HOM ,0.46,-0.19, 2 -HOM00098, 9,40NNW_HOM ,0.62,-0.25, 2 -HOM00099, 9,50NNW_HOM ,0.77,-0.32, 2 -HOM00100, 9,60NNW_HOM ,0.92,-0.38, 2 -HOM00101, 9,70NNW_HOM ,1.08,-0.45, 2 -HOM00102, 9,80NNW_HOM ,1.23,-0.51, 2 -HOM00103, 9,90NNW_HOM ,1.38,-0.57, 2 -HOM00104, 9,100NNW_HOM ,1.54,-0.64, 2 -HOM00105, 9,110NNW_HOM ,1.69,-0.70, 2 -HOM00106, 9,120NNW_HOM ,1.85,-0.77, 2 -HOM00107, 9,130NNW_HOM ,2.00,-0.83, 2 -HOM00108, 9,140NNW_HOM ,2.15,-0.89, 2 -HOM00109, 9,150NNW_HOM ,2.31,-0.96, 2 -HOM00110, 9,160NNW_HOM ,2.46,-1.02, 2 -HOM00111, 9,170NNW_HOM ,2.62,-1.08, 2 -HOM00112, 9,180NNW_HOM ,2.77,-1.15, 2 -HOM00113, 9,190NNW_HOM ,2.92,-1.21, 2 -HOM00114, 9,200NNW_HOM ,3.08,-1.28, 2 -HOM00115, 9,210NNW_HOM ,3.23,-1.34, 2 -HOM00116, 9,220NNW_HOM ,3.38,-1.40, 2 -HOM00117, 9,230NNW_HOM ,3.54,-1.47, 2 -HOM00118, 9,240NNW_HOM ,3.69,-1.53, 2 -ENA00000, 9,ENA ,0.00,0.00, 1 -ENA00001, 9,20N_ENA ,0.33,0.00, 2 -ENA00002, 9,30N_ENA ,0.50,0.00, 2 -ENA00003, 9,40N_ENA ,0.67,0.00, 2 -ENA00004, 9,50N_ENA ,0.83,0.00, 2 -ENA00005, 9,60N_ENA ,1.00,0.00, 2 -ENA00006, 9,70N_ENA ,1.17,0.00, 2 -ENA00007, 9,80N_ENA ,1.33,0.00, 2 -ENA00008, 9,90N_ENA ,1.50,0.00, 2 -ENA00009, 9,100N_ENA ,1.67,0.00, 2 -ENA00010, 9,110N_ENA ,1.83,0.00, 2 -ENA00011, 9,120N_ENA ,2.00,0.00, 2 -ENA00012, 9,130N_ENA ,2.17,0.00, 2 -ENA00013, 9,140N_ENA ,2.33,0.00, 2 -ENA00014, 9,150N_ENA ,2.50,0.00, 2 -ENA00015, 9,160N_ENA ,2.66,0.00, 2 -ENA00016, 9,170N_ENA ,2.83,0.00, 2 -ENA00017, 9,180N_ENA ,3.00,0.00, 2 -ENA00018, 9,190N_ENA ,3.16,0.00, 2 -ENA00019, 9,200N_ENA ,3.33,0.00, 2 -ENA00020, 9,210N_ENA ,3.50,0.00, 2 -ENA00021, 9,220N_ENA ,3.66,0.00, 2 -ENA00022, 9,230N_ENA ,3.83,0.00, 2 -ENA00023, 9,240N_ENA ,4.00,0.00, 2 -ENA00024, 9,250N_ENA ,4.16,0.00, 2 -ENA00025, 9,20NNE_ENA ,0.31,0.13, 2 -ENA00026, 9,30NNE_ENA ,0.46,0.19, 2 -ENA00027, 9,40NNE_ENA ,0.62,0.25, 2 -ENA00028, 9,50NNE_ENA ,0.77,0.32, 2 -ENA00029, 9,60NNE_ENA ,0.92,0.38, 2 -ENA00030, 9,70NNE_ENA ,1.08,0.45, 2 -ENA00031, 9,80NNE_ENA ,1.23,0.51, 2 -ENA00032, 9,90NNE_ENA ,1.38,0.57, 2 -ENA00033, 9,100NNE_ENA ,1.54,0.64, 2 -ENA00034, 9,110NNE_ENA ,1.69,0.70, 2 -ENA00035, 9,120NNE_ENA ,1.85,0.77, 2 -ENA00036, 9,130NNE_ENA ,2.00,0.83, 2 -ENA00037, 9,140NNE_ENA ,2.15,0.89, 2 -ENA00038, 9,150NNE_ENA ,2.31,0.96, 2 -ENA00039, 9,160NNE_ENA ,2.46,1.02, 2 -ENA00040, 9,170NNE_ENA ,2.62,1.08, 2 -ENA00041, 9,180NNE_ENA ,2.77,1.15, 2 -ENA00042, 9,190NNE_ENA ,2.92,1.21, 2 -ENA00043, 9,200NNE_ENA ,3.08,1.28, 2 -ENA00044, 9,210NNE_ENA ,3.23,1.34, 2 -ENA00045, 9,220NNE_ENA ,3.38,1.40, 2 -ENA00046, 9,230NNE_ENA ,3.54,1.47, 2 -ENA00047, 9,240NNE_ENA ,3.69,1.53, 2 -ENA00048, 9,20NE_ENA ,0.24,0.24, 2 -ENA00049, 9,30NE_ENA ,0.35,0.35, 2 -ENA00050, 9,40NE_ENA ,0.47,0.47, 2 -ENA00051, 9,50NE_ENA ,0.59,0.59, 2 -ENA00052, 9,60NE_ENA ,0.71,0.71, 2 -ENA00053, 9,70NE_ENA ,0.82,0.82, 2 -ENA00054, 9,80NE_ENA ,0.94,0.94, 2 -ENA00055, 9,90NE_ENA ,1.06,1.06, 2 -ENA00056, 9,100NE_ENA ,1.18,1.18, 2 -ENA00057, 9,110NE_ENA ,1.30,1.30, 2 -ENA00058, 9,120NE_ENA ,1.41,1.41, 2 -ENA00059, 9,130NE_ENA ,1.53,1.53, 2 -ENA00060, 9,140NE_ENA ,1.65,1.65, 2 -ENA00061, 9,150NE_ENA ,1.77,1.77, 2 -ENA00062, 9,160NE_ENA ,1.88,1.88, 2 -ENA00063, 9,170NE_ENA ,2.00,2.00, 2 -ENA00064, 9,180NE_ENA ,2.12,2.12, 2 -ENA00065, 9,190NE_ENA ,2.24,2.24, 2 -ENA00066, 9,200NE_ENA ,2.35,2.36, 2 -ENA00067, 9,210NE_ENA ,2.47,2.47, 2 -ENA00068, 9,220NE_ENA ,2.59,2.59, 2 -ENA00069, 9,230NE_ENA ,2.71,2.71, 2 -ENA00070, 9,240NE_ENA ,2.83,2.83, 2 -ENA00071, 9,250NE_ENA ,2.94,2.95, 2 -ENA00072, 9,20NW_ENA ,0.24,-0.24, 2 -ENA00073, 9,30NW_ENA ,0.35,-0.35, 2 -ENA00074, 9,40NW_ENA ,0.47,-0.47, 2 -ENA00075, 9,50NW_ENA ,0.59,-0.59, 2 -ENA00076, 9,60NW_ENA ,0.71,-0.71, 2 -ENA00077, 9,70NW_ENA ,0.82,-0.82, 2 -ENA00078, 9,80NW_ENA ,0.94,-0.94, 2 -ENA00079, 9,90NW_ENA ,1.06,-1.06, 2 -ENA00080, 9,100NW_ENA ,1.18,-1.18, 2 -ENA00081, 9,110NW_ENA ,1.30,-1.30, 2 -ENA00082, 9,120NW_ENA ,1.41,-1.41, 2 -ENA00083, 9,130NW_ENA ,1.53,-1.53, 2 -ENA00084, 9,140NW_ENA ,1.65,-1.65, 2 -ENA00085, 9,150NW_ENA ,1.77,-1.77, 2 -ENA00086, 9,160NW_ENA ,1.88,-1.88, 2 -ENA00087, 9,170NW_ENA ,2.00,-2.00, 2 -ENA00088, 9,180NW_ENA ,2.12,-2.12, 2 -ENA00089, 9,190NW_ENA ,2.24,-2.24, 2 -ENA00090, 9,200NW_ENA ,2.35,-2.36, 2 -ENA00091, 9,210NW_ENA ,2.47,-2.47, 2 -ENA00092, 9,220NW_ENA ,2.59,-2.59, 2 -ENA00093, 9,230NW_ENA ,2.71,-2.71, 2 -ENA00094, 9,240NW_ENA ,2.83,-2.83, 2 -ENA00095, 9,250NW_ENA ,2.94,-2.95, 2 -ENA00096, 9,20NNW_ENA ,0.31,-0.13, 2 -ENA00097, 9,30NNW_ENA ,0.46,-0.19, 2 -ENA00098, 9,40NNW_ENA ,0.62,-0.25, 2 -ENA00099, 9,50NNW_ENA ,0.77,-0.32, 2 -ENA00100, 9,60NNW_ENA ,0.92,-0.38, 2 -ENA00101, 9,70NNW_ENA ,1.08,-0.45, 2 -ENA00102, 9,80NNW_ENA ,1.23,-0.51, 2 -ENA00103, 9,90NNW_ENA ,1.38,-0.57, 2 -ENA00104, 9,100NNW_ENA ,1.54,-0.64, 2 -ENA00105, 9,110NNW_ENA ,1.69,-0.70, 2 -ENA00106, 9,120NNW_ENA ,1.85,-0.77, 2 -ENA00107, 9,130NNW_ENA ,2.00,-0.83, 2 -ENA00108, 9,140NNW_ENA ,2.15,-0.89, 2 -ENA00109, 9,150NNW_ENA ,2.31,-0.96, 2 -ENA00110, 9,160NNW_ENA ,2.46,-1.02, 2 -ENA00111, 9,170NNW_ENA ,2.62,-1.08, 2 -ENA00112, 9,180NNW_ENA ,2.77,-1.15, 2 -ENA00113, 9,190NNW_ENA ,2.92,-1.21, 2 -ENA00114, 9,200NNW_ENA ,3.08,-1.28, 2 -ENA00115, 9,210NNW_ENA ,3.23,-1.34, 2 -ENA00116, 9,220NNW_ENA ,3.38,-1.40, 2 -ENA00117, 9,230NNW_ENA ,3.54,-1.47, 2 -ENA00118, 9,240NNW_ENA ,3.69,-1.53, 2 -ANC00000, 9,ANC ,0.00,0.00, 1 -ANC00001, 9,20N_ANC ,0.33,0.00, 2 -ANC00002, 9,30N_ANC ,0.50,0.00, 2 -ANC00003, 9,40N_ANC ,0.67,0.00, 2 -ANC00004, 9,50N_ANC ,0.83,0.00, 2 -ANC00005, 9,60N_ANC ,1.00,0.00, 2 -ANC00006, 9,70N_ANC ,1.17,0.00, 2 -ANC00007, 9,80N_ANC ,1.33,0.00, 2 -ANC00008, 9,90N_ANC ,1.50,0.00, 2 -ANC00009, 9,100N_ANC ,1.67,0.00, 2 -ANC00010, 9,110N_ANC ,1.83,0.00, 2 -ANC00011, 9,120N_ANC ,2.00,0.00, 2 -ANC00012, 9,130N_ANC ,2.17,0.00, 2 -ANC00013, 9,140N_ANC ,2.33,0.00, 2 -ANC00014, 9,150N_ANC ,2.50,0.00, 2 -ANC00015, 9,160N_ANC ,2.66,0.00, 2 -ANC00016, 9,170N_ANC ,2.83,0.00, 2 -ANC00017, 9,180N_ANC ,3.00,0.00, 2 -ANC00018, 9,190N_ANC ,3.16,0.00, 2 -ANC00019, 9,200N_ANC ,3.33,0.00, 2 -ANC00020, 9,210N_ANC ,3.50,0.00, 2 -ANC00021, 9,220N_ANC ,3.66,0.00, 2 -ANC00022, 9,230N_ANC ,3.83,0.00, 2 -ANC00023, 9,240N_ANC ,4.00,0.00, 2 -ANC00024, 9,250N_ANC ,4.16,0.00, 2 -ANC00025, 9,20NNE_ANC ,0.31,0.13, 2 -ANC00026, 9,30NNE_ANC ,0.46,0.19, 2 -ANC00027, 9,40NNE_ANC ,0.62,0.25, 2 -ANC00028, 9,50NNE_ANC ,0.77,0.32, 2 -ANC00029, 9,60NNE_ANC ,0.92,0.38, 2 -ANC00030, 9,70NNE_ANC ,1.08,0.45, 2 -ANC00031, 9,80NNE_ANC ,1.23,0.51, 2 -ANC00032, 9,90NNE_ANC ,1.38,0.57, 2 -ANC00033, 9,100NNE_ANC ,1.54,0.64, 2 -ANC00034, 9,110NNE_ANC ,1.69,0.70, 2 -ANC00035, 9,120NNE_ANC ,1.85,0.77, 2 -ANC00036, 9,130NNE_ANC ,2.00,0.83, 2 -ANC00037, 9,140NNE_ANC ,2.15,0.89, 2 -ANC00038, 9,150NNE_ANC ,2.31,0.96, 2 -ANC00039, 9,160NNE_ANC ,2.46,1.02, 2 -ANC00040, 9,170NNE_ANC ,2.62,1.08, 2 -ANC00041, 9,180NNE_ANC ,2.77,1.15, 2 -ANC00042, 9,190NNE_ANC ,2.92,1.21, 2 -ANC00043, 9,200NNE_ANC ,3.08,1.28, 2 -ANC00044, 9,210NNE_ANC ,3.23,1.34, 2 -ANC00045, 9,220NNE_ANC ,3.38,1.40, 2 -ANC00046, 9,230NNE_ANC ,3.54,1.47, 2 -ANC00047, 9,240NNE_ANC ,3.69,1.53, 2 -ANC00048, 9,20NE_ANC ,0.24,0.24, 2 -ANC00049, 9,30NE_ANC ,0.35,0.35, 2 -ANC00050, 9,40NE_ANC ,0.47,0.47, 2 -ANC00051, 9,50NE_ANC ,0.59,0.59, 2 -ANC00052, 9,60NE_ANC ,0.71,0.71, 2 -ANC00053, 9,70NE_ANC ,0.82,0.82, 2 -ANC00054, 9,80NE_ANC ,0.94,0.94, 2 -ANC00055, 9,90NE_ANC ,1.06,1.06, 2 -ANC00056, 9,100NE_ANC ,1.18,1.18, 2 -ANC00057, 9,110NE_ANC ,1.30,1.30, 2 -ANC00058, 9,120NE_ANC ,1.41,1.41, 2 -ANC00059, 9,130NE_ANC ,1.53,1.53, 2 -ANC00060, 9,140NE_ANC ,1.65,1.65, 2 -ANC00061, 9,150NE_ANC ,1.77,1.77, 2 -ANC00062, 9,160NE_ANC ,1.88,1.88, 2 -ANC00063, 9,170NE_ANC ,2.00,2.00, 2 -ANC00064, 9,180NE_ANC ,2.12,2.12, 2 -ANC00065, 9,190NE_ANC ,2.24,2.24, 2 -ANC00066, 9,200NE_ANC ,2.35,2.36, 2 -ANC00067, 9,210NE_ANC ,2.47,2.47, 2 -ANC00068, 9,220NE_ANC ,2.59,2.59, 2 -ANC00069, 9,230NE_ANC ,2.71,2.71, 2 -ANC00070, 9,240NE_ANC ,2.83,2.83, 2 -ANC00071, 9,250NE_ANC ,2.94,2.95, 2 -ANC00072, 9,20NW_ANC ,0.24,-0.24, 2 -ANC00073, 9,30NW_ANC ,0.35,-0.35, 2 -ANC00074, 9,40NW_ANC ,0.47,-0.47, 2 -ANC00075, 9,50NW_ANC ,0.59,-0.59, 2 -ANC00076, 9,60NW_ANC ,0.71,-0.71, 2 -ANC00077, 9,70NW_ANC ,0.82,-0.82, 2 -ANC00078, 9,80NW_ANC ,0.94,-0.94, 2 -ANC00079, 9,90NW_ANC ,1.06,-1.06, 2 -ANC00080, 9,100NW_ANC ,1.18,-1.18, 2 -ANC00081, 9,110NW_ANC ,1.30,-1.30, 2 -ANC00082, 9,120NW_ANC ,1.41,-1.41, 2 -ANC00083, 9,130NW_ANC ,1.53,-1.53, 2 -ANC00084, 9,140NW_ANC ,1.65,-1.65, 2 -ANC00085, 9,150NW_ANC ,1.77,-1.77, 2 -ANC00086, 9,160NW_ANC ,1.88,-1.88, 2 -ANC00087, 9,170NW_ANC ,2.00,-2.00, 2 -ANC00088, 9,180NW_ANC ,2.12,-2.12, 2 -ANC00089, 9,190NW_ANC ,2.24,-2.24, 2 -ANC00090, 9,200NW_ANC ,2.35,-2.36, 2 -ANC00091, 9,210NW_ANC ,2.47,-2.47, 2 -ANC00092, 9,220NW_ANC ,2.59,-2.59, 2 -ANC00093, 9,230NW_ANC ,2.71,-2.71, 2 -ANC00094, 9,240NW_ANC ,2.83,-2.83, 2 -ANC00095, 9,250NW_ANC ,2.94,-2.95, 2 -ANC00096, 9,20NNW_ANC ,0.31,-0.13, 2 -ANC00097, 9,30NNW_ANC ,0.46,-0.19, 2 -ANC00098, 9,40NNW_ANC ,0.62,-0.25, 2 -ANC00099, 9,50NNW_ANC ,0.77,-0.32, 2 -ANC00100, 9,60NNW_ANC ,0.92,-0.38, 2 -ANC00101, 9,70NNW_ANC ,1.08,-0.45, 2 -ANC00102, 9,80NNW_ANC ,1.23,-0.51, 2 -ANC00103, 9,90NNW_ANC ,1.38,-0.57, 2 -ANC00104, 9,100NNW_ANC ,1.54,-0.64, 2 -ANC00105, 9,110NNW_ANC ,1.69,-0.70, 2 -ANC00106, 9,120NNW_ANC ,1.85,-0.77, 2 -ANC00107, 9,130NNW_ANC ,2.00,-0.83, 2 -ANC00108, 9,140NNW_ANC ,2.15,-0.89, 2 -ANC00109, 9,150NNW_ANC ,2.31,-0.96, 2 -ANC00110, 9,160NNW_ANC ,2.46,-1.02, 2 -ANC00111, 9,170NNW_ANC ,2.62,-1.08, 2 -ANC00112, 9,180NNW_ANC ,2.77,-1.15, 2 -ANC00113, 9,190NNW_ANC ,2.92,-1.21, 2 -ANC00114, 9,200NNW_ANC ,3.08,-1.28, 2 -ANC00115, 9,210NNW_ANC ,3.23,-1.34, 2 -ANC00116, 9,220NNW_ANC ,3.38,-1.40, 2 -ANC00117, 9,230NNW_ANC ,3.54,-1.47, 2 -ANC00118, 9,240NNW_ANC ,3.69,-1.53, 2 -BGQ00000, 9,BGQ ,0.00,0.00, 1 -BGQ00001, 9,20N_BGQ ,0.33,0.00, 2 -BGQ00002, 9,30N_BGQ ,0.50,0.00, 2 -BGQ00003, 9,40N_BGQ ,0.67,0.00, 2 -BGQ00004, 9,50N_BGQ ,0.83,0.00, 2 -BGQ00005, 9,60N_BGQ ,1.00,0.00, 2 -BGQ00006, 9,70N_BGQ ,1.17,0.00, 2 -BGQ00007, 9,80N_BGQ ,1.33,0.00, 2 -BGQ00008, 9,90N_BGQ ,1.50,0.00, 2 -BGQ00009, 9,100N_BGQ ,1.67,0.00, 2 -BGQ00010, 9,110N_BGQ ,1.83,0.00, 2 -BGQ00011, 9,120N_BGQ ,2.00,0.00, 2 -BGQ00012, 9,130N_BGQ ,2.17,0.00, 2 -BGQ00013, 9,140N_BGQ ,2.33,0.00, 2 -BGQ00014, 9,150N_BGQ ,2.50,0.00, 2 -BGQ00015, 9,160N_BGQ ,2.66,0.00, 2 -BGQ00016, 9,170N_BGQ ,2.83,0.00, 2 -BGQ00017, 9,180N_BGQ ,3.00,0.00, 2 -BGQ00018, 9,190N_BGQ ,3.16,0.00, 2 -BGQ00019, 9,200N_BGQ ,3.33,0.00, 2 -BGQ00020, 9,210N_BGQ ,3.50,0.00, 2 -BGQ00021, 9,220N_BGQ ,3.66,0.00, 2 -BGQ00022, 9,230N_BGQ ,3.83,0.00, 2 -BGQ00023, 9,240N_BGQ ,4.00,0.00, 2 -BGQ00024, 9,250N_BGQ ,4.16,0.00, 2 -BGQ00025, 9,20NNE_BGQ ,0.31,0.13, 2 -BGQ00026, 9,30NNE_BGQ ,0.46,0.19, 2 -BGQ00027, 9,40NNE_BGQ ,0.62,0.25, 2 -BGQ00028, 9,50NNE_BGQ ,0.77,0.32, 2 -BGQ00029, 9,60NNE_BGQ ,0.92,0.38, 2 -BGQ00030, 9,70NNE_BGQ ,1.08,0.45, 2 -BGQ00031, 9,80NNE_BGQ ,1.23,0.51, 2 -BGQ00032, 9,90NNE_BGQ ,1.38,0.57, 2 -BGQ00033, 9,100NNE_BGQ ,1.54,0.64, 2 -BGQ00034, 9,110NNE_BGQ ,1.69,0.70, 2 -BGQ00035, 9,120NNE_BGQ ,1.85,0.77, 2 -BGQ00036, 9,130NNE_BGQ ,2.00,0.83, 2 -BGQ00037, 9,140NNE_BGQ ,2.15,0.89, 2 -BGQ00038, 9,150NNE_BGQ ,2.31,0.96, 2 -BGQ00039, 9,160NNE_BGQ ,2.46,1.02, 2 -BGQ00040, 9,170NNE_BGQ ,2.62,1.08, 2 -BGQ00041, 9,180NNE_BGQ ,2.77,1.15, 2 -BGQ00042, 9,190NNE_BGQ ,2.92,1.21, 2 -BGQ00043, 9,200NNE_BGQ ,3.08,1.28, 2 -BGQ00044, 9,210NNE_BGQ ,3.23,1.34, 2 -BGQ00045, 9,220NNE_BGQ ,3.38,1.40, 2 -BGQ00046, 9,230NNE_BGQ ,3.54,1.47, 2 -BGQ00047, 9,240NNE_BGQ ,3.69,1.53, 2 -BGQ00048, 9,20NE_BGQ ,0.24,0.24, 2 -BGQ00049, 9,30NE_BGQ ,0.35,0.35, 2 -BGQ00050, 9,40NE_BGQ ,0.47,0.47, 2 -BGQ00051, 9,50NE_BGQ ,0.59,0.59, 2 -BGQ00052, 9,60NE_BGQ ,0.71,0.71, 2 -BGQ00053, 9,70NE_BGQ ,0.82,0.82, 2 -BGQ00054, 9,80NE_BGQ ,0.94,0.94, 2 -BGQ00055, 9,90NE_BGQ ,1.06,1.06, 2 -BGQ00056, 9,100NE_BGQ ,1.18,1.18, 2 -BGQ00057, 9,110NE_BGQ ,1.30,1.30, 2 -BGQ00058, 9,120NE_BGQ ,1.41,1.41, 2 -BGQ00059, 9,130NE_BGQ ,1.53,1.53, 2 -BGQ00060, 9,140NE_BGQ ,1.65,1.65, 2 -BGQ00061, 9,150NE_BGQ ,1.77,1.77, 2 -BGQ00062, 9,160NE_BGQ ,1.88,1.88, 2 -BGQ00063, 9,170NE_BGQ ,2.00,2.00, 2 -BGQ00064, 9,180NE_BGQ ,2.12,2.12, 2 -BGQ00065, 9,190NE_BGQ ,2.24,2.24, 2 -BGQ00066, 9,200NE_BGQ ,2.35,2.36, 2 -BGQ00067, 9,210NE_BGQ ,2.47,2.47, 2 -BGQ00068, 9,220NE_BGQ ,2.59,2.59, 2 -BGQ00069, 9,230NE_BGQ ,2.71,2.71, 2 -BGQ00070, 9,240NE_BGQ ,2.83,2.83, 2 -BGQ00071, 9,250NE_BGQ ,2.94,2.95, 2 -BGQ00072, 9,20NW_BGQ ,0.24,-0.24, 2 -BGQ00073, 9,30NW_BGQ ,0.35,-0.35, 2 -BGQ00074, 9,40NW_BGQ ,0.47,-0.47, 2 -BGQ00075, 9,50NW_BGQ ,0.59,-0.59, 2 -BGQ00076, 9,60NW_BGQ ,0.71,-0.71, 2 -BGQ00077, 9,70NW_BGQ ,0.82,-0.82, 2 -BGQ00078, 9,80NW_BGQ ,0.94,-0.94, 2 -BGQ00079, 9,90NW_BGQ ,1.06,-1.06, 2 -BGQ00080, 9,100NW_BGQ ,1.18,-1.18, 2 -BGQ00081, 9,110NW_BGQ ,1.30,-1.30, 2 -BGQ00082, 9,120NW_BGQ ,1.41,-1.41, 2 -BGQ00083, 9,130NW_BGQ ,1.53,-1.53, 2 -BGQ00084, 9,140NW_BGQ ,1.65,-1.65, 2 -BGQ00085, 9,150NW_BGQ ,1.77,-1.77, 2 -BGQ00086, 9,160NW_BGQ ,1.88,-1.88, 2 -BGQ00087, 9,170NW_BGQ ,2.00,-2.00, 2 -BGQ00088, 9,180NW_BGQ ,2.12,-2.12, 2 -BGQ00089, 9,190NW_BGQ ,2.24,-2.24, 2 -BGQ00090, 9,200NW_BGQ ,2.35,-2.36, 2 -BGQ00091, 9,210NW_BGQ ,2.47,-2.47, 2 -BGQ00092, 9,220NW_BGQ ,2.59,-2.59, 2 -BGQ00093, 9,230NW_BGQ ,2.71,-2.71, 2 -BGQ00094, 9,240NW_BGQ ,2.83,-2.83, 2 -BGQ00095, 9,250NW_BGQ ,2.94,-2.95, 2 -BGQ00096, 9,20NNW_BGQ ,0.31,-0.13, 2 -BGQ00097, 9,30NNW_BGQ ,0.46,-0.19, 2 -BGQ00098, 9,40NNW_BGQ ,0.62,-0.25, 2 -BGQ00099, 9,50NNW_BGQ ,0.77,-0.32, 2 -BGQ00100, 9,60NNW_BGQ ,0.92,-0.38, 2 -BGQ00101, 9,70NNW_BGQ ,1.08,-0.45, 2 -BGQ00102, 9,80NNW_BGQ ,1.23,-0.51, 2 -BGQ00103, 9,90NNW_BGQ ,1.38,-0.57, 2 -BGQ00104, 9,100NNW_BGQ ,1.54,-0.64, 2 -BGQ00105, 9,110NNW_BGQ ,1.69,-0.70, 2 -BGQ00106, 9,120NNW_BGQ ,1.85,-0.77, 2 -BGQ00107, 9,130NNW_BGQ ,2.00,-0.83, 2 -BGQ00108, 9,140NNW_BGQ ,2.15,-0.89, 2 -BGQ00109, 9,150NNW_BGQ ,2.31,-0.96, 2 -BGQ00110, 9,160NNW_BGQ ,2.46,-1.02, 2 -BGQ00111, 9,170NNW_BGQ ,2.62,-1.08, 2 -BGQ00112, 9,180NNW_BGQ ,2.77,-1.15, 2 -BGQ00113, 9,190NNW_BGQ ,2.92,-1.21, 2 -BGQ00114, 9,200NNW_BGQ ,3.08,-1.28, 2 -BGQ00115, 9,210NNW_BGQ ,3.23,-1.34, 2 -BGQ00116, 9,220NNW_BGQ ,3.38,-1.40, 2 -BGQ00117, 9,230NNW_BGQ ,3.54,-1.47, 2 -BGQ00118, 9,240NNW_BGQ ,3.69,-1.53, 2 -ORT00000, 9,ORT ,0.00,0.00, 1 -ORT00001, 9,20N_ORT ,0.33,0.00, 2 -ORT00002, 9,30N_ORT ,0.50,0.00, 2 -ORT00003, 9,40N_ORT ,0.67,0.00, 2 -ORT00004, 9,50N_ORT ,0.83,0.00, 2 -ORT00005, 9,60N_ORT ,1.00,0.00, 2 -ORT00006, 9,70N_ORT ,1.17,0.00, 2 -ORT00007, 9,80N_ORT ,1.33,0.00, 2 -ORT00008, 9,90N_ORT ,1.50,0.00, 2 -ORT00009, 9,100N_ORT ,1.67,0.00, 2 -ORT00010, 9,110N_ORT ,1.83,0.00, 2 -ORT00011, 9,120N_ORT ,2.00,0.00, 2 -ORT00012, 9,130N_ORT ,2.17,0.00, 2 -ORT00013, 9,140N_ORT ,2.33,0.00, 2 -ORT00014, 9,150N_ORT ,2.50,0.00, 2 -ORT00015, 9,160N_ORT ,2.66,0.00, 2 -ORT00016, 9,170N_ORT ,2.83,0.00, 2 -ORT00017, 9,180N_ORT ,3.00,0.00, 2 -ORT00018, 9,190N_ORT ,3.16,0.00, 2 -ORT00019, 9,200N_ORT ,3.33,0.00, 2 -ORT00020, 9,210N_ORT ,3.50,0.00, 2 -ORT00021, 9,220N_ORT ,3.66,0.00, 2 -ORT00022, 9,230N_ORT ,3.83,0.00, 2 -ORT00023, 9,240N_ORT ,4.00,0.00, 2 -ORT00024, 9,250N_ORT ,4.16,0.00, 2 -ORT00025, 9,20NNE_ORT ,0.31,0.13, 2 -ORT00026, 9,30NNE_ORT ,0.46,0.19, 2 -ORT00027, 9,40NNE_ORT ,0.62,0.25, 2 -ORT00028, 9,50NNE_ORT ,0.77,0.32, 2 -ORT00029, 9,60NNE_ORT ,0.92,0.38, 2 -ORT00030, 9,70NNE_ORT ,1.08,0.45, 2 -ORT00031, 9,80NNE_ORT ,1.23,0.51, 2 -ORT00032, 9,90NNE_ORT ,1.38,0.57, 2 -ORT00033, 9,100NNE_ORT ,1.54,0.64, 2 -ORT00034, 9,110NNE_ORT ,1.69,0.70, 2 -ORT00035, 9,120NNE_ORT ,1.85,0.77, 2 -ORT00036, 9,130NNE_ORT ,2.00,0.83, 2 -ORT00037, 9,140NNE_ORT ,2.15,0.89, 2 -ORT00038, 9,150NNE_ORT ,2.31,0.96, 2 -ORT00039, 9,160NNE_ORT ,2.46,1.02, 2 -ORT00040, 9,170NNE_ORT ,2.62,1.08, 2 -ORT00041, 9,180NNE_ORT ,2.77,1.15, 2 -ORT00042, 9,190NNE_ORT ,2.92,1.21, 2 -ORT00043, 9,200NNE_ORT ,3.08,1.28, 2 -ORT00044, 9,210NNE_ORT ,3.23,1.34, 2 -ORT00045, 9,220NNE_ORT ,3.38,1.40, 2 -ORT00046, 9,230NNE_ORT ,3.54,1.47, 2 -ORT00047, 9,240NNE_ORT ,3.69,1.53, 2 -ORT00048, 9,20NE_ORT ,0.24,0.24, 2 -ORT00049, 9,30NE_ORT ,0.35,0.35, 2 -ORT00050, 9,40NE_ORT ,0.47,0.47, 2 -ORT00051, 9,50NE_ORT ,0.59,0.59, 2 -ORT00052, 9,60NE_ORT ,0.71,0.71, 2 -ORT00053, 9,70NE_ORT ,0.82,0.82, 2 -ORT00054, 9,80NE_ORT ,0.94,0.94, 2 -ORT00055, 9,90NE_ORT ,1.06,1.06, 2 -ORT00056, 9,100NE_ORT ,1.18,1.18, 2 -ORT00057, 9,110NE_ORT ,1.30,1.30, 2 -ORT00058, 9,120NE_ORT ,1.41,1.41, 2 -ORT00059, 9,130NE_ORT ,1.53,1.53, 2 -ORT00060, 9,140NE_ORT ,1.65,1.65, 2 -ORT00061, 9,150NE_ORT ,1.77,1.77, 2 -ORT00062, 9,160NE_ORT ,1.88,1.88, 2 -ORT00063, 9,170NE_ORT ,2.00,2.00, 2 -ORT00064, 9,180NE_ORT ,2.12,2.12, 2 -ORT00065, 9,190NE_ORT ,2.24,2.24, 2 -ORT00066, 9,200NE_ORT ,2.35,2.36, 2 -ORT00067, 9,210NE_ORT ,2.47,2.47, 2 -ORT00068, 9,220NE_ORT ,2.59,2.59, 2 -ORT00069, 9,230NE_ORT ,2.71,2.71, 2 -ORT00070, 9,240NE_ORT ,2.83,2.83, 2 -ORT00071, 9,250NE_ORT ,2.94,2.95, 2 -ORT00072, 9,20NW_ORT ,0.24,-0.24, 2 -ORT00073, 9,30NW_ORT ,0.35,-0.35, 2 -ORT00074, 9,40NW_ORT ,0.47,-0.47, 2 -ORT00075, 9,50NW_ORT ,0.59,-0.59, 2 -ORT00076, 9,60NW_ORT ,0.71,-0.71, 2 -ORT00077, 9,70NW_ORT ,0.82,-0.82, 2 -ORT00078, 9,80NW_ORT ,0.94,-0.94, 2 -ORT00079, 9,90NW_ORT ,1.06,-1.06, 2 -ORT00080, 9,100NW_ORT ,1.18,-1.18, 2 -ORT00081, 9,110NW_ORT ,1.30,-1.30, 2 -ORT00082, 9,120NW_ORT ,1.41,-1.41, 2 -ORT00083, 9,130NW_ORT ,1.53,-1.53, 2 -ORT00084, 9,140NW_ORT ,1.65,-1.65, 2 -ORT00085, 9,150NW_ORT ,1.77,-1.77, 2 -ORT00086, 9,160NW_ORT ,1.88,-1.88, 2 -ORT00087, 9,170NW_ORT ,2.00,-2.00, 2 -ORT00088, 9,180NW_ORT ,2.12,-2.12, 2 -ORT00089, 9,190NW_ORT ,2.24,-2.24, 2 -ORT00090, 9,200NW_ORT ,2.35,-2.36, 2 -ORT00091, 9,210NW_ORT ,2.47,-2.47, 2 -ORT00092, 9,220NW_ORT ,2.59,-2.59, 2 -ORT00093, 9,230NW_ORT ,2.71,-2.71, 2 -ORT00094, 9,240NW_ORT ,2.83,-2.83, 2 -ORT00095, 9,250NW_ORT ,2.94,-2.95, 2 -ORT00096, 9,20NNW_ORT ,0.31,-0.13, 2 -ORT00097, 9,30NNW_ORT ,0.46,-0.19, 2 -ORT00098, 9,40NNW_ORT ,0.62,-0.25, 2 -ORT00099, 9,50NNW_ORT ,0.77,-0.32, 2 -ORT00100, 9,60NNW_ORT ,0.92,-0.38, 2 -ORT00101, 9,70NNW_ORT ,1.08,-0.45, 2 -ORT00102, 9,80NNW_ORT ,1.23,-0.51, 2 -ORT00103, 9,90NNW_ORT ,1.38,-0.57, 2 -ORT00104, 9,100NNW_ORT ,1.54,-0.64, 2 -ORT00105, 9,110NNW_ORT ,1.69,-0.70, 2 -ORT00106, 9,120NNW_ORT ,1.85,-0.77, 2 -ORT00107, 9,130NNW_ORT ,2.00,-0.83, 2 -ORT00108, 9,140NNW_ORT ,2.15,-0.89, 2 -ORT00109, 9,150NNW_ORT ,2.31,-0.96, 2 -ORT00110, 9,160NNW_ORT ,2.46,-1.02, 2 -ORT00111, 9,170NNW_ORT ,2.62,-1.08, 2 -ORT00112, 9,180NNW_ORT ,2.77,-1.15, 2 -ORT00113, 9,190NNW_ORT ,2.92,-1.21, 2 -ORT00114, 9,200NNW_ORT ,3.08,-1.28, 2 -ORT00115, 9,210NNW_ORT ,3.23,-1.34, 2 -ORT00116, 9,220NNW_ORT ,3.38,-1.40, 2 -ORT00117, 9,230NNW_ORT ,3.54,-1.47, 2 -ORT00118, 9,240NNW_ORT ,3.69,-1.53, 2 -GKN00000, 9,GKN ,0.00,0.00, 1 -GKN00001, 9,20N_GKN ,0.33,0.00, 2 -GKN00002, 9,30N_GKN ,0.50,0.00, 2 -GKN00003, 9,40N_GKN ,0.67,0.00, 2 -GKN00004, 9,50N_GKN ,0.83,0.00, 2 -GKN00005, 9,60N_GKN ,1.00,0.00, 2 -GKN00006, 9,70N_GKN ,1.17,0.00, 2 -GKN00007, 9,80N_GKN ,1.33,0.00, 2 -GKN00008, 9,90N_GKN ,1.50,0.00, 2 -GKN00009, 9,100N_GKN ,1.67,0.00, 2 -GKN00010, 9,110N_GKN ,1.83,0.00, 2 -GKN00011, 9,120N_GKN ,2.00,0.00, 2 -GKN00012, 9,130N_GKN ,2.17,0.00, 2 -GKN00013, 9,140N_GKN ,2.33,0.00, 2 -GKN00014, 9,150N_GKN ,2.50,0.00, 2 -GKN00015, 9,160N_GKN ,2.66,0.00, 2 -GKN00016, 9,170N_GKN ,2.83,0.00, 2 -GKN00017, 9,180N_GKN ,3.00,0.00, 2 -GKN00018, 9,190N_GKN ,3.16,0.00, 2 -GKN00019, 9,200N_GKN ,3.33,0.00, 2 -GKN00020, 9,210N_GKN ,3.50,0.00, 2 -GKN00021, 9,220N_GKN ,3.66,0.00, 2 -GKN00022, 9,230N_GKN ,3.83,0.00, 2 -GKN00023, 9,240N_GKN ,4.00,0.00, 2 -GKN00024, 9,250N_GKN ,4.16,0.00, 2 -GKN00025, 9,20NNE_GKN ,0.31,0.13, 2 -GKN00026, 9,30NNE_GKN ,0.46,0.19, 2 -GKN00027, 9,40NNE_GKN ,0.62,0.25, 2 -GKN00028, 9,50NNE_GKN ,0.77,0.32, 2 -GKN00029, 9,60NNE_GKN ,0.92,0.38, 2 -GKN00030, 9,70NNE_GKN ,1.08,0.45, 2 -GKN00031, 9,80NNE_GKN ,1.23,0.51, 2 -GKN00032, 9,90NNE_GKN ,1.38,0.57, 2 -GKN00033, 9,100NNE_GKN ,1.54,0.64, 2 -GKN00034, 9,110NNE_GKN ,1.69,0.70, 2 -GKN00035, 9,120NNE_GKN ,1.85,0.77, 2 -GKN00036, 9,130NNE_GKN ,2.00,0.83, 2 -GKN00037, 9,140NNE_GKN ,2.15,0.89, 2 -GKN00038, 9,150NNE_GKN ,2.31,0.96, 2 -GKN00039, 9,160NNE_GKN ,2.46,1.02, 2 -GKN00040, 9,170NNE_GKN ,2.62,1.08, 2 -GKN00041, 9,180NNE_GKN ,2.77,1.15, 2 -GKN00042, 9,190NNE_GKN ,2.92,1.21, 2 -GKN00043, 9,200NNE_GKN ,3.08,1.28, 2 -GKN00044, 9,210NNE_GKN ,3.23,1.34, 2 -GKN00045, 9,220NNE_GKN ,3.38,1.40, 2 -GKN00046, 9,230NNE_GKN ,3.54,1.47, 2 -GKN00047, 9,240NNE_GKN ,3.69,1.53, 2 -GKN00048, 9,20NE_GKN ,0.24,0.24, 2 -GKN00049, 9,30NE_GKN ,0.35,0.35, 2 -GKN00050, 9,40NE_GKN ,0.47,0.47, 2 -GKN00051, 9,50NE_GKN ,0.59,0.59, 2 -GKN00052, 9,60NE_GKN ,0.71,0.71, 2 -GKN00053, 9,70NE_GKN ,0.82,0.82, 2 -GKN00054, 9,80NE_GKN ,0.94,0.94, 2 -GKN00055, 9,90NE_GKN ,1.06,1.06, 2 -GKN00056, 9,100NE_GKN ,1.18,1.18, 2 -GKN00057, 9,110NE_GKN ,1.30,1.30, 2 -GKN00058, 9,120NE_GKN ,1.41,1.41, 2 -GKN00059, 9,130NE_GKN ,1.53,1.53, 2 -GKN00060, 9,140NE_GKN ,1.65,1.65, 2 -GKN00061, 9,150NE_GKN ,1.77,1.77, 2 -GKN00062, 9,160NE_GKN ,1.88,1.88, 2 -GKN00063, 9,170NE_GKN ,2.00,2.00, 2 -GKN00064, 9,180NE_GKN ,2.12,2.12, 2 -GKN00065, 9,190NE_GKN ,2.24,2.24, 2 -GKN00066, 9,200NE_GKN ,2.35,2.36, 2 -GKN00067, 9,210NE_GKN ,2.47,2.47, 2 -GKN00068, 9,220NE_GKN ,2.59,2.59, 2 -GKN00069, 9,230NE_GKN ,2.71,2.71, 2 -GKN00070, 9,240NE_GKN ,2.83,2.83, 2 -GKN00071, 9,250NE_GKN ,2.94,2.95, 2 -GKN00072, 9,20NW_GKN ,0.24,-0.24, 2 -GKN00073, 9,30NW_GKN ,0.35,-0.35, 2 -GKN00074, 9,40NW_GKN ,0.47,-0.47, 2 -GKN00075, 9,50NW_GKN ,0.59,-0.59, 2 -GKN00076, 9,60NW_GKN ,0.71,-0.71, 2 -GKN00077, 9,70NW_GKN ,0.82,-0.82, 2 -GKN00078, 9,80NW_GKN ,0.94,-0.94, 2 -GKN00079, 9,90NW_GKN ,1.06,-1.06, 2 -GKN00080, 9,100NW_GKN ,1.18,-1.18, 2 -GKN00081, 9,110NW_GKN ,1.30,-1.30, 2 -GKN00082, 9,120NW_GKN ,1.41,-1.41, 2 -GKN00083, 9,130NW_GKN ,1.53,-1.53, 2 -GKN00084, 9,140NW_GKN ,1.65,-1.65, 2 -GKN00085, 9,150NW_GKN ,1.77,-1.77, 2 -GKN00086, 9,160NW_GKN ,1.88,-1.88, 2 -GKN00087, 9,170NW_GKN ,2.00,-2.00, 2 -GKN00088, 9,180NW_GKN ,2.12,-2.12, 2 -GKN00089, 9,190NW_GKN ,2.24,-2.24, 2 -GKN00090, 9,200NW_GKN ,2.35,-2.36, 2 -GKN00091, 9,210NW_GKN ,2.47,-2.47, 2 -GKN00092, 9,220NW_GKN ,2.59,-2.59, 2 -GKN00093, 9,230NW_GKN ,2.71,-2.71, 2 -GKN00094, 9,240NW_GKN ,2.83,-2.83, 2 -GKN00095, 9,250NW_GKN ,2.94,-2.95, 2 -GKN00096, 9,20NNW_GKN ,0.31,-0.13, 2 -GKN00097, 9,30NNW_GKN ,0.46,-0.19, 2 -GKN00098, 9,40NNW_GKN ,0.62,-0.25, 2 -GKN00099, 9,50NNW_GKN ,0.77,-0.32, 2 -GKN00100, 9,60NNW_GKN ,0.92,-0.38, 2 -GKN00101, 9,70NNW_GKN ,1.08,-0.45, 2 -GKN00102, 9,80NNW_GKN ,1.23,-0.51, 2 -GKN00103, 9,90NNW_GKN ,1.38,-0.57, 2 -GKN00104, 9,100NNW_GKN ,1.54,-0.64, 2 -GKN00105, 9,110NNW_GKN ,1.69,-0.70, 2 -GKN00106, 9,120NNW_GKN ,1.85,-0.77, 2 -GKN00107, 9,130NNW_GKN ,2.00,-0.83, 2 -GKN00108, 9,140NNW_GKN ,2.15,-0.89, 2 -GKN00109, 9,150NNW_GKN ,2.31,-0.96, 2 -GKN00110, 9,160NNW_GKN ,2.46,-1.02, 2 -GKN00111, 9,170NNW_GKN ,2.62,-1.08, 2 -GKN00112, 9,180NNW_GKN ,2.77,-1.15, 2 -GKN00113, 9,190NNW_GKN ,2.92,-1.21, 2 -GKN00114, 9,200NNW_GKN ,3.08,-1.28, 2 -GKN00115, 9,210NNW_GKN ,3.23,-1.34, 2 -GKN00116, 9,220NNW_GKN ,3.38,-1.40, 2 -GKN00117, 9,230NNW_GKN ,3.54,-1.47, 2 -GKN00118, 9,240NNW_GKN ,3.69,-1.53, 2 -TKA00000, 9,TKA ,0.00,0.00, 1 -TKA00001, 9,20N_TKA ,0.33,0.00, 2 -TKA00002, 9,30N_TKA ,0.50,0.00, 2 -TKA00003, 9,40N_TKA ,0.67,0.00, 2 -TKA00004, 9,50N_TKA ,0.83,0.00, 2 -TKA00005, 9,60N_TKA ,1.00,0.00, 2 -TKA00006, 9,70N_TKA ,1.17,0.00, 2 -TKA00007, 9,80N_TKA ,1.33,0.00, 2 -TKA00008, 9,90N_TKA ,1.50,0.00, 2 -TKA00009, 9,100N_TKA ,1.67,0.00, 2 -TKA00010, 9,110N_TKA ,1.83,0.00, 2 -TKA00011, 9,120N_TKA ,2.00,0.00, 2 -TKA00012, 9,130N_TKA ,2.17,0.00, 2 -TKA00013, 9,140N_TKA ,2.33,0.00, 2 -TKA00014, 9,150N_TKA ,2.50,0.00, 2 -TKA00015, 9,160N_TKA ,2.66,0.00, 2 -TKA00016, 9,170N_TKA ,2.83,0.00, 2 -TKA00017, 9,180N_TKA ,3.00,0.00, 2 -TKA00018, 9,190N_TKA ,3.16,0.00, 2 -TKA00019, 9,200N_TKA ,3.33,0.00, 2 -TKA00020, 9,210N_TKA ,3.50,0.00, 2 -TKA00021, 9,220N_TKA ,3.66,0.00, 2 -TKA00022, 9,230N_TKA ,3.83,0.00, 2 -TKA00023, 9,240N_TKA ,4.00,0.00, 2 -TKA00024, 9,250N_TKA ,4.16,0.00, 2 -TKA00025, 9,20NNE_TKA ,0.31,0.13, 2 -TKA00026, 9,30NNE_TKA ,0.46,0.19, 2 -TKA00027, 9,40NNE_TKA ,0.62,0.25, 2 -TKA00028, 9,50NNE_TKA ,0.77,0.32, 2 -TKA00029, 9,60NNE_TKA ,0.92,0.38, 2 -TKA00030, 9,70NNE_TKA ,1.08,0.45, 2 -TKA00031, 9,80NNE_TKA ,1.23,0.51, 2 -TKA00032, 9,90NNE_TKA ,1.38,0.57, 2 -TKA00033, 9,100NNE_TKA ,1.54,0.64, 2 -TKA00034, 9,110NNE_TKA ,1.69,0.70, 2 -TKA00035, 9,120NNE_TKA ,1.85,0.77, 2 -TKA00036, 9,130NNE_TKA ,2.00,0.83, 2 -TKA00037, 9,140NNE_TKA ,2.15,0.89, 2 -TKA00038, 9,150NNE_TKA ,2.31,0.96, 2 -TKA00039, 9,160NNE_TKA ,2.46,1.02, 2 -TKA00040, 9,170NNE_TKA ,2.62,1.08, 2 -TKA00041, 9,180NNE_TKA ,2.77,1.15, 2 -TKA00042, 9,190NNE_TKA ,2.92,1.21, 2 -TKA00043, 9,200NNE_TKA ,3.08,1.28, 2 -TKA00044, 9,210NNE_TKA ,3.23,1.34, 2 -TKA00045, 9,220NNE_TKA ,3.38,1.40, 2 -TKA00046, 9,230NNE_TKA ,3.54,1.47, 2 -TKA00047, 9,240NNE_TKA ,3.69,1.53, 2 -TKA00048, 9,20NE_TKA ,0.24,0.24, 2 -TKA00049, 9,30NE_TKA ,0.35,0.35, 2 -TKA00050, 9,40NE_TKA ,0.47,0.47, 2 -TKA00051, 9,50NE_TKA ,0.59,0.59, 2 -TKA00052, 9,60NE_TKA ,0.71,0.71, 2 -TKA00053, 9,70NE_TKA ,0.82,0.82, 2 -TKA00054, 9,80NE_TKA ,0.94,0.94, 2 -TKA00055, 9,90NE_TKA ,1.06,1.06, 2 -TKA00056, 9,100NE_TKA ,1.18,1.18, 2 -TKA00057, 9,110NE_TKA ,1.30,1.30, 2 -TKA00058, 9,120NE_TKA ,1.41,1.41, 2 -TKA00059, 9,130NE_TKA ,1.53,1.53, 2 -TKA00060, 9,140NE_TKA ,1.65,1.65, 2 -TKA00061, 9,150NE_TKA ,1.77,1.77, 2 -TKA00062, 9,160NE_TKA ,1.88,1.88, 2 -TKA00063, 9,170NE_TKA ,2.00,2.00, 2 -TKA00064, 9,180NE_TKA ,2.12,2.12, 2 -TKA00065, 9,190NE_TKA ,2.24,2.24, 2 -TKA00066, 9,200NE_TKA ,2.35,2.36, 2 -TKA00067, 9,210NE_TKA ,2.47,2.47, 2 -TKA00068, 9,220NE_TKA ,2.59,2.59, 2 -TKA00069, 9,230NE_TKA ,2.71,2.71, 2 -TKA00070, 9,240NE_TKA ,2.83,2.83, 2 -TKA00071, 9,250NE_TKA ,2.94,2.95, 2 -TKA00072, 9,20NW_TKA ,0.24,-0.24, 2 -TKA00073, 9,30NW_TKA ,0.35,-0.35, 2 -TKA00074, 9,40NW_TKA ,0.47,-0.47, 2 -TKA00075, 9,50NW_TKA ,0.59,-0.59, 2 -TKA00076, 9,60NW_TKA ,0.71,-0.71, 2 -TKA00077, 9,70NW_TKA ,0.82,-0.82, 2 -TKA00078, 9,80NW_TKA ,0.94,-0.94, 2 -TKA00079, 9,90NW_TKA ,1.06,-1.06, 2 -TKA00080, 9,100NW_TKA ,1.18,-1.18, 2 -TKA00081, 9,110NW_TKA ,1.30,-1.30, 2 -TKA00082, 9,120NW_TKA ,1.41,-1.41, 2 -TKA00083, 9,130NW_TKA ,1.53,-1.53, 2 -TKA00084, 9,140NW_TKA ,1.65,-1.65, 2 -TKA00085, 9,150NW_TKA ,1.77,-1.77, 2 -TKA00086, 9,160NW_TKA ,1.88,-1.88, 2 -TKA00087, 9,170NW_TKA ,2.00,-2.00, 2 -TKA00088, 9,180NW_TKA ,2.12,-2.12, 2 -TKA00089, 9,190NW_TKA ,2.24,-2.24, 2 -TKA00090, 9,200NW_TKA ,2.35,-2.36, 2 -TKA00091, 9,210NW_TKA ,2.47,-2.47, 2 -TKA00092, 9,220NW_TKA ,2.59,-2.59, 2 -TKA00093, 9,230NW_TKA ,2.71,-2.71, 2 -TKA00094, 9,240NW_TKA ,2.83,-2.83, 2 -TKA00095, 9,250NW_TKA ,2.94,-2.95, 2 -TKA00096, 9,20NNW_TKA ,0.31,-0.13, 2 -TKA00097, 9,30NNW_TKA ,0.46,-0.19, 2 -TKA00098, 9,40NNW_TKA ,0.62,-0.25, 2 -TKA00099, 9,50NNW_TKA ,0.77,-0.32, 2 -TKA00100, 9,60NNW_TKA ,0.92,-0.38, 2 -TKA00101, 9,70NNW_TKA ,1.08,-0.45, 2 -TKA00102, 9,80NNW_TKA ,1.23,-0.51, 2 -TKA00103, 9,90NNW_TKA ,1.38,-0.57, 2 -TKA00104, 9,100NNW_TKA ,1.54,-0.64, 2 -TKA00105, 9,110NNW_TKA ,1.69,-0.70, 2 -TKA00106, 9,120NNW_TKA ,1.85,-0.77, 2 -TKA00107, 9,130NNW_TKA ,2.00,-0.83, 2 -TKA00108, 9,140NNW_TKA ,2.15,-0.89, 2 -TKA00109, 9,150NNW_TKA ,2.31,-0.96, 2 -TKA00110, 9,160NNW_TKA ,2.46,-1.02, 2 -TKA00111, 9,170NNW_TKA ,2.62,-1.08, 2 -TKA00112, 9,180NNW_TKA ,2.77,-1.15, 2 -TKA00113, 9,190NNW_TKA ,2.92,-1.21, 2 -TKA00114, 9,200NNW_TKA ,3.08,-1.28, 2 -TKA00115, 9,210NNW_TKA ,3.23,-1.34, 2 -TKA00116, 9,220NNW_TKA ,3.38,-1.40, 2 -TKA00117, 9,230NNW_TKA ,3.54,-1.47, 2 -TKA00118, 9,240NNW_TKA ,3.69,-1.53, 2 COORD001, 9,50WSW_YXC ,49.27,-116.95, 1 COORD002, 9,50SE_REO ,42.00,-117.08, 1 COORD003, 9,40SE_LKV ,42.02,-119.87, 1 diff --git a/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosAvnData.java b/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosAvnData.java index 630af09cbb..79a9700b63 100644 --- a/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosAvnData.java +++ b/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosAvnData.java @@ -19,6 +19,9 @@ **/ package com.raytheon.edex.plugin.bufrmos.common; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.SequenceGenerator; import javax.persistence.Table; @@ -48,6 +51,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 14, 2013 1869 bsteffen Remove DataURI column from bufrmos. + * Aug 19, 2013 2275 bsteffen Add dataURI column back into bufrmos + * types. * * * @@ -77,4 +82,11 @@ public class BufrMosAvnData extends BufrMosData { return MOSType.AVN; } + @Override + @Column + @Access(AccessType.PROPERTY) + public String getDataURI() { + return super.getDataURI(); + } + } diff --git a/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosHpcData.java b/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosHpcData.java index 9ee9929ef8..bbc388319c 100644 --- a/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosHpcData.java +++ b/edexOsgi/com.raytheon.edex.plugin.bufrmos/src/com/raytheon/edex/plugin/bufrmos/common/BufrMosHpcData.java @@ -19,6 +19,9 @@ **/ package com.raytheon.edex.plugin.bufrmos.common; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.SequenceGenerator; import javax.persistence.Table; @@ -48,6 +51,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. * May 14, 2013 1869 bsteffen Remove DataURI column from bufrmos. + * Aug 19, 2013 2275 bsteffen Add dataURI column back into bufrmos + * types. * * * @@ -77,4 +82,11 @@ public class BufrMosHpcData extends BufrMosData { return MOSType.HPC; } + @Override + @Column + @Access(AccessType.PROPERTY) + public String getDataURI() { + return super.getDataURI(); + } + } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java index e127deea6d..42f2be1a89 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/db/dao/GFEDao.java @@ -1292,7 +1292,7 @@ public class GFEDao extends DefaultPluginDao { DatabaseQuery query = new DatabaseQuery(this.daoClass); query.addQueryParam("parmId.dbId.siteId", dbId.getSiteId(), QueryOperand.EQUALS); - query.addQueryParam("parmId.dbId.format", dbId.getFormat(), + query.addQueryParam("parmId.dbId.dbType", dbId.getDbType(), QueryOperand.EQUALS); query.addQueryParam("parmId.dbId.modelName", dbId.getModelName(), QueryOperand.EQUALS); diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/res/spring.deprecated/grib-decode.xml b/edexOsgi/com.raytheon.edex.plugin.grib/res/spring.deprecated/grib-decode.xml index efa2bd86a0..19b4807c0b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/res/spring.deprecated/grib-decode.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/res/spring.deprecated/grib-decode.xml @@ -53,6 +53,9 @@ class="com.raytheon.edex.plugin.grib.spatial.GribSpatialCache" factory-method="getInstance" depends-on="gridcoveragelookup"/> + + + @@ -63,6 +66,7 @@ + grid diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/filenameprocessor/NcgribFileNameProcessor.java b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/filenameprocessor/NcgribFileNameProcessor.java index 09e97004a2..ef52528cdb 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/filenameprocessor/NcgribFileNameProcessor.java +++ b/edexOsgi/com.raytheon.edex.plugin.grib/src/com/raytheon/edex/plugin/grib/filenameprocessor/NcgribFileNameProcessor.java @@ -54,11 +54,11 @@ public class NcgribFileNameProcessor implements Processor { // grab global wind and wave ensemble IDs private static final Pattern ENSEMBLE_WAVE_PATTERN = Pattern - .compile("^gep(\\d{0,2}{2})$"); + .compile("^\\d{8}_gep(\\d{0,2}{2})$"); // grab global wind and wave ensemble IDs private static final Pattern ENSEMBLE_NFC_PATTERN = Pattern - .compile("^HTSGW_(\\d{0,2}{2})$"); + .compile("^\\d{8}_HTSGW_(\\d{2})$"); // anything that ends in nest is assumed to be a nested grid identifier // might add alaska fire weather later... private static final Pattern FIREWXNEST_ID_PATTERN = Pattern @@ -73,7 +73,7 @@ public class NcgribFileNameProcessor implements Processor { // This is the least generic pattern ever, are there any constraints on // event names, who knows? private static final Pattern HURRICANE_PATTERN = Pattern - .compile("^([a-z]*)\\d{1,2}[lewcs]$"); + .compile("^\\d{10}_([a-z]*)\\d{1,2}[lewcs]$"); private static NcgribModelNameMap modelMap = null; @@ -85,6 +85,7 @@ public class NcgribFileNameProcessor implements Processor { String secondaryid = null; String ensembleid = null; String[] nameTokens = flName.split("\\."); + for (String token : nameTokens) { if (ENSEMBLE_ID_PATTERN.matcher(token).find()) { ensembleid = token; @@ -112,15 +113,17 @@ public class NcgribFileNameProcessor implements Processor { matcher.find(); secondaryid = matcher.group(1); datasetid = "GHM"; - if (nameTokens[2].equalsIgnoreCase("gribn3")) { + + if (nameTokens[3].equalsIgnoreCase("gribn3")) { datasetid = "GHMNEST"; - } else if (nameTokens[2].equalsIgnoreCase("grib6th")) { + } else if (nameTokens[3].equalsIgnoreCase("grib6th")) { datasetid = "GHM6TH"; - } else if (nameTokens[2].equalsIgnoreCase("hwrfprs_n")) { + } else if (nameTokens[3].equalsIgnoreCase("hwrfprs_n")) { datasetid = "HWRFNEST"; - } else if (nameTokens[2].equalsIgnoreCase("hwrfprs_p")) { + } else if (nameTokens[3].equalsIgnoreCase("hwrfprs_p")) { datasetid = "HWRF"; } + } } @@ -128,6 +131,7 @@ public class NcgribFileNameProcessor implements Processor { modelMap = NcgribModelNameMap.load(); } + // Get model name from grib file template if (datasetid == null) { datasetid = modelMap.getModelName(flName); } diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml index 2f4169156c..8eb3e0c393 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml +++ b/edexOsgi/com.raytheon.edex.plugin.grib/utility/edex_static/base/grib/ncgrib/ncgribModelNameMap.xml @@ -3,219 +3,219 @@ - cmc_geavg.* + gens_cmce.*_cmc_geavg.* cmceDerv - cmc_gespr.* + gens_cmce.*_cmc_gespr.* cmceDerv - gec00.*anl + gens_gefs.*_gec00.*anl gefsAnal - gep[0-9][0-9].*anl + gens_gefs.*_gep[0-9][0-9].*anl gefsAnal - gec00.*bcf.* + gens_gefs.*_gec00.*bcf.* gefsBC - gep[0-9][0-9].*bcf.* + gens_gefs.*_gep[0-9][0-9].*bcf.* gefsBC - geavg.*bcf.* + gens_gefs.*_geavg.*bcf.* gefsBCDerv - gespr.*bcf.* + gens_gefs.*_gespr.*bcf.* gefsBCDerv - geavg.* + gens_gefs.*_geavg.* gefsDerv - gespr.* + gens_gefs.*_gespr.* gefsDerv - HTSGW_mean.* + wave_nfcens.*_HTSGW_mean.* nfcMean - HTSGW_probab.* + wave_nfcens.*_HTSGW_probab.* nfcProb - HTSGW_spread.* + wave_nfcens.*_HTSGW_spread.* nfcSprd - mens.glo_60m.*.grib2 + wave_wave.*_mens.glo_60m.*.grib2 gwwEns - gep[0-9][0-9].glo_60m.*.grib2 + wave_wave.*_gep[0-9][0-9].glo_60m.*.grib2 gwwEns - mean.* + wave_wave.*_mean.* gwwMean - spread.*.grib2 + wave_wave.*_spread.*.grib2 gwwSprd - probab.*.grib2 + wave_wave.*_probab.*.grib2 gwwProb - naefs_geavg.*bcf.* + gens_naefs.*_naefs_geavg.*bcf.* naefsDervBC - naefs_gespr.*bcf.* + gens_naefs.*_naefs_gespr.*bcf.* naefsDervBC - naefs_gemode.*bcf.* + gens_naefs.*_naefs_gemode.*bcf.* naefsModeBC - naefs_ge10pt.*bcf.* + gens_naefs.*_naefs_ge10pt.*bcf.* naefs10ptBC - naefs_ge50pt.*bcf.* + gens_naefs.*_naefs_ge50pt.*bcf.* naefs50ptBC - naefs_ge90pt.*bcf.* + gens_naefs.*_naefs_ge90pt.*bcf.* naefs90ptBC - naefs_geavg.*ndgd_conusf.*grib2 + gens_naefs.*_naefs_geavg.*ndgd_conusf.*grib2 naefsDervUS - naefs_gespr.*ndgd_conusf.*grib2 + gens_naefs.*_naefs_gespr.*ndgd_conusf.*grib2 naefsDervUS - naefs_gemode.*ndgd_conusf.*grib2 + gens_naefs.*_naefs_gemode.*ndgd_conusf.*grib2 naefsModeUS - naefs_ge10pt.*ndgd_conusf.*grib2 + gens_naefs.*_naefs_ge10pt.*ndgd_conusf.*grib2 naefs10ptUS - naefs_ge50pt.*ndgd_conusf.*grib2 + gens_naefs.*_naefs_ge50pt.*ndgd_conusf.*grib2 naefs50ptUS - naefs_ge90pt.*ndgd_conusf.*grib2 + gens_naefs.*_naefs_ge90pt.*ndgd_conusf.*grib2 naefs90ptUS - naefs_geavg.*ndgd_alaskaf.*grib2 + gens_naefs.*_naefs_geavg.*ndgd_alaskaf.*grib2 naefsDervAK - naefs_gespr.*ndgd_alaskaf.*grib2 + gens_naefs.*_naefs_gespr.*ndgd_alaskaf.*grib2 naefsDervAK - naefs_gemode.*ndgd_alaskaf.*grib2 + gens_naefs.*_naefs_gemode.*ndgd_alaskaf.*grib2 naefsModeAK - naefs_ge10pt.*ndgd_alaskaf.*grib2 + gens_naefs.*_naefs_ge10pt.*ndgd_alaskaf.*grib2 naefs10ptAK - naefs_ge50pt.*ndgd_alaskaf.*grib2 + gens_naefs.*_naefs_ge50pt.*ndgd_alaskaf.*grib2 naefs50ptAK - naefs_ge90pt.*ndgd_alaskaf.*grib2 + gens_naefs.*_naefs_ge90pt.*ndgd_alaskaf.*grib2 naefs90ptAK - sref_em.*132.ctl.* + sref_sref.*_sref_em.*132.ctl.* sref16EM - sref_em.*132.[pn][1-3].* + sref_sref.*_sref_em.*132.[pn][1-3].* sref16EM - sref_nmb.*132.ctl.* + sref_sref.*_sref_nmb.*132.ctl.* sref16NMB - sref_nmb.*132.[pn][1-3].* + sref_sref.*_sref_nmb.*132.[pn][1-3].* sref16NMB - sref_nmm.*132.ctl.* + sref_sref.*_sref_nmm.*132.ctl.* sref16NMM - sref_nmm.*132.[pn][1-3].* + sref_sref.*_sref_nmm.*132.[pn][1-3].* sref16NMM - sref.*132.mean.* + sref_sref.*_sref.*132.mean.* sref16Derv - sref.*132.prob.* + sref_sref.*_sref.*132.prob.* sref16Derv - sref.*132.spread.* + sref_sref.*_sref.*132.spread.* sref16Derv - sref_em.*212.ctl.* + sref_sref.*_sref_em.*212.ctl.* sref40EM - sref_em.*212.[pn][1-3].* + sref_sref.*_sref_em.*212.[pn][1-3].* sref40EM - sref_nmb.*212.ctl.* + sref_sref.*_sref_nmb.*212.ctl.* sref40NMB - sref_nmb.*212.[pn][1-3].* + sref_sref.*_sref_nmb.*212.[pn][1-3].* sref40NMB - sref_nmm.*212.ctl.* + sref_sref.*_sref_nmm.*212.ctl.* sref40NMM - sref_nmm.*212.[pn][1-3].* + sref_sref.*_sref_nmm.*212.[pn][1-3].* sref40NMM - sref.*212.mean.* + sref_sref.*_sref.*212.mean.* sref40Derv - sref.*212.prob.* + sref_sref.*_sref.*212.prob.* sref40Derv - sref.*212.spread.* + sref_sref.*_sref.*212.spread.* sref40Derv diff --git a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java index 24c4b13a74..77f060bd0a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java +++ b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecompressor.java @@ -19,11 +19,15 @@ **/ package com.raytheon.edex.plugin.radar; +import java.io.ByteArrayInputStream; +import java.nio.ByteBuffer; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.DataFormatException; import java.util.zip.Inflater; +import org.itadaki.bzip2.BZip2InputStream; + import com.raytheon.edex.esb.Headers; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -42,6 +46,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Jul 16, 2012 DR 14723 D.Friedman Decompress files atomically * Mar 20, 2013 1804 bsteffen Switch all radar decompressing to be in * memory. + * Aug 20, 2013 16157 wkwock Add bunzip2 cabability. * * * @@ -104,13 +109,27 @@ public class RadarDecompressor { wmoHeaderSize, radarData.length); radarData = radarDataWithHeader; } - } else if (!keepHeader && wmoHeaderSize > 0) { - // strip the header. - radarData = new byte[messageData.length - wmoHeaderSize]; - System.arraycopy(messageData, wmoHeaderSize, radarData, 0, - radarData.length); } else { - radarData = messageData; + radarData = decompressBzip2 (messageData, wmoHeaderSize, headers); + if (radarData !=null) { + if (keepHeader) { + // put the header back on. + byte[] radarDataWithHeader = new byte[radarData.length + + wmoHeaderSize]; + System.arraycopy(messageData, 0, radarDataWithHeader, 0, + wmoHeaderSize); + System.arraycopy(radarData, 0, radarDataWithHeader, + wmoHeaderSize, radarData.length); + radarData = radarDataWithHeader; + } + } else if (!keepHeader && wmoHeaderSize > 0) { + // strip the header. + radarData = new byte[messageData.length - wmoHeaderSize]; + System.arraycopy(messageData, wmoHeaderSize, radarData, 0, + radarData.length); + } else { + radarData = messageData; + } } } catch (Exception e) { theHandler.handle(Priority.ERROR, "Failed decompression on " @@ -152,6 +171,33 @@ public class RadarDecompressor { return false; } + /** + * Checks to see if inBuf has bzip2 compressed block. + * 0-inOff in inBuf is WMO header. + * (inOff+1) - (inOff+120) is nexrad_header(18 bytes) + + * s_product_description_block (102 bytes) + * And inBuf[inOff+121 to inOff+123] is 'BZh' then it most likely is bzip2 + * compressed. + * Also see AWIPS I RadarDecompress.c for more info. + * + * @param inBuf + * the data buffer + * @param inOff + * the offset into the buffer + * @return true if data is bzip2 compressed + */ + private boolean isBzip2Compressed(byte[] inBuf, int inOff) { + if ((inBuf==null) || (inOff < 0) || ((inOff +120) >= inBuf.length)) { + return false; + } + + if (inBuf[inOff+120]== 'B' && inBuf[inOff+121]== 'Z' && inBuf[inOff+122]== 'h') { + return true; + } + + return false; + } + private int findStartRadarData(String headerInfo) { int startOfRadarData = 0; Matcher matcher = WMO_PATTERN.matcher(headerInfo); @@ -222,4 +268,40 @@ public class RadarDecompressor { return outBuf; } + + /** + * Method to handle bzip2 compressed radar data. If data is not compressed it is + * just copied to the output buffer. + * + * @return The decompressed byte array for the radar data + * or null if not decompressed + */ + private byte[] decompressBzip2(byte[] inBuf, int offset, Headers headers) { + byte[] outBuf = null; + + if (isBzip2Compressed(inBuf, offset)) { + byte[] tmpBuf= new byte[inBuf.length-offset-120]; + System.arraycopy(inBuf, offset+120, tmpBuf, 0, tmpBuf.length); + ByteArrayInputStream is = new ByteArrayInputStream(tmpBuf); + BZip2InputStream bis= new BZip2InputStream(is,false); + try { + //use 10x85716 should be safe + byte[] tmpBuf2= new byte[860000]; + int actualByte=bis.read(tmpBuf2); + bis.close(); + outBuf = new byte[actualByte+120]; + //the 120 bytes:description block and symbology block + System.arraycopy(inBuf, offset, outBuf, 0, 8); + byte[] lengthMsg2=ByteBuffer.allocate(4).putInt(outBuf.length).array(); + System.arraycopy(lengthMsg2, 0, outBuf, 8, 4); + System.arraycopy(inBuf, offset+8+4, outBuf, 12, 108); + + System.arraycopy(tmpBuf2, 0, outBuf, 120, actualByte); + } catch (Exception e) { + theHandler.handle(Priority.ERROR, + "Failed to decompress " + headers.get("ingestfilename")); + } + } + return outBuf; + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/decoder/synoptic/SynopticSec2Decoder.java b/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/decoder/synoptic/SynopticSec2Decoder.java index aad27be948..1e577dd73b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/decoder/synoptic/SynopticSec2Decoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.sfcobs/src/com/raytheon/edex/plugin/sfcobs/decoder/synoptic/SynopticSec2Decoder.java @@ -46,6 +46,7 @@ import com.raytheon.uf.edex.decodertools.core.ReportParser; * ------------ ---------- ----------- -------------------------- * 20071010 391 jkorman Initial coding. * 20071109 391 jkorman Added guard for short data. + * 2013/8 757 T. Lee Checked missing wave height from ship report * * * @@ -254,7 +255,7 @@ public class SynopticSec2Decoder extends AbstractSectionDecoder { wavePeriod = null; } } - if(waveHeight != null) { + if((waveHeight != null) && (waveHeight >=0) ) { receiver.setWaveHeight(waveHeight.doubleValue() * 0.5); } if(windWavePeriod != null) { @@ -265,7 +266,7 @@ public class SynopticSec2Decoder extends AbstractSectionDecoder { windWavePeriod = null; } } - if(windWaveHeight != null) { + if((windWaveHeight != null) && (windWaveHeight >=0) ) { receiver.setWindWaveHeight(windWaveHeight.doubleValue() * 0.5); } if ((wavePeriod != null) && (waveHeight != null)) { diff --git a/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py b/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py index e08ef12a8f..3c051d366c 100644 --- a/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py +++ b/edexOsgi/com.raytheon.edex.plugin.warning/WarningDecoder.py @@ -34,6 +34,7 @@ # Feb 19, 2013 1636 rferrel Use TimeTools to get file timestamp. # May 07, 2013 1973 rferrel Adjust Issue and Purge times to be relative to start time. # Jun 24, 2013 DR 16317 D. Friedman If no storm line, parse storm motion from event text. +# Aug 21, 2013 DR16501 m.gamazaychikov Adjusted calculation of Purge time in NoVTECWarningDecoder. # # # @author rferrel @@ -986,7 +987,7 @@ class NoVTECWarningDecoder(StdWarningDecoder): if self._officeFromWMO: template['officeid'] = self._officeFromWMO - template['purgeTime'] = long(purgeTime * 1000) + template['purgeTime'] = long(self._dtgFromDDHHMM(purgeTime, self._issueTime)*1000) template['issueTime'] = long(self._issueTime * 1000) template['state'] = "Decoded" template['xxxid'] = self._completeProductPil[3:] diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java index 837db25cfc..cc32ea8dee 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.ffmp/src/com/raytheon/uf/common/dataplugin/ffmp/FFMPBasinData.java @@ -688,7 +688,6 @@ public class FFMPBasinData implements ISerializableObject { * @param times */ public void populate(List times) { - if (mapFactory == null) { mapFactory = new BasinMapFactory(Collections.reverseOrder(), getBasins().size()); diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/RemapGrid.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/RemapGrid.java index 60666d9995..e14788f32c 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/RemapGrid.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/RemapGrid.java @@ -66,6 +66,8 @@ import com.vividsolutions.jts.geom.Coordinate; * 02/19/13 #1637 randerso Fixed remapping of byte grids * 07/09/13 #2044 randerso Made SoftReferences to interp and rotation since * they can be quite large and may not be needed frequently + * 08/27/13 #2287 randerso Removed 180 degree adjustment required by error + * in Maputil.rotation * 07/17/13 #2185 bsteffen Cache computed grid reprojections. * 08/13/13 #1571 randerso Passed fill values into interpolator. * @@ -642,8 +644,8 @@ public class RemapGrid { for (int y1 = 0; y1 < rotation.getYdim(); y1++) { Coordinate llc = destinationGloc .latLonCenter(new Coordinate(x1, y1)); - rotation.set(x1, y1, (float) (180 - MapUtil.rotation( - llc, sourceGloc))); + rotation.set(x1, y1, + (float) (-MapUtil.rotation(llc, sourceGloc))); } } rotationRef = new SoftReference(rotation); diff --git a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/MapUtil.java b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/MapUtil.java index f16cd33f5f..167a7bcfa5 100644 --- a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/MapUtil.java +++ b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/MapUtil.java @@ -94,6 +94,8 @@ import com.vividsolutions.jts.geom.Polygon; * 06/19/2012 14988 D. Friedman Make oversampling more like AWIPS 1 * 09/18/2012 #1091 randerso corrected getBoundingEnvelope * 11/06/2012 15406 ryu Added convertToNativeEnvelope() + * 08/27/2013 #2287 randerso Fixed rotation methods so it is not necessary + * to subtract 180 from the returned value * * * @@ -1062,12 +1064,13 @@ public class MapUtil { * the right of UP is north (or 360) degrees. * * @param latLon + * @param spatialObject * @return rotation angle */ public static double rotation(Coordinate latLon, ISpatialObject spatialObject) { - double newLatLonY = latLon.y + 0.05; + double newLatLonY = latLon.y - 0.05; if (newLatLonY > 90) { newLatLonY -= 180; } @@ -1098,11 +1101,12 @@ public class MapUtil { * the right of UP is north (or 360) degrees. * * @param latLon + * @param geometry * @return rotation angle */ public static double rotation(Coordinate latLon, GridGeometry2D geometry) { - double newLatLonY = latLon.y + 0.05; + double newLatLonY = latLon.y - 0.05; if (newLatLonY > 90) { newLatLonY -= 180; } diff --git a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/TransformFactory.java b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/TransformFactory.java index 4794b34e7f..6927b428e9 100644 --- a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/TransformFactory.java +++ b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/TransformFactory.java @@ -20,6 +20,7 @@ package com.raytheon.uf.common.geospatial; import org.geotools.coverage.grid.GeneralGridGeometry; +import org.geotools.referencing.CRS; import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.geotools.referencing.operation.transform.IdentityTransform; import org.opengis.referencing.FactoryException; @@ -166,6 +167,27 @@ public class TransformFactory { return factory.createConcatenatedTransform(mt1, mt2); } + /** + * Constructs a transform from the "world" CRS of the crs passed in. null + * will be returned if no "world" crs exists. + * + * @param crs + * @return + * @throws FactoryException + */ + public static MathTransform worldToCRS(CoordinateReferenceSystem crs) + throws FactoryException { + CoordinateReferenceSystem worldCRS = crs; + while (worldCRS instanceof GeneralDerivedCRS) { + GeneralDerivedCRS derivedCRS = (GeneralDerivedCRS) worldCRS; + worldCRS = derivedCRS.getBaseCRS(); + } + if (worldCRS != crs) { + return CRS.findMathTransform(worldCRS, crs); + } + return null; + } + /** * Constructs a transform from the "world" CRS of the target geometry to the * grid of the targetGeometry. Will return crsToGrid if no "world" CRS @@ -178,23 +200,19 @@ public class TransformFactory { */ public static MathTransform worldToGrid(GeneralGridGeometry targetGeometry, PixelInCell cellType) throws FactoryException { - CoordinateReferenceSystem crs = targetGeometry.getEnvelope() - .getCoordinateReferenceSystem(); try { - if (crs instanceof GeneralDerivedCRS) { - GeneralDerivedCRS projCRS = (GeneralDerivedCRS) crs; - CoordinateReferenceSystem worldCRS = projCRS.getBaseCRS(); - MathTransform worldToCRS = CRSCache.getInstance() - .findMathTransform(worldCRS, crs); - - MathTransform crsToPixel = targetGeometry - .getGridToCRS(cellType).inverse(); - return factory.createConcatenatedTransform(worldToCRS, - crsToPixel); - } else { - // No associated "world" CRS, go straight crs to grid - return targetGeometry.getGridToCRS(cellType).inverse(); + CoordinateReferenceSystem crs = targetGeometry.getEnvelope() + .getCoordinateReferenceSystem(); + MathTransform worldToCRS = worldToCRS(crs); + MathTransform worldToGrid = targetGeometry.getGridToCRS(cellType) + .inverse(); + if (worldToCRS != null) { + worldToGrid = factory.createConcatenatedTransform(worldToCRS, + worldToGrid); } + return worldToGrid; + } catch (FactoryException e) { + throw e; } catch (Exception e) { throw new FactoryException(e); } diff --git a/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java index 6d0cd35200..d613a2c985 100644 --- a/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java +++ b/edexOsgi/com.raytheon.uf.edex.distribution/src/com/raytheon/uf/edex/distribution/DistributionSrv.java @@ -61,6 +61,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Feb 27, 2013 1638 mschenke Cleaned up localization code to fix null pointer * when no distribution files present * Mar 19, 2013 1794 djohnson PatternWrapper is immutable, add toString() to it for debugging. + * Aug 19, 2013 2257 bkowal edexBridge to qpid 0.18 upgrade * * * @@ -73,6 +74,8 @@ public class DistributionSrv { private static final IUFStatusHandler statusHandler = UFStatus .getHandler(DistributionSrv.class); + private static final String HEADER_QPID_SUBJECT = "qpid.subject"; + private static class PatternWrapper { private final String plugin; @@ -223,7 +226,15 @@ public class DistributionSrv { StringBuilder pluginNames = new StringBuilder(); List dest = new ArrayList(); Message in = exchange.getIn(); - String header = (String) in.getHeader("header"); + // determine if the header is in the qpid subject field? + String header = (String) in.getHeader(HEADER_QPID_SUBJECT); + if (header != null) { + // make the qpid subject the header so that everything downstream + // will be able to read it as the header. + in.setHeader("header", header); + } + + header = (String) in.getHeader("header"); Object payload = in.getBody(); String bodyString = null; if (payload instanceof byte[]) { @@ -277,8 +288,8 @@ public class DistributionSrv { throws DistributionException { RequestPatterns patternSet = null; try { - patternSet = SerializationUtil - .jaxbUnmarshalFromXmlFile(RequestPatterns.class, modelFile.getPath()); + patternSet = SerializationUtil.jaxbUnmarshalFromXmlFile( + RequestPatterns.class, modelFile.getPath()); } catch (Exception e) { throw new DistributionException("File " + modelFile.getAbsolutePath() diff --git a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java index 4a205c7e9e..2d852ff443 100644 --- a/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java +++ b/edexOsgi/com.raytheon.uf.edex.esb.camel/src/com/raytheon/uf/edex/esb/camel/cluster/quartz/ClusteredQuartzEndpoint.java @@ -39,6 +39,7 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Feb 19, 2010 njensen Initial creation + * Aug 21, 2013 DR 16521 D. Friedman Ensure endpoint URI is used for cluster entry * * * @@ -61,7 +62,7 @@ public class ClusteredQuartzEndpoint extends QuartzEndpoint { @Override public void onJobExecute(final JobExecutionContext jobExecutionContext) throws JobExecutionException { - String jName = jobExecutionContext.getJobDetail().getName(); + String jName = getEndpointUri(); long period = Math.abs(jobExecutionContext.getFireTime().getTime() - jobExecutionContext.getNextFireTime().getTime()) / 2; ClusterTask ct = ClusterLockUtils.lock(TASK, jName, period, false); diff --git a/edexOsgi/com.raytheon.uf.tools.cli/impl/gpd b/edexOsgi/com.raytheon.uf.tools.cli/impl/gpd new file mode 100644 index 0000000000..1516d0ffed --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.cli/impl/gpd @@ -0,0 +1,34 @@ +#!/bin/bash +## +## +############################################################################## +# This script allows users to query point data database from EDEX. +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 05/20/2013 Chin Chen Initial Creation. +############################################################################## + +# this allows you to run this script from outside of ./bin +path_to_script=`readlink -f $0` +RUN_FROM_DIR=`dirname $path_to_script` + +BASE_AWIPS_DIR=`dirname $RUN_FROM_DIR` + +# get the base environment +source ${RUN_FROM_DIR}/setup.env + +# setup the environment needed to run the the Python +export LD_LIBRARY_PATH=${BASE_AWIPS_DIR}/src/lib:${PYTHON_INSTALL}/lib +export PYTHONPATH=${RUN_FROM_DIR}/src:$PYTHONPATH + +# execute the ifpInit Python module +_PYTHON="${PYTHON_INSTALL}/bin/python" +_MODULE="${RUN_FROM_DIR}/src/gpd/gpd.py" + +# quoting of '$@' is used to prevent command line interpretation +#$_PYTHON $_MODULE -h ${DEFAULT_HOST} -p ${DEFAULT_PORT} "$@" +$_PYTHON $_MODULE "$@" + diff --git a/edexOsgi/com.raytheon.uf.tools.cli/impl/src/gpd/GpdCliRequestHandler.py b/edexOsgi/com.raytheon.uf.tools.cli/impl/src/gpd/GpdCliRequestHandler.py new file mode 100644 index 0000000000..b1405ef5f8 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.cli/impl/src/gpd/GpdCliRequestHandler.py @@ -0,0 +1,117 @@ +## +# This script is used to send GPD request to EDEX. +# +# Users can override the default EDEX server and port name by specifying them +# in the $DEFAULT_HOST and $DEFAULT_PORT shell environment variables. +# +# 5/22/2013 Chin J. Chen +## +import os +from dynamicserialize.dstypes.gov.noaa.nws.ncep.common.dataplugin.gpd.query import GenericPointDataReqMsg +from ufpy import ThriftClient + + +class GpdCliRequestHandler: + """ Request Activity to EDEX.""" + + def __init__(self): + self.host = os.getenv("DEFAULT_HOST", "localhost") + self.port = os.getenv("DEFAULT_PORT", "9581") + self.client = ThriftClient.ThriftClient(self.host, self.port) + + def getGpdProdInfo(self, prodName, reqType): + req = GenericPointDataReqMsg() + req.setReqType(reqType) + req.setProductName(prodName) + resp = self.client.sendRequest(req) + return resp + + def getGpdProduct(self, refTime,prodName , reqType,querySpecifiedProductVersion=None,versionNum=None ): + req = GenericPointDataReqMsg() + req.setReqType(reqType) + req.setRefTime(refTime) + req.setProductName(prodName) + if (querySpecifiedProductVersion!= None and versionNum !=None): + req.setQuerySpecifiedProductVersion(querySpecifiedProductVersion) + req.setProductVersion(versionNum) + resp = self.client.sendRequest(req) + return resp + + + def getGpdStationProduct(self, stnId, refTime,prodName , reqType,querySpecifiedProductVersion=None,versionNum=None ): + req = GenericPointDataReqMsg() + req.setReqType(reqType) + req.setStnId(stnId) + req.setRefTime(refTime) + req.setProductName(prodName) + if (querySpecifiedProductVersion!= None and versionNum !=None): + req.setQuerySpecifiedProductVersion(querySpecifiedProductVersion) + req.setProductVersion(versionNum) + resp = self.client.sendRequest(req) + return resp + + def getGpdMovingProduct(self, slat, slon, refTime,prodName , reqType,querySpecifiedProductVersion=None,versionNum=None ): + req = GenericPointDataReqMsg() + req.setReqType(reqType) + req.setSlon(slon) + req.setSlat(slat) + req.setRefTime(refTime) + req.setProductName(prodName) + if (querySpecifiedProductVersion!= None and versionNum !=None): + req.setQuerySpecifiedProductVersion(querySpecifiedProductVersion) + req.setProductVersion(versionNum) + resp = self.client.sendRequest(req) + return resp + + def storeGpdGempakProduct(self, gpdGempak, prodName, maxNumLevel,versionNum): + req = GenericPointDataReqMsg() + req.setReqType("STORE_GPD_PRODUCT_FROM_GEMPAK_TBL") + req.setGpdDataString(gpdGempak) + req.setProductName(prodName) + req.setProductVersion(versionNum) + req.setMaxNumLevel(maxNumLevel) + resp = self.client.sendRequest(req) + return resp + + def storeGpdXmlProduct(self, gpdXml): + req = GenericPointDataReqMsg() + req.setReqType("STORE_GPD_PRODUCT_FROM_XML") + req.setGpdDataString(gpdXml) + resp = self.client.sendRequest(req) + return resp + + def storeGpdProductInfo(self, gpdXml): + req = GenericPointDataReqMsg() + req.setReqType("STORE_GPD_PRODUCT_INFO_FROM_XML") + req.setGpdDataString(gpdXml) + resp = self.client.sendRequest(req) + return resp + ''' + def purgeGpdProd(self, prodName, refTime=None, all=None): + req = GenericPointDataReqMsg() + if(all == "yes"): + req.setReqType("PURGE_GPD_PRODUCT_ALLTIME") + else: + req.setReqType("PURGE_GPD_PRODUCT_ONETIME") + if(refTime!=None): + req.setRefTime(refTime) + else: + return "reference time required for purging" + req.setProductName(prodName) + + resp = self.client.sendRequest(req) + return resp + ''' + def purgeGpdExpired(self): + req = GenericPointDataReqMsg() + req.setReqType("PURGE_GPD_EXPIRED_PRODUCT") + resp = self.client.sendRequest(req) + return resp + + def purgeGpdAll(self): + req = GenericPointDataReqMsg() + req.setReqType("PURGE_GPD_ALL_PRODUCTS") + resp = self.client.sendRequest(req) + return resp + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.tools.cli/impl/src/gpd/gpd.py b/edexOsgi/com.raytheon.uf.tools.cli/impl/src/gpd/gpd.py new file mode 100644 index 0000000000..e0bdc4e7e5 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.cli/impl/src/gpd/gpd.py @@ -0,0 +1,695 @@ +## +# This script is used to query Generic Point Data database from EDEX. +# +# 5/22/2013 Chin J. Chen +## +import io +import logging +import sys +import time +import GpdCliRequestHandler +from ufpy import UsageArgumentParser +from dynamicserialize.dstypes.gov.noaa.nws.ncep.common.dataplugin.gpd.query import GenericPointDataReqMsg +from dynamicserialize.dstypes.java.util import Date + +logger = None +parser = None +USAGE_MESSAGE = \ +""" + + gpd qix --p prodName --f filePath + + gpd qixl --p prodName + + gpd qpx --p prodName --t referenceTime [--f filePath --v versionNum] + + gpd qpxl --p prodName --t referenceTime [--v versionNum] + + gpd qsx --p prodName --t referenceTime --id stationId [--f filePath --v versionNum] + + gpd qsxl --p prodName --t referenceTime --id stationId [--v versionNum] + + gpd qmx --p prodName --t referenceTime --slat latitude --slon longitude [--f filePath --v versionNum] + + gpd qmxl --p prodName --t referenceTime --slat latitude --slon longitude [--v versionNum] + + + gpd spx --f filePath + + gpd spg --f filePath --p prodName [--v versionNum] + + gpd pe + + gpd pa + + gpd u + ####### + NOTE: referenceTime string format yyyy-mm-dd HH:MM:SS, for example "2013-05-21 20:30:00" + filePath - required when saving Gempak table or XML file + filePath - optional when querying, if not provided, result will be saved at current directory + versionNum - optional, if not provided, latest version is returned + ####### +""" +SUBCOMMAND_MESSAGE = \ +""" + qix: To query product information, result saved at optional filePath + qixl: To query and list product information + qpx: To query a product (all stations), result saved at optional filePath + qpxl: To query and list a product (all stations) + qsx: To query a station product, result saved at optional filePath + qsxl: To query and list a station product + qmx: To query a moving product, result saved at optional filePath + qmxl: To query and print a moving product + spx: To store product XML file to EDEX server database + spg: To store product GEMPAk table file to EDEX server database + pe: To purge expired products + pa: To purge all products + u: To print usage +""" +''' + gpd qig --p prodName --f filePath + + gpd qigl --p prodName + + gpd qpg --p prodName --t referenceTime [--f filePath --v versionNum] + + gpd qpgl --p prodName --t referenceTime [--v versionNum] + + gpd qsg --p prodName --t referenceTime --id stationId [--f filePath --v versionNum] + + gpd qsgl --p prodName --t referenceTime --id stationId [--v versionNum] + + gpd qmg --p prodName --t referenceTime --slat latitude --slon longitude [--f filePath --v versionNum] + + gpd qmgl --p prodName --t referenceTime --slat latitude --slon longitude [--v versionNum] + + qig: To query product information, result saved at optional filePath + qigl: To query and list product information + qpg: To query a product (all stations), result saved at optional filePath + qpgl: To query and list a product (all stations) + qsg: To query a station product, result saved at optional filePath + qsgl: To query and list a station product + qmg: To query a moving product, result saved at optional filePath + qmgl: To query and print a moving product +''' +def __initLogger(): + global logger + logger = logging.getLogger("gpd") + logger.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + # Uncomment line below to enable debug-level logging + ch.setLevel(logging.DEBUG) + formatter = logging.Formatter("\n%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S") + ch.setFormatter(formatter) + logger.addHandler(ch) + +def __parseCommandLine(): + global parser + parser = UsageArgumentParser.UsageArgumentParser(prog='gpd',description="Query or store point data database from EDEX.")#, usage=USAGE_MESSAGE) + #parser.add_argument("-u", action="help", + # help="show usage") + + subparsers = parser.add_subparsers(help=USAGE_MESSAGE) + + #to print usage + parser_usage = subparsers.add_parser('u') + parser_usage.set_defaults(func=__printUsage) + + #To update/replace product information + #parser_saveinfo = subparsers.add_parser('si') + #parser_saveinfo.add_argument("--f", dest="filePath", action="store",required=True, + # help=":target file path for return product") + #parser_saveinfo.set_defaults(func=__saveProdInfo) + + #To save a GPD product in XML format + parser_saveprod_xml = subparsers.add_parser('spx') + parser_saveprod_xml.add_argument("--f", dest="filePath", action="store",required=True, + help=":target file path for return product") + parser_saveprod_xml.set_defaults(func=__saveProdXml) + + #To save a GPD product in GEMPAk table format + parser_saveprod_gempak = subparsers.add_parser('spg') + parser_saveprod_gempak.add_argument("--f", dest="filePath", action="store",required=True, + help=":target file path for return product") + parser_saveprod_gempak.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_saveprod_gempak.add_argument("--l", dest="maxNumLevel", action="store",required=True, + help=":max number of level for product") + parser_saveprod_gempak.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_saveprod_gempak.set_defaults(func=__saveProdGempak) + + #To query product information + parser_infoXml = subparsers.add_parser('qix') + parser_infoXml.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_infoXml.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_infoXml.set_defaults(func=__getProdInfoXml) + + parser_info_printXml = subparsers.add_parser('qixl') + parser_info_printXml.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + #parser_info_printXml.add_argument("--f", dest="filePath", action="store", + # help=":target file path for return product") + parser_info_printXml.set_defaults(func=__getPrintProdInfoXml) + ''' + parser_infoGempak = subparsers.add_parser('qig') + parser_infoGempak.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_infoGempak.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_infoGempak.set_defaults(func=__getProdInfoGempak) + + parser_info_printGempak = subparsers.add_parser('qigl') + parser_info_printGempak.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_info_printGempak.set_defaults(func=__getPrintProdInfoGempak) + ''' + #To query a station product (single station) + parser_stnProdXml = subparsers.add_parser('qsx') + parser_stnProdXml.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_stnProdXml.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_stnProdXml.add_argument("--id", dest="stnId", action="store",required=True, + help=":station id of a product") + parser_stnProdXml.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_stnProdXml.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_stnProdXml.set_defaults(func=__getStnProdXml) + + parser_stnProdXml_print = subparsers.add_parser('qsxl') + parser_stnProdXml_print.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_stnProdXml_print.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_stnProdXml_print.add_argument("--id", dest="stnId", action="store",required=True, + help=":station id of a product") + parser_stnProdXml_print.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_stnProdXml_print.set_defaults(func=__getPrintStnProdXml) + + ''' + parser_stnProdGempak = subparsers.add_parser('qsg') + parser_stnProdGempak.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_stnProdGempak.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_stnProdGempak.add_argument("--id", dest="stnId", action="store",required=True, + help=":station id of a product") + parser_stnProdGempak.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_stnProdGempak.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_stnProdGempak.set_defaults(func=__getStnProdGempak) + + parser_stnProdGempak_print = subparsers.add_parser('qsgl') + parser_stnProdGempak_print.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_stnProdGempak_print.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_stnProdGempak_print.add_argument("--id", dest="stnId", action="store",required=True, + help=":station id of a product") + parser_stnProdGempak_print.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_stnProdGempak_print.set_defaults(func=__getPrintStnProdGempak) + ''' + #To query a moving product + parser_movingProdXml = subparsers.add_parser('qmx') + parser_movingProdXml.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_movingProdXml.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_movingProdXml.add_argument("--slat", dest="slat", type=float, action="store",required=True, + help=":latitude of a moving product") + parser_movingProdXml.add_argument("--slon", dest="slon", type=float, action="store",required=True, + help=":longitude of a moving product") + parser_movingProdXml.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_movingProdXml.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_movingProdXml.set_defaults(func=__getMovingProdXml) + + parser_movingProdXml_print = subparsers.add_parser('qmxl') + parser_movingProdXml_print.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_movingProdXml_print.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_movingProdXml_print.add_argument("--slat", dest="slat", type=float, action="store",required=True, + help=":latitude of a moving product") + parser_movingProdXml_print.add_argument("--slon", dest="slon", type=float, action="store",required=True, + help=":longitude of a moving product") + parser_movingProdXml_print.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_movingProdXml_print.set_defaults(func=__getPrintMovingProdXml) + + ''' + parser_movingProdGempak = subparsers.add_parser('qmg') + parser_movingProdGempak.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_movingProdGempak.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_movingProdGempak.add_argument("--slat", dest="slat", type=float, action="store",required=True, + help=":latitude of a moving product") + parser_movingProdGempak.add_argument("--slon", dest="slon", type=float, action="store",required=True, + help=":longitude of a moving product") + parser_movingProdGempak.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_movingProdGempak.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_movingProdGempak.set_defaults(func=__getMovingProdGempak) + + parser_movingProdGempak_print = subparsers.add_parser('qmgl') + parser_movingProdGempak_print.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_movingProdGempak_print.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_movingProdGempak_print.add_argument("--slat", dest="slat", type=float, action="store",required=True, + help=":latitude of a moving product") + parser_movingProdGempak_print.add_argument("--slon", dest="slon", type=float, action="store",required=True, + help=":longitude of a moving product") + parser_movingProdGempak_print.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_movingProdGempak_print.set_defaults(func=__getPrintMovingProdGempak) + ''' + + #To query a product + parser_prodXml = subparsers.add_parser('qpx') + parser_prodXml.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_prodXml.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_prodXml.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_prodXml.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_prodXml.set_defaults(func=__getProdXml) + + ''' + parser_prodGempak = subparsers.add_parser('qpg') + parser_prodGempak.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_prodGempak.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_prodGempak.add_argument("--f", dest="filePath", action="store", + help=":target file path for return product") + parser_prodGempak.add_argument("--v", dest="versionNum", action="store", + help=":product version") + parser_prodGempak.set_defaults(func=__getProdGempak) + ''' + parser_prodXml_print = subparsers.add_parser('qpxl') + parser_prodXml_print.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_prodXml_print.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_prodXml_print.add_argument("--v", dest="versionNum", action="store", + help=":product version") + + parser_prodXml_print.set_defaults(func=__getPrintProdXml) + ''' + parser_prodGempak_print = subparsers.add_parser('qpgl') + parser_prodGempak_print.add_argument("--p", dest="prodName", action="store",required=True, + help=":name of a Generic Point Data product") + parser_prodGempak_print.add_argument("--t", dest="refTime", action="store",required=True, + help=":reference time of a product") + parser_prodGempak_print.add_argument("--v", dest="versionNum", action="store", + help=":product version") + + parser_prodGempak_print.set_defaults(func=__getPrintProdGempak) + ''' + + ''' + #parser_purge_prod = subparsers.add_parser('pp') + #parser_purge_prod.add_argument("--p", dest="prodName", action="store",required=True, + # help=":name of a Generic Point Data product") + #parser_purge_prod.add_argument("--t", dest="refTime", action="store", + # help=":reference time of a product") + #parser_purge_prod.add_argument("--all", dest="all", action="store", + # help=":yes") + #parser_purge_prod.set_defaults(func=__purgeProd) + ''' + + parser_purge_expired = subparsers.add_parser('pe') + parser_purge_expired.set_defaults(func=__purgeExpired) + + parser_purge_all = subparsers.add_parser('pa') + parser_purge_all.set_defaults(func=__purgeAll) + + options = parser.parse_args() + + #logger.debug("Command-line arguments: " + str(options)) + return options + +def __convertTimeToDate(refTime): + struct_time = time.strptime(refTime, "%Y-%m-%d %H:%M:%S") + #print "returned tuple: %s " % struct_time + #print "timeZone " + str(time.timezone) + " altimezone " + str(time.altzone) + milsec = (time.mktime(struct_time)-time.altzone) * 1000 + date= Date() + date.setTime(milsec) + #print "time in msec: %s" % str(date.getTime()) + return date + +def __createFilenameStringXml(name, refTime): + filename = name + '@'+ refTime.replace(" ","@")+".xml" + return filename + +def __createFilenameStringGempak(name, refTime): + filename = name + '@'+ refTime.replace(" ","@")+".gempak" + return filename + +def __getPrintProdInfoXml(options): + req= GpdCliRequestHandler.GpdCliRequestHandler() + prodInfo = req.getGpdProdInfo(options.prodName, "GET_GPD_PRODUCT_INFO_XML") + if(prodInfo != None): + print(prodInfo) + else: + print("Query failed!") + +def __getProdInfoXml(options): + #if options.prodName == None: + # parser.print_help() + # return None + req= GpdCliRequestHandler.GpdCliRequestHandler() + prodInfo = req.getGpdProdInfo(options.prodName,"GET_GPD_PRODUCT_INFO_XML") + if(prodInfo != None): + if(options.filePath == None): + f = open(options.prodName+"Info.xml",'w') + else: + f = open(options.filePath,'w') + f.write(prodInfo) + return prodInfo + else: + print("Query failed!") + return None + +def __getPrintProdInfoGempak(options): + req= GpdCliRequestHandler.GpdCliRequestHandler() + prodInfo = req.getGpdProdInfo(options.prodName, "GET_GPD_PRODUCT_INFO_GEMPAK_TBL") + if(prodInfo != None): + print(prodInfo) + else: + print("Query failed!") + +def __getProdInfoGempak(options): + #if options.prodName == None: + # parser.print_help() + # return None + req= GpdCliRequestHandler.GpdCliRequestHandler() + prodInfo = req.getGpdProdInfo(options.prodName,"GET_GPD_PRODUCT_INFO_GEMPAK_TBL") + if(prodInfo != None): + if(options.filePath == None): + f = open(options.prodName+"Info.gempak",'w') + else: + f = open(options.filePath,'w') + f.write(prodInfo) + return prodInfo + else: + print("Query failed!") + return None + + #=========================================================================== + # print ("GPD Report::::::::::::::") + # print str("Report Name: "+ prodInfo.getName()) + # print str("Master Level Name = " + prodInfo.getMasterLevel().getName()) + # print str("Master Level Description = " + prodInfo.getMasterLevel().getDescription()) + # print str("Master Level Type = " + prodInfo.getMasterLevel().getType()) + # print str("Master Level Unit String = " + prodInfo.getMasterLevel().getUnitString()) + # print ("Max NUmber of Level = " + str(prodInfo.getMaxNumberOfLevel())) + # print ("Parameters:") + # parmLst =prodInfo.getParameterLst() + # i = 1 + # for parm in parmLst: + # print ("Parameter "+ str(i)+ ": Abbreviation="+ str(parm.getAbbreviation())+ " Unit="+str(parm.getUnitString())+ " Name =" + str(parm.getName())) + # i=i+1 + #=========================================================================== + +def __getStnProdXml(options): + #if options.prodName == None or options.refTime == None or options.stnId == None: + # parser.print_help() + # return None + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + + if(options.versionNum == None): + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName,"GET_GPD_STATION_PRODUCT_XML") + else: + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName, "GET_GPD_STATION_PRODUCT_XML", True, int(options.versionNum)) + if(stnProd!=None): + if(options.filePath == None): + filename = __createFilenameStringXml((options.prodName+'@'+options.stnId),options.refTime) + else: + filename = options.filePath + f = open(filename,'w') + f.write(stnProd) + return stnProd + else: + print("Query failed!") + return None +def __getPrintStnProdXml(options): + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + + if(options.versionNum == None): + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName,"GET_GPD_STATION_PRODUCT_XML") + else: + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName, "GET_GPD_STATION_PRODUCT_XML",True, int(options.versionNum)) + if(stnProd != None): + print(stnProd) + else: + print("Query failed!") + +def __getStnProdGempak(options): + #if options.prodName == None or options.refTime == None or options.stnId == None: + # parser.print_help() + # return None + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + + if(options.versionNum == None): + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName,"GET_GPD_STATION_PRODUCT_GEMPAK_TBL") + else: + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName, "GET_GPD_STATION_PRODUCT_GEMPAK_TBL", True, int(options.versionNum)) + if(stnProd!=None): + if(options.filePath == None): + filename = __createFilenameStringGempak((options.prodName+'@'+options.stnId),options.refTime) + else: + filename = options.filePath + f = open(filename,'w') + f.write(stnProd) + return stnProd + else: + print("Query failed!") + return None +def __getPrintStnProdGempak(options): + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + + if(options.versionNum == None): + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName,"GET_GPD_STATION_PRODUCT_GEMPAK_TBL") + else: + stnProd = req.getGpdStationProduct(options.stnId, date,options.prodName, "GET_GPD_STATION_PRODUCT_GEMPAK_TBL",True, int(options.versionNum)) + if(stnProd != None): + print(stnProd) + else: + print("Query failed!") + +def __getMovingProdXml(options): + #if options.prodName == None or options.refTime == None or options.slat == None or options.slon == None: + # parser.print_help() + # return None + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName,"GET_GPD_MOVING_PRODUCT_XML") + else: + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName, "GET_GPD_MOVING_PRODUCT_XML",True, int(options.versionNum)) + if(stnProd!=None): + if(options.filePath == None): + filename = __createFilenameStringXml((options.prodName+'@'+str(options.slat)+'#'+str(options.slon)),options.refTime) + else: + filename = options.filePath + f = open(filename,'w') + f.write(stnProd) + return stnProd + else: + print("Query failed!") + return None +def __getPrintMovingProdXml(options): + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName,"GET_GPD_MOVING_PRODUCT_XML") + else: + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName, "GET_GPD_MOVING_PRODUCT_XML", True, int(options.versionNum)) + if(stnProd != None): + print(stnProd) + else: + print("Query failed!") + +def __getMovingProdGempak(options): + #if options.prodName == None or options.refTime == None or options.slat == None or options.slon == None: + # parser.print_help() + # return None + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName,"GET_GPD_MOVING_PRODUCT_GEMPAK_TBL") + else: + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName, "GET_GPD_MOVING_PRODUCT_GEMPAK_TBL",True, int(options.versionNum)) + if(stnProd!=None): + if(options.filePath == None): + filename = __createFilenameStringGempak((options.prodName+'@'+str(options.slat)+'#'+str(options.slon)),options.refTime) + else: + filename = options.filePath + f = open(filename,'w') + f.write(stnProd) + return stnProd + else: + print("Query failed!") + return None +def __getPrintMovingProdGempak(options): + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName,"GET_GPD_MOVING_PRODUCT_GEMPAK_TBL") + else: + stnProd = req.getGpdMovingProduct(options.slat, options.slon, date,options.prodName, "GET_GPD_MOVING_PRODUCT_GEMPAK_TBL", True, int(options.versionNum)) + if(stnProd != None): + print(stnProd) + else: + print("Query failed!") + +def __getProdXml(options): + #if options.prodName == None or options.refTime == None: + # parser.print_help() + # return None + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_XML") + else: + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_XML", True, int(options.versionNum)) + if(prod != None): + if(options.filePath == None): + filename = __createFilenameStringXml(options.prodName,options.refTime) + else: + filename = options.filePath + f = open(filename,'w') + f.write(prod) + return prod + else: + print("Query failed!") + return None + +def __getPrintProdXml(options): + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_XML") + else: + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_XML", True, int(options.versionNum)) + if(prod != None): + print(prod) + else: + print("Query failed!") + +def __getProdGempak(options): + #if options.prodName == None or options.refTime == None: + # parser.print_help() + # return None + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_GEMPAK_TBL") + else: + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_GEMPAK_TBL", True, int(options.versionNum)) + if(prod != None): + if(options.filePath == None): + filename = __createFilenameStringGempak(options.prodName,options.refTime) + else: + filename = options.filePath + f = open(filename,'w') + f.write(prod) + return prod + else: + print("Query failed!") + return None + +def __getPrintProdGempak(options): + date = __convertTimeToDate(options.refTime) + req= GpdCliRequestHandler.GpdCliRequestHandler() + if(options.versionNum == None): + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_GEMPAK_TBL") + else: + prod = req.getGpdProduct( date,options.prodName,"GET_GPD_PRODUCT_GEMPAK_TBL", True, int(options.versionNum)) + if(prod != None): + print(prod) + else: + print("Query failed!") + +#def __purgeProd(options): +# req= GpdCliRequestHandler.GpdCliRequestHandler() +# req.purgeGpdProd(options.prodName,options.refTime, option.all) + +def __purgeExpired(options): + req= GpdCliRequestHandler.GpdCliRequestHandler() + req.purgeGpdExpired() + +def __purgeAll(options): + req= GpdCliRequestHandler.GpdCliRequestHandler() + req.purgeGpdAll() + +def __printUsage(options): + print(USAGE_MESSAGE) + + +def __saveProdXml(options): + # read in XML from input file + xmlfile = io.open(options.filePath, 'rb') + gpdXML = xmlfile.read() + xmlfile.close() + + # Store GPD report to EDEX + req= GpdCliRequestHandler.GpdCliRequestHandler() + result = req.storeGpdXmlProduct(gpdXML) + if result==None: + print("Store action failed!") + else: + print(result) + +def __saveProdGempak(options): + # read in XML from input file + gpkfile = io.open(options.filePath, 'rb') + gpdGempak = gpkfile.read() + gpkfile.close() + + # Store GPD report to EDEX + req= GpdCliRequestHandler.GpdCliRequestHandler() + maxNumLevel = options.maxNumLevel + + if(options.versionNum == None): + result = req.storeGpdGempakProduct(gpdGempak,options.prodName,int(maxNumLevel),0) + else: + result = req.storeGpdGempakProduct(gpdGempak,options.prodName,int(maxNumLevel),int(options.versionNum)) + + if result==None: + print("Store action failed!") + else: + print(result) + +def main(): + __initLogger() + #logger.info("Starting Query report.") + options = __parseCommandLine() + #vars(options) + options.func(options) + #logger.info("queried report name: " + options.prodName) + + return 0 + +if __name__ == '__main__': + main() diff --git a/msi/VizLauncher/VizLauncher.suo b/msi/VizLauncher/VizLauncher.suo index 610c195a0e..cd5496cb2c 100644 Binary files a/msi/VizLauncher/VizLauncher.suo and b/msi/VizLauncher/VizLauncher.suo differ diff --git a/msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/AbstractProcessLauncher.cs b/msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/AbstractProcessLauncher.cs index db02974126..85a4068f4b 100644 --- a/msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/AbstractProcessLauncher.cs +++ b/msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/AbstractProcessLauncher.cs @@ -1,129 +1,128 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; -using System.Diagnostics; -using VizLauncher.com.raytheon.viz.launcher.environment; - -namespace VizLauncher.com.raytheon.viz.launcher.process -{ - public abstract class AbstractProcessLauncher : IProcessLauncher - { - private static readonly String LOG_DATE_FORMAT = "yyyyMMdd_HHmmss"; - protected static readonly String LOG_SUFFIX = ".log"; - protected Process process = null; - private StreamWriter logFileWriter; - - private bool ready = false; - private String exceptionText = null; - - public AbstractProcessLauncher(VizEnvironment vizEnvironment) - { - // Prepare the log file. - if (Directory.Exists(vizEnvironment.getLogDirectory()) == false) - { - Directory.CreateDirectory(vizEnvironment.getLogDirectory()); - } - String logName = vizEnvironment.getLogDirectory() + - Path.DirectorySeparatorChar + this.constructLogName(this.determineLogDate()); - - // Prepare the process. - this.process = new Process(); - this.process.StartInfo = this.constructProcessStartInfo(vizEnvironment); - this.process.OutputDataReceived += new DataReceivedEventHandler(processOutputHandler); - this.validate(); - if (this.ready == false) - { - return; - } - - /* - * Access the log file for write access; other processes will have read-only access to - * the log file until it is closed. - **/ - this.logFileWriter = - new StreamWriter(File.Open(logName, FileMode.Append, - FileAccess.Write, FileShare.Read)); - } - - private String determineLogDate() - { - return DateTime.Now.ToString(LOG_DATE_FORMAT); - } - - private ProcessStartInfo constructProcessStartInfo(VizEnvironment vizEnvironment) - { - ProcessStartInfo processStartInfo = - new ProcessStartInfo(this.constructProcessName(vizEnvironment.getLocation())); - processStartInfo.EnvironmentVariables.Remove(EnvironmentProperties.ENVIRONMENT_VARIABLE_PATH); - processStartInfo.EnvironmentVariables.Add( - EnvironmentProperties.ENVIRONMENT_VARIABLE_PATH, vizEnvironment.getPath()); - processStartInfo.EnvironmentVariables.Add( - EnvironmentProperties.ENVIRONMENT_VARIABLE_PYTHON_PATH, vizEnvironment.getPythonPath()); - processStartInfo.UseShellExecute = false; - processStartInfo.Arguments = this.getCommandLineArguments(); - processStartInfo.RedirectStandardOutput = true; - - return processStartInfo; - } - - protected void validate() - { - String application = this.process.StartInfo.FileName; - /* ensure that the specified application exists. */ - if (File.Exists(application) == false) - { - this.ready = false; - this.exceptionText = "Unable to find the specified Viz application: " + application; - return; - } - - this.ready = true; - } - - public virtual void launchProcess() - { - this.runProcess(); - this.closeLog(); - } - - protected void runProcess() - { - this.process.Start(); - this.process.BeginOutputReadLine(); - this.process.WaitForExit(); - this.process.CancelOutputRead(); - } - - protected void closeLog() - { - this.logFileWriter.Close(); - } - - private void processOutputHandler(Object sendingProcess, DataReceivedEventArgs outline) - { - if (String.IsNullOrEmpty(outline.Data)) - { - return; - } - this.logFileWriter.WriteLine(outline.Data); - } - - public bool isReady() - { - return this.ready; - } - - public String getExceptionText() - { - return this.exceptionText; - } - - protected abstract String constructProcessName(String location); - - protected abstract String constructLogName(String logDate); - - protected abstract String getCommandLineArguments(); - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Diagnostics; +using VizLauncher.com.raytheon.viz.launcher.environment; + +namespace VizLauncher.com.raytheon.viz.launcher.process +{ + public abstract class AbstractProcessLauncher : IProcessLauncher + { + private static readonly String LOG_DATE_FORMAT = "yyyyMMdd_HHmmss"; + protected static readonly String LOG_SUFFIX = ".log"; + protected Process process = null; + private StreamWriter logFileWriter; + + private bool ready = false; + private String exceptionText = null; + + public AbstractProcessLauncher(VizEnvironment vizEnvironment) + { + // Prepare the log file. + if (Directory.Exists(vizEnvironment.getLogDirectory()) == false) + { + Directory.CreateDirectory(vizEnvironment.getLogDirectory()); + } + String logName = vizEnvironment.getLogDirectory() + + Path.DirectorySeparatorChar + this.constructLogName(this.determineLogDate()); + + // Prepare the process. + this.process = new Process(); + this.process.StartInfo = this.constructProcessStartInfo(vizEnvironment); + this.process.OutputDataReceived += new DataReceivedEventHandler(processOutputHandler); + this.validate(); + if (this.ready == false) + { + return; + } + + /* + * Access the log file for write access; other processes will have read-only access to + * the log file until it is closed. + **/ + this.logFileWriter = + new StreamWriter(File.Open(logName, FileMode.Append, + FileAccess.Write, FileShare.Read)); + } + + private String determineLogDate() + { + return DateTime.Now.ToString(LOG_DATE_FORMAT); + } + + private ProcessStartInfo constructProcessStartInfo(VizEnvironment vizEnvironment) + { + ProcessStartInfo processStartInfo = + new ProcessStartInfo(this.constructProcessName(vizEnvironment.getLocation())); + processStartInfo.EnvironmentVariables[EnvironmentProperties.ENVIRONMENT_VARIABLE_PATH] = + vizEnvironment.getPath(); + processStartInfo.EnvironmentVariables[EnvironmentProperties.ENVIRONMENT_VARIABLE_PYTHON_PATH] = + vizEnvironment.getPythonPath(); + processStartInfo.UseShellExecute = false; + processStartInfo.Arguments = this.getCommandLineArguments(); + processStartInfo.RedirectStandardOutput = true; + + return processStartInfo; + } + + protected void validate() + { + String application = this.process.StartInfo.FileName; + /* ensure that the specified application exists. */ + if (File.Exists(application) == false) + { + this.ready = false; + this.exceptionText = "Unable to find the specified Viz application: " + application; + return; + } + + this.ready = true; + } + + public virtual void launchProcess() + { + this.runProcess(); + this.closeLog(); + } + + protected void runProcess() + { + this.process.Start(); + this.process.BeginOutputReadLine(); + this.process.WaitForExit(); + this.process.CancelOutputRead(); + } + + protected void closeLog() + { + this.logFileWriter.Close(); + } + + private void processOutputHandler(Object sendingProcess, DataReceivedEventArgs outline) + { + if (String.IsNullOrEmpty(outline.Data)) + { + return; + } + this.logFileWriter.WriteLine(outline.Data); + } + + public bool isReady() + { + return this.ready; + } + + public String getExceptionText() + { + return this.exceptionText; + } + + protected abstract String constructProcessName(String location); + + protected abstract String constructLogName(String logDate); + + protected abstract String getCommandLineArguments(); + } } \ No newline at end of file diff --git a/msi/build/A2Staging/VisualStudio/VizLauncher.exe b/msi/build/A2Staging/VisualStudio/VizLauncher.exe index 7b199ed61c..af03282d6f 100644 Binary files a/msi/build/A2Staging/VisualStudio/VizLauncher.exe and b/msi/build/A2Staging/VisualStudio/VizLauncher.exe differ diff --git a/nativeLib/edexBridge/.cproject b/nativeLib/edexBridge/.cproject index e46d10c81d..d6e0bcb04b 100644 --- a/nativeLib/edexBridge/.cproject +++ b/nativeLib/edexBridge/.cproject @@ -26,7 +26,7 @@