Issue #1297. Changed non-blocking ZoneTableDlg. Next patch.

Changes from reviewers comments.

Change-Id: Ie812ef1167fa6b1ea78ee615190bd3059285a682

Former-commit-id: 4560efe149 [formerly 8f002a71cb688fe8fbf7378ef53398dfecb0354e]
Former-commit-id: d220f74018
This commit is contained in:
Slav Korolev 2012-10-30 21:37:52 -04:00
parent eb297f00fc
commit 487a9eabb8
28 changed files with 3527 additions and 3311 deletions

View file

@ -20,6 +20,7 @@ Require-Bundle: org.eclipse.ui,
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Import-Package: com.raytheon.uf.common.colormap
Export-Package: com.raytheon.uf.viz.monitor.fog.threshold,
Export-Package: com.raytheon.uf.viz.monitor.fog,
com.raytheon.uf.viz.monitor.fog.threshold,
com.raytheon.uf.viz.monitor.fog.ui.resource,
com.raytheon.uf.viz.monitor.fog.xml

View file

@ -0,0 +1,839 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.monitor.fog;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Map;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.dataplugin.fog.FogRecord;
import com.raytheon.uf.common.dataplugin.fog.FogRecord.FOG_THREAT;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogCell;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogDataCorrector;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogMonitorUtils;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.geospatial.ReferencedObject.Type;
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.monitor.fog.xml.FogMonitorAlgorithmXML;
import com.vividsolutions.jts.algorithm.locate.SimplePointInAreaLocator;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
/**
* Common calculations of Fog threats for Fog and SAFESEAS monitors.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 13, 2012 skorolev Initial creation
*
* </pre>
*
* @author skorolev
* @version 1.0
*/
public abstract class FogCommonThreat {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(FogCommonThreat.class);
// /** list of coordinates for each zone **/
// private Map<String, ArrayList<Coordinate>> zoneCoordinates = null;
/** GeometryFactory **/
protected final GeometryFactory geoFactory = new GeometryFactory();
/** Fog record **/
private FogRecord fog = null;
/** Fog algorithm XML **/
protected FogMonitorAlgorithmXML fogAlgXML = null;
/** Geometry of adjacent areas **/
protected Geometry geoAdjAreas = null;
/** Fog threats as the colors **/
private FOG_THREAT[] threats = null;
/** Fog cells from satellites **/
private ArrayList<FogCell> cells = null;
/** IR thresholds **/
private float[] ir_diff_thresholds = null;
/** VIS thresholds **/
private float[] vis_thresholds = null;
/** Twilight angle offset **/
protected int twilight_angle_offset = 0;
/** boolean isSnowIce switch **/
protected boolean isSnowIce = true;
/** boolean isFractalDimension switch **/
protected boolean isFractalDimension = true;
/** boolean isSmoothness switch **/
protected boolean isSmoothness = true;
/** boolean isAdjacency switch **/
protected boolean isAdjacency = true;
/** Geometry of zones **/
protected Map<String, Geometry> zoneGeos = null;
/**
* This method will be called with the switches from the GUI front end
*
* Fog Product [T(10.7) - (T(3.9)] or VIS (normalized count) Maximum cloud
* temperature Daytime Ice/Snow vs Fog Threshold (c) (FogSnowIceFilter) Cool
* Fog vs Warm Surface threshold Daytime Smoothness Algorithm
* (FogSmoothnessFilter) Adjacency Threshold Twilight Angle Threshold
* Fractal Dimension Threshold (FogFractalFilter)
*
* Adds fog threat into Fog record.
*
* @param fog
* record
* @return fog record
*/
public FogRecord getFogThreat(FogRecord fog) {
this.fog = fog;
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.handle(Priority.DEBUG,
"Start analyzing Fog Threat...");
}
long start = System.currentTimeMillis();
// this.geoAdjAreas = getMonitor().getGeoAdjAreas();
// clear threats array, make gray (SK)i=>x j=>y
for (int i = 0; i < fog.getNx(); i++) {
for (int j = 0; j < fog.getNy(); j++) {
getThreats()[fog.getNx() * j + i] = FOG_THREAT.GRAY;
}
}
// First execute the data corrector, this divides up the FogRecord field
// into Day, Night, and Twilight.
FogDataCorrector fdc = new FogDataCorrector(getFog(),
fogAlgXML.getTwilightAngle());
fog = fdc.execute();
// Second, core processor. Gets you the cells, sets non-filtered values.
executeCoreProcessor();
// Third, apply filters
for (FogCell cell : getCells()) {
// *********** APPLY FILTERS *******************
// Area Size filter
if (fogAlgXML.isAdjacencyThreshOn()
&& cell.getCellThreat() != FOG_THREAT.GREEN
&& cell.getCellThreat() != FOG_THREAT.GRAY) {
if (cell.getArea() < fogAlgXML.getAdjacencyThresh()) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
}
}
// Snow & Ice filter
if (fogAlgXML.isIceSnowVsFogOn()
&& cell.getImageGroup() == FogRecord.IMAGE_GROUP.VIS_GROUP
&& (cell.getCellThreat() != FOG_THREAT.GREEN || cell
.getCellThreat() != FOG_THREAT.GRAY)) {
float tempMean = calAverageTemp(cell);
if (tempMean < fogAlgXML.getIceSnowVsFog()) {
downgradeThreat(cell);
}
}
// Smoothness filter
if (fogAlgXML.isDaytimeSmoothThreshOn()
&& cell.getCellThreat() != FOG_THREAT.GREEN
|| cell.getCellThreat() != FOG_THREAT.GRAY) {
float tem_smoothness = calSmoothness(cell);
if (tem_smoothness < fogAlgXML.getDaytimeSmoothThresh()) {
downgradeThreat(cell);
}
}
// Fractal filter
if (fogAlgXML.isFractalDimensionOn()
&& cell.getCellThreat() != FOG_THREAT.GREEN
&& cell.getCellThreat() != FOG_THREAT.GRAY) {
float temFD = calRegularity(cell);
if (temFD > fogAlgXML.getFractalDimension() && temFD > 0.0f) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
}
}
// We extract the zone threat differently than the GI filter
// Hence it is not needed.
}
setThreats();
setMonitorAreaThreats();
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.handle(
Priority.DEBUG,
"Analyzed Fog Threat...Duration: "
+ (System.currentTimeMillis() - start));
}
return fog;
}
/**
* Gets the zone threats (ALG) with worst case for zone area
*
* @return Map<String, FOG_THREAT> zoneThreats
*/
protected abstract void setMonitorAreaThreats();
/**
* Quick static method to get the float to threat mapping Convert threat
* color to float value
*
* @param threat
* color
* @return float value
*/
public static float getThreatValue(FOG_THREAT threat) {
float value = 0;
if (threat == FOG_THREAT.BLACK) {
value = 0.0f;
} else if (threat == FOG_THREAT.GRAY) {
value = 15.0f;
} else if (threat == FOG_THREAT.GREEN) {
value = 60.0f;
} else if (threat == FOG_THREAT.YELLOW) {
value = 110.0f;
} else if (threat == FOG_THREAT.RED) {
value = 220.0f;
}
return value;
}
/**
* Gets the existing threat value at that point
*
* @param i
* => y
* @param j
* => x
* @return threat at point
*/
public FOG_THREAT getThreat(int i, int j) {
return getThreats()[fog.getNx() * j + i];
}
/**
* Gets the drawable float array of threats
*/
private void setThreats() {
float[] floats = new float[getThreats().length];
int i = 0;
for (FOG_THREAT threat : getThreats()) {
floats[i] = getThreatValue(threat);
i++;
}
getFog().setThreats(floats);
}
// *********************** FILTERS **************************** //
/**
* NAME: CalRegularity().
*
* TYPE: Private Member function.
*
* Description: Given a cell, calculate its regularity i.e. the fractal
* dimension Input Arguments: cell: The Fog_Cell whose fractal dimension is
* to be measured Output Arguments: Return float: fractal dimension. the
* value is between 1 to 2 smaller means more regular. Here use the
* perimeter and area relation to represent fractal dimension (one of the
* simply ways) History: May 2004 Qin Zeng (GDMB/MDL) -- created Dec 2009 D
* Hladky translated to Java
*
*
*
* @param cell
* @return fractalDimension
*/
private float calRegularity(FogCell cell) {
int nx = cell.right - cell.left + 1;
int ny = cell.bottom - cell.top + 1;
int i;
boolean[] flag = new boolean[nx * ny];
for (i = 0; i < nx * ny; i++) {
flag[i] = false;
}
int pixels_num = (int) cell.getArea();
int flagPos;
for (i = 0; i < pixels_num; i++) {
Coordinate coor = cell.getPixelCoordinate(i);
flagPos = (int) ((coor.y - cell.top) * nx + coor.x - cell.left);
if (flagPos >= 0 && flagPos < nx * ny) {
flag[flagPos] = true;
}
}
// From here, perimeter of the fog cell will be calculated;
// |...| 1 |...|
// | 4 | 0 | 2 |
// |...| 3 |...|
//
// If the any of the 0's surrounding pixels(1,2,3,4) is flagged as
// false,
// which means that surrounding pixel(1,2,3,or 4) is not included in
// the cell, pixel 0 then will be at the edge of the cell cluster.
// And the edge connecting to the outside pixel will be counted into the
// perimeter of the cell cluster.
int pos1, pos2, pos3, pos4;
float perimeter = 0;
for (i = 0; i < pixels_num; i++) {
Coordinate coor = cell.getPixelCoordinate(i);
pos1 = (int) ((i - cell.top - 1) * nx + coor.y - cell.left);
if (pos1 >= 0 && pos1 < nx * ny && !flag[pos1]
|| i - coor.x < cell.top) {
perimeter++;
}
pos2 = (int) ((coor.y - cell.top) * nx + coor.x + 1 - cell.left);
if (pos2 >= 0 && pos2 < nx * ny && !flag[pos2]
|| coor.x + 1 > cell.right) {
perimeter++;
}
pos3 = (int) ((coor.y - cell.top + 1) * nx + coor.x - cell.left);
if (pos3 >= 0 && pos3 < nx * ny && !flag[pos3]
|| coor.y + 1 > cell.bottom) {
perimeter++;
}
pos4 = (int) ((coor.y - cell.top) * nx + coor.x - 1 - cell.left);
if (pos4 >= 0 && pos4 < nx * ny && !flag[pos4]
|| coor.x - 1 < cell.left) {
perimeter++;
}
}
float fractalDimension = 1.0f;
if (cell.getArea() != 1) {
fractalDimension = (float) (2 * Math.log(perimeter / 4.0) / Math
.log(cell.getArea()));
}
// Note : fractalDimension is a data between 1 and 2 and the larger
// fractalDimension is , the more irregular the shape of the cell will
// be.
return fractalDimension;
}
/**
* NAME: CalSmoothness().
*
* TYPE: Private Member function.
*
* Description: Given a cell, calculate the its smoothness Input Arguments:
* cell: The Fog_Cell whose smoothness is to be measured Output Arguments:
* return float: smoothness defined above History: May 2004 Qin Zeng
* (GDMB/MDL) -- created Dec 2009 D Hladky ported to AWIPS II
*
* @param cell
* @return smoothness
**/
private float calSmoothness(FogCell cell) {
float mean = 0; // mean grayscale value of pixels in the cell from VIS.
float stdDev = 0; // standard deviation
int pixels_num = (int) cell.getArea();
if (pixels_num == 0) {
return 0;
}
int i;
for (i = 0; i < pixels_num; i++) {
Coordinate pixr = cell.getPixelRelativeCoordinate(i);
mean += getFog().getVisArray()[(int) (getFog().getNx() * pixr.y + pixr.x)];
}
mean /= pixels_num;
float tem_float;
for (i = 0; i < pixels_num; i++) {
Coordinate pixr = cell.getPixelRelativeCoordinate(i);
tem_float = getFog().getVisArray()[(int) (getFog().getNx() * pixr.y + pixr.x)];
stdDev += (tem_float - mean) * (tem_float - mean);
}
stdDev /= pixels_num;
stdDev = (float) Math.sqrt(stdDev);
// mean should not be zero, so no need to check mean here.
return (1 - stdDev / mean) * 100; // use percent as unit
}
/**
* NAME: Cal().
*
* TYPE: Private Member function.
*
* Description: Calculate the average temperature for a Fog_Cell in channel
* 3.9 um History: May 2004 Qin Zeng (GDMB/MDL) -- created
*
* @param cell
* @return average temperature
*/
private float calAverageTemp(FogCell cell) {
float mean = 0; // mean temperature value of pixels in the cell.
int pixels_num = (int) cell.getArea();
if (pixels_num == 0) {
return -999.9f;
}
for (int i = 0; i < pixels_num; i++) {
Coordinate pixc = cell.getPixelRelativeCoordinate(i);
mean += temp_at_vis_pixel(new Point((int) pixc.x, (int) pixc.y),
FogRecord.CHANNEL.IR3_9);
}
mean /= pixels_num;
return mean;
}
/**
* Get the temp at the pixel
*
* @param pointVis
* @param channel
* @return
*/
private float temp_at_vis_pixel(Point pointVis, FogRecord.CHANNEL channel) {
// The assumption is that Dimensions of IR4 and IR2 are the same.
// IR4 data will be always needed, so attributes for IR4 shall be
// always available.
// **** ATTENTION ***** We have made the vis the same as well for AWIPS
// II
int count_value = 255;
if (channel == FogRecord.CHANNEL.IR3_9) {
count_value = fog.getIR_3_9Array()[fog.getNx() * pointVis.y
+ pointVis.x];
} else if (channel == FogRecord.CHANNEL.IR10_7) {
count_value = fog.getIR_10_7Array()[fog.getNx() * pointVis.y
+ pointVis.x];
}
return FogMonitorUtils.count2temp(count_value, channel);
}
/**
* NAME: Execute().
*
* TYPE: Private Member function.
*
* Description: Based on the thresholds of the VIS image data and the IR
* image data, a number of patches of the contiguous suspected fog areas
* will be extracted from the satellite image data. This is an
* implementation of the feature extraction algorithm based on the
* contiguous gray scale values.
*
* Arguments: None History: March 2004 Qin Zeng (GDMB/MDL) -- created Dec
* 2009 D Hladky ported to Java for AWIPS II
*
*
* Calculates cells parameters
*/
private void executeCoreProcessor() {
cells = new ArrayList<FogCell>();
ArrayList<Point> parent = new ArrayList<Point>();
ArrayList<Point> child = new ArrayList<Point>();
ArrayList<Point> single_segment = new ArrayList<Point>();
int x_dim = getFog().getNx();
int y_dim = getFog().getNy();
int i; // (SK) x
int j; // (SK) y
// To flag whether a pixel has been visited or not
boolean[][] visited = new boolean[x_dim][y_dim];
Point[] surroundPts = new Point[8]; // 8 surrounding points of one
// specific point
for (int z = 0; z < surroundPts.length; z++) {
surroundPts[z] = new Point();
}
Point tempoint = new Point();
getCells().clear();
for (i = 0; i < x_dim; i++) {
for (j = 0; j < y_dim; j++) {
visited[i][j] = false;
}
}
for (j = 0; j < y_dim; j++) {
Point firstone = new Point();
FOG_THREAT threat_level = FOG_THREAT.BLACK;
FogRecord.IMAGE_GROUP imggroup;
for (i = 0; i < x_dim; i++) {
if (visited[i][j]) {
continue;
}
Coordinate cellCoor = this.getCellCoor(i, j);
visited[i][j] = true;
imggroup = getFog().findGroup(i, j);
threat_level = getThreatLevel(i, j, imggroup);
// Sets the initial threat level
setThreat(i, j, threat_level);
firstone.x = i;
firstone.y = j;
parent.clear();
tempoint.y = j;
tempoint.x = i;
single_segment.add(tempoint);
parent.add(tempoint);
while (parent.size() != 0) {
// the variables(surroundPts[1],surroundPts[2]...) below
// mean surrounding 1,2
// | 0 | 1 | 2 |
// | 7 | i | 3 |
// | 6 | 5 | 4 |
// iteratively search the 8-connected surrounding pixels
child.clear();
for (int k = 0; k < parent.size(); k++) {
// y's too small, too big
if (parent.get(k).y == 0) {
surroundPts[0].y = parent.get(k).y;
surroundPts[1].y = parent.get(k).y;
surroundPts[2].y = parent.get(k).y;
}
if (parent.get(k).y == y_dim - 1) {
surroundPts[4].y = parent.get(k).y;
surroundPts[5].y = parent.get(k).y;
surroundPts[6].y = parent.get(k).y;
}
// x's too small, too big
if (parent.get(k).x == 0) {
surroundPts[0].x = parent.get(k).x;
surroundPts[6].x = parent.get(k).x;
surroundPts[7].x = parent.get(k).x;
}
if (parent.get(k).x == x_dim - 1) {
surroundPts[2].x = parent.get(k).x;
surroundPts[3].x = parent.get(k).x;
surroundPts[4].x = parent.get(k).x;
}
// all others
if (parent.get(k).x > 0 && parent.get(k).x < x_dim - 1
&& parent.get(k).y < y_dim - 1
&& parent.get(k).y > 0) {
surroundPts[0].y = parent.get(k).y - 1;
surroundPts[0].x = parent.get(k).x - 1;
surroundPts[1].y = parent.get(k).y - 1;
surroundPts[1].x = parent.get(k).x;
surroundPts[2].y = parent.get(k).y - 1;
surroundPts[2].x = parent.get(k).x + 1;
surroundPts[3].y = parent.get(k).y;
surroundPts[3].x = parent.get(k).x + 1;
surroundPts[4].y = parent.get(k).y + 1;
surroundPts[4].x = parent.get(k).x + 1;
surroundPts[5].y = parent.get(k).y + 1;
surroundPts[5].x = parent.get(k).x;
surroundPts[6].y = parent.get(k).y + 1;
surroundPts[6].x = parent.get(k).x - 1;
surroundPts[7].y = parent.get(k).y;
surroundPts[7].x = parent.get(k).x - 1;
}
FogRecord.IMAGE_GROUP temgroup;
FOG_THREAT temthreat;
for (int m = 0; m < 8; m++) {
if (surroundPts[m].y >= 0
&& surroundPts[m].y < y_dim
&& surroundPts[m].x >= 0
&& surroundPts[m].x < x_dim) {
int ii = surroundPts[m].x;
int jj = surroundPts[m].y;
if (!visited[ii][jj]) {
temgroup = getFog().findGroup(ii, jj);
temthreat = getThreatLevel(ii, jj, temgroup);
if (temgroup == imggroup
&& temthreat == threat_level) {
child.add(surroundPts[m]);
visited[ii][jj] = true;
single_segment.add(surroundPts[m]);
}
}// end of if
}// end of if
}// end of for m
}// end of for k
parent = child;
}// end of while
int lct = SimplePointInAreaLocator.locate(cellCoor,
this.geoAdjAreas);
if (lct == 2) {
threat_level = FOG_THREAT.BLACK;
setThreat(i, j, threat_level);
}
getCells().add(
new FogCell(single_segment, threat_level, imggroup));
single_segment.clear();
} // end of for i
} // end of for j
}
/**
* Gets geo coordinates of cell
*
* @param i
* => y
* @param j
* => x
* @return crd
*/
private Coordinate getCellCoor(int i, int j) {
ReferencedCoordinate rc = new ReferencedCoordinate(
new Coordinate(i, j), this.getFog().getGridGeometry(),
Type.GRID_CENTER);
Coordinate crd = null;
try {
crd = rc.asLatLon();
} catch (TransformException e) {
statusHandler.handle(Priority.ERROR, e.getMessage());
} catch (FactoryException e) {
statusHandler.handle(Priority.ERROR, e.getMessage());
}
return crd;
}
/**
* Set fog threat at threat level point
*
* @param i
* => y
* @param j
* => x
* @param threat
*/
private void setThreat(int i, int j, FOG_THREAT threat) {
getThreats()[fog.getNx() * j + i] = threat;
}
/**
* Remember J is X and I is Y, totally against convention! Gets the threat
* level
*
* @param i
* (SK y)
* @param j
* (SK x)
* @param group
* @return threat level as color
*/
private FOG_THREAT getThreatLevel(int i, int j, FogRecord.IMAGE_GROUP group) {
// (SK) i=>x, j=>y
// default return
FOG_THREAT returnValue = FOG_THREAT.GRAY;
int idx = fog.getNx() * j + i;
switch (group) {
case VIS_GROUP:
float ir4_temp = bTemp(i, j, FogRecord.CHANNEL.IR10_7);
int CLOUD_FREE_BRIGHTNESS = 68; // empirical value
// Too cold
if (ir4_temp < fogAlgXML.getMaxCloudTemp()) {
returnValue = FOG_THREAT.GRAY;
}
// overlapping high/middle cloud
else if (fog.getVisArray()[idx] <= vis_thresholds[2]
&& fog.getVisArray()[idx] >= vis_thresholds[1]) {
returnValue = FOG_THREAT.RED;
} else if (fog.getVisArray()[idx] < vis_thresholds[1]
&& fog.getVisArray()[idx] >= vis_thresholds[0]
|| fog.getVisArray()[idx] <= vis_thresholds[3]
&& fog.getVisArray()[idx] > vis_thresholds[2]) {
returnValue = FOG_THREAT.YELLOW;
}
// This is essentially the Cool Fog vs. Warm surface threshold check
else if (fogAlgXML.isCoolFogVsWarmSurfaceOn()
&& ir4_temp >= fogAlgXML.getCoolFogVsWarmSurface()) {
returnValue = FOG_THREAT.GREEN;
}
else if (fog.getVisArray()[idx] < CLOUD_FREE_BRIGHTNESS) {
returnValue = FOG_THREAT.GREEN;
}
return returnValue;
case IR_GROUP:
// for some odd reason j is x and i is y,
// not sure why AWIPS 1 does it this way.
// It is completely against convention.
// Point tempoint = new Point(j, i);
// (SK) here i=>x and j=>y
Point tempoint = new Point(i, j);
float tempIR10_7 = temp_at_vis_pixel(tempoint,
FogRecord.CHANNEL.IR10_7);
if (tempIR10_7 < fogAlgXML.getMaxCloudTemp()) {
// Too cold
returnValue = FOG_THREAT.GRAY;
}
// Overlapping high/middle cloud
float tempIR3_9 = temp_at_vis_pixel(tempoint,
FogRecord.CHANNEL.IR3_9);
float tempDiff = tempIR10_7 - tempIR3_9;
if (tempDiff <= ir_diff_thresholds[2]
&& tempDiff >= ir_diff_thresholds[1]) {
returnValue = FOG_THREAT.RED;
} else if (tempDiff < ir_diff_thresholds[1]
&& tempDiff >= ir_diff_thresholds[0]
|| tempDiff <= ir_diff_thresholds[3]
&& tempDiff > ir_diff_thresholds[2]) {
returnValue = FOG_THREAT.YELLOW;
} else {
returnValue = FOG_THREAT.GREEN;
}
case TWILIGHT_GROUP:
// do nothing, stays gray
}
return returnValue;
}
/**
* Precursor call to get temp at pixel
*
* @param i
* => y
* @param j
* => x
* @param imgtype
* @return temperature at the pixel
*/
private float bTemp(int i, int j, FogRecord.CHANNEL imgtype) {
// (SK) here i=>x and j=>y
// for some odd reason j is x and i is y,
// not sure why AWIPS 1 does it this way.
// It is completely against convention.
Point tempoint = new Point(i, j);
return temp_at_vis_pixel(tempoint, imgtype);
}
/**
* Downgrade the Fog Threat in the cell
*
* @param cell
*/
private void downgradeThreat(FogCell cell) {
if (cell.getCellThreat() == FOG_THREAT.YELLOW) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
} else if (cell.getCellThreat() == FOG_THREAT.RED) {
setCellThreats(cell.getPoints(), FOG_THREAT.YELLOW);
}
}
/**
* Sets the thresholds
*/
protected void setThresholdArrays() {
ir_diff_thresholds = new float[4];
vis_thresholds = new float[4];
ir_diff_thresholds[0] = (float) fogAlgXML.getFogProductYLo();
ir_diff_thresholds[1] = (float) fogAlgXML.getFogProductYHi();
ir_diff_thresholds[2] = (float) fogAlgXML.getFogProductRLo();
ir_diff_thresholds[3] = (float) fogAlgXML.getFogProductRHi();
vis_thresholds[0] = (float) fogAlgXML.getVisYLo();
vis_thresholds[1] = (float) fogAlgXML.getVisYHi();
vis_thresholds[2] = (float) fogAlgXML.getVisRLo();
vis_thresholds[3] = (float) fogAlgXML.getVisRHi();
}
/**
* Sets all points in the cell to the cell filtered value threat
*
* @param points
* @param threat
*/
private void setCellThreats(ArrayList<Point> points, FOG_THREAT threat) {
for (Point point : points) {
getThreats()[fog.getNx() * point.y + point.x] = threat;
}
}
/**
* Gets the cells of this analysis
*
* @return cells
*/
private ArrayList<FogCell> getCells() {
return cells;
}
/**
* Gets the fog record
*
* @return
*/
public FogRecord getFog() {
return fog;
}
/**
* Gets the existing array of threats
*
* @return threats in color
*/
public FOG_THREAT[] getThreats() {
if (threats == null) {
threats = new FOG_THREAT[getFog().getNx() * getFog().getNy()];
}
return threats;
}
}

View file

@ -21,8 +21,10 @@ package com.raytheon.uf.viz.monitor.fog;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.raytheon.uf.common.dataplugin.fog.FogRecord;
import com.raytheon.uf.common.dataplugin.fog.FogRecord.FOG_THREAT;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.CommonTableConfig;
import com.raytheon.uf.common.monitor.data.CommonTableConfig.CellType;
@ -36,156 +38,223 @@ import com.raytheon.uf.viz.monitor.fog.threshold.FogThresholdMgr;
import com.raytheon.uf.viz.monitor.util.MonitorConfigConstants;
/**
* Generate Data for Fog Dialogs
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 12/07/09 dhladky Initial Creation.
*
* </pre>
*
* @author dhladky
*
*/
* Generate Data for Fog Dialogs
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 12/07/09 dhladky Initial Creation.
* Oct.29, 2012 1297 skorolev Changed HashMap to Map
* Oct.31, 2012 1297 skorolev Clean code
*
* </pre>
*
* @author dhladky
*
*/
public class FogDataGenerator {
private CommonTableConfig ctc;
private FogThresholdMgr ftm;
public FogDataGenerator()
{
ctc = CommonTableConfig.getInstance();
ftm = FogThresholdMgr.getInstance();
}
/**
* Generates the zone fog data for table
* @param tableData
* @return
*/
public TableData generateZoneData(ObsData obsData, HashMap<String, FogRecord.FOG_THREAT> algThreats, Date date)
{
//TODO: in the future use the data passed to get the nominal time
// closest for display in table and CAVE rendering.
TableData fogTableData = new TableData(CommonConfig.AppName.FOG);
if (obsData != null) {
for (String zone: obsData.getContainer().keySet()) {
addZoneRow(zone, obsData.getArea(zone).getBestAreaReport(date), algThreats.get(zone), fogTableData);
}
}
private CommonTableConfig ctc;
return fogTableData;
private FogThresholdMgr ftm;
/**
* Generates Fog data
*/
public FogDataGenerator() {
ctc = CommonTableConfig.getInstance();
ftm = FogThresholdMgr.getInstance();
}
/**
* Generates the zone fog data for table
*
* @param obsData
* @param algThreats
* @param date
* @return fogTableData
*/
public TableData generateZoneData(ObsData obsData,
Map<String, FogRecord.FOG_THREAT> algThreats, Date date) {
// TODO: in the future use the data passed to get the nominal time
// closest for display in table and CAVE rendering.
TableData fogTableData = new TableData(CommonConfig.AppName.FOG);
if (obsData != null) {
for (String zone : obsData.getContainer().keySet()) {
addZoneRow(zone, obsData.getArea(zone).getBestAreaReport(date),
algThreats.get(zone), fogTableData);
}
}
/**
* Creates a Zone table row
* @param report
* @param td
*/
private void addZoneRow(String zone, ObReport report, FogRecord.FOG_THREAT threat, TableData td)
{
TableRowData trd = new TableRowData(ctc.getTableColumnKeys(CommonConfig.AppName.FOG).length);
return fogTableData;
}
trd.setTableCellData(0, new TableCellData(zone,
zone, CellType.AreaId, false));
trd.setTableCellData(1, new TableCellData(new Float(report
.getVisibility()).intValue(),ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_VIS.getXmlKey(), report.getVisibility()), true));
/**
* Creates a Zone table row
*
* @param zone
* @param report
* @param threat
* @param td
*/
private void addZoneRow(String zone, ObReport report,
FogRecord.FOG_THREAT threat, TableData td) {
TableRowData trd = new TableRowData(
ctc.getTableColumnKeys(CommonConfig.AppName.FOG).length);
trd.setTableCellData(2, new TableCellData(report.getPresentWx(), zone, CellType.NotMonitored, false));
trd.setTableCellData(0, new TableCellData(zone, zone, CellType.AreaId,
false));
trd.setTableCellData(3, new TableCellData(new Float(report
.getCeiling()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_CEILING.getXmlKey(), report.getCeiling()), true));
trd.setTableCellData(4, new TableCellData(new Float(report
.getWindDir()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_DIR_FROM.getXmlKey(), report
.getWindDir()), true));
trd.setTableCellData(5, new TableCellData(new Float(report
.getWindSpeed()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_WIND_SPEED.getXmlKey(), report
.getWindSpeed()), true));
trd.setTableCellData(6, new TableCellData(new Float(report
.getMaxWindSpeed()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_PEAK_WIND.getXmlKey(), report
.getMaxWindSpeed()), true));
trd.setTableCellData(7, new TableCellData(new Float(report
.getWindGust()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_GUST_SPEED.getXmlKey(), report
.getWindGust()), true));
trd.setTableCellData(8, new TableCellData(new Float(report
.getTemperature()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_TEMP.getXmlKey(), report
.getTemperature()), true));
trd.setTableCellData(9, new TableCellData(new Float(report
.getDewpoint()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_DEWPT.getXmlKey(), report
.getDewpoint()), true));
trd.setTableCellData(10, new TableCellData(new Float(report
.getDewpointDepr()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_T_TD.getXmlKey(), report
.getDewpointDepr()), true));
trd.setTableCellData(11, new TableCellData(new Float(report
.getRelativeHumidity()).intValue(), ftm.getThresholdValueCellType(DataUsageKey.DISPLAY, zone, MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_REL_HUMIDITY.getXmlKey(),
report.getRelativeHumidity()), true));
trd.setTableCellData(12, new TableCellData("", zone, getAlgorithmCellType(threat), true));
trd.setTableCellData(
1,
new TableCellData(
new Float(report.getVisibility()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_VIS
.getXmlKey(), report.getVisibility()),
true));
td.addReplaceDataRow(trd);
trd.setTableCellData(2, new TableCellData(report.getPresentWx(), zone,
CellType.NotMonitored, false));
trd.setTableCellData(
3,
new TableCellData(
new Float(report.getCeiling()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_CEILING
.getXmlKey(), report.getCeiling()),
true));
trd.setTableCellData(
4,
new TableCellData(
new Float(report.getWindDir()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_DIR_FROM
.getXmlKey(), report.getWindDir()),
true));
trd.setTableCellData(
5,
new TableCellData(
new Float(report.getWindSpeed()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_WIND_SPEED
.getXmlKey(), report.getWindSpeed()),
true));
trd.setTableCellData(
6,
new TableCellData(
new Float(report.getMaxWindSpeed()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_PEAK_WIND
.getXmlKey(), report.getMaxWindSpeed()),
true));
trd.setTableCellData(
7,
new TableCellData(
new Float(report.getWindGust()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_WIND_GUST_SPEED
.getXmlKey(), report.getWindGust()),
true));
trd.setTableCellData(
8,
new TableCellData(
new Float(report.getTemperature()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_TEMP
.getXmlKey(), report.getTemperature()),
true));
trd.setTableCellData(
9,
new TableCellData(
new Float(report.getDewpoint()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_DEWPT
.getXmlKey(), report.getDewpoint()),
true));
trd.setTableCellData(
10,
new TableCellData(new Float(report.getDewpointDepr())
.intValue(), ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY, zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_T_TD
.getXmlKey(), report.getDewpointDepr()), true));
trd.setTableCellData(
11,
new TableCellData(
new Float(report.getRelativeHumidity()).intValue(),
ftm.getThresholdValueCellType(
DataUsageKey.DISPLAY,
zone,
MonitorConfigConstants.FogDisplay.FOG_DISP_METEO_REL_HUMIDITY
.getXmlKey(), report
.getRelativeHumidity()), true));
trd.setTableCellData(12, new TableCellData("", zone,
getAlgorithmCellType(threat), true));
td.addReplaceDataRow(trd);
}
/**
* Get threat cells type
*
* @param threat
* @return type
*/
public CellType getAlgorithmCellType(FogRecord.FOG_THREAT threat) {
CellType type = CellType.NotDetermined;
if (threat == FogRecord.FOG_THREAT.GREEN) {
type = CellType.G;
} else if (threat == FogRecord.FOG_THREAT.YELLOW) {
type = CellType.Y;
} else if (threat == FogRecord.FOG_THREAT.RED) {
type = CellType.R;
}
//*******************************************************************************************
//*******************************************************************************************
//*******************************************************************************************
//*******************************************************************************************
//*******************************************************************************************
public TableData generateObsHistData(CommonConfig.AppName appName, CommonTableConfig.ObsHistType obsType)
{
TableData tData = new TableData(appName);
return type;
}
System.out.println("Creating data for: " + appName.name() + " and " + obsType.name());
if (appName == CommonConfig.AppName.SAFESEAS)
{
// Create Safeseas Data
}
else if (appName == CommonConfig.AppName.FOG)
{
// Create Fog Data
}
return tData;
}
public CellType getAlgorithmCellType(FogRecord.FOG_THREAT threat) {
CellType type = CellType.NotDetermined;
if (threat == FogRecord.FOG_THREAT.GREEN) {
type = CellType.G;
}
else if (threat == FogRecord.FOG_THREAT.YELLOW) {
type = CellType.Y;
}
else if (threat == FogRecord.FOG_THREAT.RED) {
type = CellType.R;
}
return type;
}
public HashMap<String,CellType> getAlgCellTypes(HashMap<String, FogRecord.FOG_THREAT> algThreats) {
HashMap<String,CellType> types = new HashMap<String,CellType>();
for (String zone : algThreats.keySet()) {
CellType type = getAlgorithmCellType(algThreats.get(zone));
types.put(zone, type);
}
return types;
/**
* Get threat types
*
* @param map
* @return types
*/
public Map<String, CellType> getAlgCellTypes(Map<String, FOG_THREAT> map) {
Map<String, CellType> types = new HashMap<String, CellType>();
for (String zone : map.keySet()) {
CellType type = getAlgorithmCellType(map.get(zone));
types.put(zone, type);
}
return types;
}
}

View file

@ -23,7 +23,8 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Pattern;
@ -40,15 +41,15 @@ import com.raytheon.uf.common.monitor.MonitorAreaUtils;
import com.raytheon.uf.common.monitor.config.FogMonitorConfigurationManager;
import com.raytheon.uf.common.monitor.data.AdjacentWfoMgr;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.ObConst.ChosenAppKey;
import com.raytheon.uf.common.time.DataTime;
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.alerts.AlertMessage;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.notification.NotificationMessage;
import com.raytheon.uf.viz.monitor.IMonitor;
import com.raytheon.uf.viz.monitor.Monitor;
import com.raytheon.uf.viz.monitor.ObsMonitor;
import com.raytheon.uf.viz.monitor.data.AreaContainer;
import com.raytheon.uf.viz.monitor.data.MonitoringArea;
import com.raytheon.uf.viz.monitor.data.ObMultiHrsReports;
import com.raytheon.uf.viz.monitor.data.ObReport;
@ -81,6 +82,8 @@ import com.vividsolutions.jts.geom.Geometry;
* 11/30/2009 3424 Zhidong/Slav/Wen Adds stationTableData to keep station info.
* May 15, 2012 14510 zhao Modified processing at startup
* Jun 16, 2012 14386 zhao Auto update County/Zone Table when new fog threat data arrives
* Oct 26, 2012 1280 skorolev Made changes for non-blocking dialog and changed HashMap to Map
* Oct.31 2012 1297 skorolev Clean code
*
* </pre>
*
@ -91,6 +94,9 @@ import com.vividsolutions.jts.geom.Geometry;
public class FogMonitor extends ObsMonitor implements IFogResourceListener {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(FogMonitor.class);
/** Singleton instance of this class */
private static FogMonitor monitor = null;
@ -102,59 +108,62 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
private ObMultiHrsReports obData;
/** data holder for FOG **/
public ObsData obsData = null;
private ObsData obsData = null;
public ArrayList<Date> resourceTimes = null;
/** data holder for FOG ALG data **/
private SortedMap<Date, Map<String, FOG_THREAT>> algorithmData = null;
/** data holder for FOG Algo data **/
//public HashMap<Date, HashMap<String, FOG_THREAT>> algorithmData = null;
public SortedMap<Date, HashMap<String, FOG_THREAT>> algorithmData = null;
public Date dialogTime = null;
private Date dialogTime = null;
/** list of coordinates for each zone **/
public HashMap<String, Geometry> zoneGeometries = null;
private Map<String, Geometry> zoneGeometries = null;
/** zone table dialog **/
public FogZoneTableDlg zoneDialog = null;
private FogZoneTableDlg zoneDialog;
/** zone table dialog **/
public MonitoringAreaConfigDlg areaDialog = null;
private MonitoringAreaConfigDlg areaDialog = null;
/** area config manager **/
public FogMonitorConfigurationManager fogConfig = null;
/** The application key */
ChosenAppKey chosenAppKey = ChosenAppKey.FOG;
private FogMonitorConfigurationManager fogConfig = null;
/** table data for the station table **/
private final TableData stationTableData = new TableData(
CommonConfig.AppName.FOG);
/** All FOG's plugs start with this **/
private static String OBS = "fssobs";
/** All FOG's datauri start with this **/
private final String OBS = "fssobs";
/** Array of fogAlg listeners **/
private final ArrayList<IFogResourceListener> fogResources = new ArrayList<IFogResourceListener>();
/** List of fogAlg listeners **/
private final List<IFogResourceListener> fogResources = new ArrayList<IFogResourceListener>();
/** regex wild card filter */
protected static String wildCard = "[\\w\\(\\)\\-_:.]+";
/** regex wild card filter **/
private final String wildCard = "[\\w\\(\\)\\-_:.]+";
/** Geometry of adjacent areas **/
private Geometry geoAdjAreas = null;
/** Data URI pattern for fog **/
private final Pattern fogPattern = Pattern.compile(URIFilter.uriSeperator
+ OBS + URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + cwa + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ "fog");
public Geometry geoAdjAreas = null;
/**
* Private constructor, singleton
*/
private FogMonitor() {
pluginPatterns.add(fogPattern);
pluginPatterns.add(fogPattern);
readTableConfig(MonitorThresholdConfiguration.FOG_THRESHOLD_CONFIG);
initObserver("fssobs", this);
initObserver(OBS, this);
}
/**
* Static factory
*
* @return
* @return fog monitor
*/
public static synchronized FogMonitor getInstance() {
if (monitor == null) {
@ -162,26 +171,26 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
// Pre-populate dialog with an observations from DB
monitor.createDataStructures();
monitor.getAdjAreas();
monitor.processProductAtStartup("fog");
monitor.fireMonitorEvent(monitor);
}
monitor.processProductAtStartup("fog");
monitor.fireMonitorEvent(monitor);
}
return monitor;
}
// TODO: Provide the changes in EDEX URIFilters when area configuration file
// has been changed.
/**
* DR#11279:
* When monitor area configuration is changed,
* this module is called to re-initialize monitor
* using new monitor area configuration
* DR#11279: When monitor area configuration is changed, this module is
* called to re-initialize monitor using new monitor area configuration
*/
public static void reInitialize() {
if ( monitor != null ) {
monitor = null;
monitor = new FogMonitor();
}
if (monitor != null) {
monitor = null;
monitor = new FogMonitor();
}
}
/**
* Creates the maps
*/
@ -191,31 +200,49 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
obData.setThresholdMgr(FogThresholdMgr.getInstance());
obsData = new ObsData();
algorithmData = new TreeMap<Date, HashMap<String, FOG_THREAT>>();
algorithmData = new TreeMap<Date, Map<String, FOG_THREAT>>();
for (String zone : MonitoringArea.getPlatformMap().keySet()) {
obsData.addArea(zone, MonitoringArea.getPlatformMap().get(zone));
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#filterNotifyMessage(com.raytheon
* .uf.viz.core.notification.NotificationMessage)
*/
@Override
public boolean filterNotifyMessage(NotificationMessage alertMessage) {
return false;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processNotifyMessage(com.raytheon
* .uf.viz.core.notification.NotificationMessage)
*/
@Override
public void processNotifyMessage(NotificationMessage filtered) {
// Not used
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processProductMessage(com.raytheon
* .uf.viz.core.alerts.AlertMessage)
*/
@Override
public void processProductMessage(final AlertMessage filtered) {
if (fogPattern.matcher(filtered.dataURI).matches()) {
// System.out.println("Found match: " + fogPattern + " URI: "
// + filtered.dataURI);
processURI(filtered.dataURI, filtered);
}
if (fogPattern.matcher(filtered.dataURI).matches()) {
processURI(filtered.dataURI, filtered);
}
}
/**
@ -226,8 +253,8 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
* -- the xml configuration filename
*/
public void readTableConfig(String file) {
// TODO update for Maritime
HashMap<String, ArrayList<String>> zones = new HashMap<String, ArrayList<String>>();
// TODO update for Maritime
Map<String, List<String>> zones = new HashMap<String, List<String>>();
// create zones and stations list
try {
FogMonitorConfigurationManager areaConfig = getMonitorAreaConfig();
@ -247,16 +274,36 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
MonitoringArea.setPlatformMap(zones);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.Monitor#initObserver(java.lang.String,
* com.raytheon.uf.viz.monitor.Monitor)
*/
@Override
public void initObserver(String pluginName, Monitor monitor) {
ProductAlertObserver.addObserver(pluginName, this);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#thresholdUpdate(com.raytheon.uf
* .viz.monitor.events.IMonitorThresholdEvent)
*/
@Override
public void thresholdUpdate(IMonitorThresholdEvent me) {
fireMonitorEvent(zoneDialog.getClass().getName());
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#configUpdate(com.raytheon.uf.viz
* .monitor.events.IMonitorConfigurationEvent)
*/
@Override
public void configUpdate(IMonitorConfigurationEvent me) {
fireMonitorEvent(zoneDialog.getClass().getName());
@ -267,89 +314,49 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
*/
@Override
public void nullifyMonitor() {
// /**
// * Before making the monitor null, remove observers
// */
// for (String p : pluginName) {
// if (!pluginName.equals("")) {
// stopObserver(p, this);
// }
// }
// monitor.fogResources.removeAll(getMonitorListeners());
ProductAlertObserver.removeObserver("fssobs", this);
ProductAlertObserver.removeObserver(OBS, this);
monitor = null;
}
private Pattern fogPattern = Pattern.compile(URIFilter.uriSeperator + OBS
+ URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + cwa + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ "fog");
/**
* Finds the zone based on the icao passed into it
*
* @param icao
* @return
* @return zone
*/
public String findZone(String icao) {
String rzone = null;
for (String zone : MonitoringArea.getPlatformMap().keySet()) {
if (MonitoringArea.getPlatformMap().get(zone).contains(icao)) {
rzone = zone;
break;
return zone;
}
}
return rzone;
return null;
}
/**
* get the main map
*
* @return
* @return obsData
*/
public ObsData getTableData() {
return obsData;
}
/**
* get your table row data
*
* @param areaID
* @return
*/
public AreaContainer getObs(String areaID) {
AreaContainer ac = null;
if (getTableData().getContainer().containsKey(areaID)) {
ac = getTableData().getArea(areaID);
}
return ac;
}
/**
* This method processes the incoming messages
*
* @param objectToSend
* @param pluginname
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ObsMonitor#process(com.raytheon.uf.viz.monitor.data.ObReport)
*/
@Override
protected void process(ObReport result)
throws Exception {
// ProcessFogReport fog = new ProcessFogReport(result);
// fog.processFogReport();
// use ObMultiHrsReports for data archive
// [Jan 21, 2010, zhao]
protected void process(ObReport result) throws Exception {
obData.addReport(result);
//fireMonitorEvent(this);
String zone = findZone(result.getPlatformId());
getTableData().getArea(zone).addReport(result.getObservationTime(),
result);
fireMonitorEvent(this);
}
@ -357,7 +364,7 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
/**
* gets the station Table Data
*
* @return
* @return stationTableData
*/
public TableData getStationTableData() {
return stationTableData;
@ -366,35 +373,38 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
/**
* launch the zone table dialog
*
* @param table
* @param type
* @param shell
*/
public void launchDialog(String type, Shell shell) {
if (type.equals("zone")) {
if (zoneDialog == null) {
zoneDialog = new FogZoneTableDlg(shell, obData);
if (zoneDialog == null || zoneDialog.getShell() == null
|| zoneDialog.isDisposed()) {
zoneDialog = new FogZoneTableDlg(shell, obData);
addMonitorListener(zoneDialog);
zoneDialog.addMonitorControlListener(this);
fireMonitorEvent(zoneDialog.getClass().getName());
zoneDialog.open();
} else {
zoneDialog.bringToTop();
}
} else if (type.equals("area")) {
if (areaDialog == null) {
areaDialog = new FogMonitoringAreaConfigDlg(shell,
"Fog Monitor Area Configuration");
areaDialog.open();
}
zoneDialog.open();
fireMonitorEvent(zoneDialog.getClass().getName());
}
else if (type.equals("area")) {
areaDialog = new FogMonitoringAreaConfigDlg(shell,
"Fog Monitor Area Configuration");
areaDialog.open();
}
}
/**
* Set the algorithm threat by zone, time
* Set the algorithm threat by time and zone
*
* @param zone
* @param threat
* @param time
* @param algData
*/
public void setAlgorithmData(Date time, HashMap<String, FOG_THREAT> algData) {
public void setAlgorithmData(Date time, Map<String, FOG_THREAT> algData) {
if (algorithmData.containsKey(time)) {
algorithmData.remove(time);
}
@ -403,19 +413,18 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
}
/**
* Gets the algorithm threat
* Gets algorithm threat by time
*
* @param zone
* @return
* @param time
* @return algData
*/
public HashMap<String, FOG_THREAT> getAlgorithmData(Date time) {
HashMap<String, FOG_THREAT> algData = new HashMap<String, FOG_THREAT>();
public Map<String, FOG_THREAT> getAlgorithmData(Date time) {
Map<String, FOG_THREAT> algData = new HashMap<String, FOG_THREAT>();
if (algorithmData.containsKey(time)) {
algData = algorithmData.get(time);
} else {
// default nothing in algo column
// by default is nothing in the ALG column
for (String zone : MonitoringArea.getPlatformMap().keySet()) {
algData.put(zone, FOG_THREAT.GRAY);
}
@ -426,21 +435,22 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
/**
* Gets the monitoring geometries
*
* @return
* @return zoneGeometries
*/
public HashMap<String, Geometry> getMonitoringAreaGeometries() {
public Map<String, Geometry> getMonitoringAreaGeometries() {
if (zoneGeometries == null) {
ArrayList<String> zones = getMonitorAreaConfig().getAreaList();
List<String> zones = getMonitorAreaConfig().getAreaList();
zoneGeometries = new HashMap<String, Geometry>();
for (String zone : zones) {
try {
zoneGeometries.put(zone, MonitorAreaUtils
.getZoneGeometry(zone));
zoneGeometries.put(zone,
MonitorAreaUtils.getZoneGeometry(zone));
} catch (Exception e) {
e.printStackTrace();
statusHandler.handle(Priority.PROBLEM,
"Error get Monitoring Area Config", e);
}
}
}
@ -451,7 +461,7 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
/**
* Gets the fog configuration manager
*
* @return
* @return fogConfig
*/
public FogMonitorConfigurationManager getMonitorAreaConfig() {
if (fogConfig == null) {
@ -464,10 +474,21 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
return fogConfig;
}
/**
* Gets observation data
*
* @return
*/
public ObMultiHrsReports getObData() {
return obData;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.fog.listeners.IFogResourceListener#
* algorithmUpdate()
*/
@Override
public void algorithmUpdate() {
@ -507,8 +528,8 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
* @param drawTime
*/
public void updateDialogTime(Date dialogTime) {
this.dialogTime = dialogTime;
fireMonitorEvent(zoneDialog.getClass().getName());
this.dialogTime = dialogTime;
fireMonitorEvent(zoneDialog.getClass().getName());
}
/**
@ -523,14 +544,20 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
/**
* close down the dialog
*
* @param type
*/
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.fog.listeners.IFogResourceListener#closeDialog
* ()
*/
public void closeDialog() {
if (zoneDialog != null) {
monitor.removeMonitorListener(zoneDialog);
monitor.nullifyMonitor();
zoneDialog.shellDisposeDialog();
zoneDialog.close();
zoneDialog = null;
}
@ -546,42 +573,28 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
* @param type
* @return
*/
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.IMonitor#getTimeOrderedKeys(com.raytheon.
* uf.viz.monitor.IMonitor, java.lang.String)
*/
@Override
public ArrayList<Date> getTimeOrderedKeys(IMonitor monitor, String type) {
return null;
}
/**
* Get most recent time
*
* @param type
* @return
* Get adjacent areas.
*/
public DataTime getMostRecent() {
DataTime time = null;
Set<Date> ds = this.algorithmData.keySet();
DataTime[] times = new DataTime[ds.size()];
int i = 0;
for (Date d : ds) {
times[i] = new DataTime(d);
i++;
}
java.util.Arrays.sort(times);
if (times.length > 0) {
time = times[times.length - 1]; // most recent
}
return time;
}
public FogZoneTableDlg getDialog() {
return zoneDialog;
}
public void getAdjAreas() {
this.geoAdjAreas = AdjacentWfoMgr.getAdjacentAreas(cwa);
}
/**
* Get geometry of adjacent areas.
*
* @return the geoAdjAreas
*/
public Geometry getGeoAdjAreas() {
@ -589,19 +602,39 @@ public class FogMonitor extends ObsMonitor implements IFogResourceListener {
}
/**
* Sets the geoAdjAreas
*
* @param geoAdjAreas
* the geoAdjAreas to set
*/
public void setGeoAdjAreas(Geometry geoAdjAreas) {
this.geoAdjAreas = geoAdjAreas;
}
@Override
protected void processAtStartup(ObReport report) {
obData.addReport(report);
/**
* First start
*/
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processAtStartup(com.raytheon.
* uf.viz.monitor.data.ObReport)
*/
@Override
protected void processAtStartup(ObReport report) {
obData.addReport(report);
String zone = findZone(report.getPlatformId());
getTableData().getArea(zone).addReport(report.getObservationTime(),
report);
}
}
/**
* Gets Fog zone table dialog
*
* @return zoneDialog
*/
public FogZoneTableDlg getZoneDialog() {
return zoneDialog;
}
}

View file

@ -47,12 +47,13 @@ public class FogMonitorAction extends AbstractHandler {
@Override
public Object execute(ExecutionEvent arg0) throws ExecutionException {
System.out.println("Activating/Action for FOG...");
FogMonitor fog = FogMonitor.getInstance();
if (fog.zoneDialog == null || fog.zoneDialog.isDisposed()) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
if (fog.getZoneDialog() == null || fog.getZoneDialog().isDisposed()) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell();
fog.launchDialog("zone", shell);
}
return null;

View file

@ -19,9 +19,10 @@
**/
package com.raytheon.uf.viz.monitor.fog.ui.dialogs;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
@ -31,6 +32,7 @@ import com.raytheon.uf.common.monitor.config.MonitorConfigurationManager;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.CommonTableConfig.CellType;
import com.raytheon.uf.common.monitor.data.ObConst.DataUsageKey;
import com.raytheon.uf.common.monitor.data.ObConst.DisplayVarName;
import com.raytheon.uf.viz.monitor.IMonitor;
import com.raytheon.uf.viz.monitor.data.ObMultiHrsReports;
import com.raytheon.uf.viz.monitor.events.IMonitorConfigurationEvent;
@ -42,15 +44,24 @@ import com.raytheon.uf.viz.monitor.listeners.IMonitorListener;
import com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg;
/**
* (Where is the history log for this file???)
* Fog Zone Table Dialog
*
* Jan 25, 2010 #4281 zhao Modified the notify method
* Jun 16, 2012 14386 zhao Modified the notify method
* <pre>
*
* @author
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 25, 2010 #4281 zhao Modified the notify method
* Jun 16, 2012 14386 zhao Modified the notify method
* Oct 30, 2012 skorolev Changed HashMap to Map
* Nov 11, 2012 1297 skorolev Added initiateProdArray
*
* </pre>
*
* @author ?
* @version 1.0
*/
public class FogZoneTableDlg extends ZoneTableDlg {
private FogMonDispThreshDlg fogThreshDlg;
@ -62,6 +73,31 @@ public class FogZoneTableDlg extends ZoneTableDlg {
super(parent, CommonConfig.AppName.FOG);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#initiateProdArray()
*/
@Override
public void initiateProdArray() {
varName = config.getFogZoneStnTableColVarNames()[colIndex];
prodArray = new ArrayList<String>();
String varpref = "VAR_";
for (DisplayVarName var : DisplayVarName.values()) {
String dispVarName = var.name();
if (dispVarName.equals(varpref + varName.name())) {
prodArray.add(dispVarName);
}
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#configThreshAction()
*/
@Override
protected void configThreshAction() {
if (fogThreshDlg == null) {
@ -72,6 +108,13 @@ public class FogZoneTableDlg extends ZoneTableDlg {
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.listeners.IMonitorListener#notify(com.raytheon
* .uf.viz.monitor.events.IMonitorEvent)
*/
@Override
public void notify(IMonitorEvent me) {
@ -87,23 +130,20 @@ public class FogZoneTableDlg extends ZoneTableDlg {
// incorporate both for the obs and
// The algorithm output.
if (me.getSource() instanceof FogMonitor) {
if (me.getSource() instanceof FogMonitor) {
FogMonitor fog = (FogMonitor) me.getSource();
Date date = fog.getDialogDate();
FogMonitor fog = (FogMonitor) me.getSource();
Date date = fog.getDialogDate();
if (date != null) {
Date nominalTime = date;
ObMultiHrsReports obData = fog.getObData();
// if (!isLinkedToFrame()) {
// nominalTime = obData.getLatestNominalTime();
// }
FogDataGenerator fdg = new FogDataGenerator();
HashMap<String, CellType> fogAlgCellType = fdg
.getAlgCellTypes(fog.getAlgorithmData(nominalTime));
obData.setFogAlgCellType(fogAlgCellType);
this.updateTableDlg(obData.getObHourReports(nominalTime));
ObMultiHrsReports obData = fog.getObData();
FogDataGenerator fdg = new FogDataGenerator();
Map<String, CellType> fogAlgCellType = fdg.getAlgCellTypes(fog
.getAlgorithmData(nominalTime));
obData.setFogAlgCellType(fogAlgCellType);
this.updateTableDlg(obData.getObHourReports(nominalTime));
}
}
}
}
/**
@ -129,17 +169,36 @@ public class FogZoneTableDlg extends ZoneTableDlg {
* date); //} }
*/
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* addMonitorControlListener(com.raytheon.uf.viz.monitor.IMonitor)
*/
@Override
public void addMonitorControlListener(IMonitor monitor) {
getMonitorControlListeners().add(monitor);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireConfigUpdate
* (com.raytheon.uf.viz.monitor.events.IMonitorConfigurationEvent)
*/
@Override
public void fireConfigUpdate(IMonitorConfigurationEvent imce) {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireDialogShutdown
* (com.raytheon.uf.viz.monitor.listeners.IMonitorListener)
*/
@Override
public void fireDialogShutdown(IMonitorListener iml) {
Display.getDefault().asyncExec(new Runnable() {
@ -153,6 +212,13 @@ public class FogZoneTableDlg extends ZoneTableDlg {
});
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#fireKillMonitor
* ()
*/
@Override
public void fireKillMonitor() {
Display.getDefault().asyncExec(new Runnable() {
@ -166,35 +232,51 @@ public class FogZoneTableDlg extends ZoneTableDlg {
});
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireThresholdUpdate
* (com.raytheon.uf.viz.monitor.events.IMonitorThresholdEvent)
*/
@Override
public void fireThresholdUpdate(IMonitorThresholdEvent imte) {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* removeMonitorContorlListener(com.raytheon.uf.viz.monitor.IMonitor)
*/
@Override
public void removeMonitorContorlListener(IMonitor monitor) {
getMonitorControlListeners().remove(monitor);
}
@Override
protected MonitorConfigurationManager getConfigMgr() {
return FogMonitorConfigurationManager.getInstance();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#getConfigMgr()
*/
@Override
protected MonitorConfigurationManager getConfigMgr() {
return FogMonitorConfigurationManager.getInstance();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#handleLinkToFrame()
*/
@Override
protected void handleLinkToFrame() {
linkedToFrame = linkToFrameChk.getSelection();
FogMonitor.getInstance().fireMonitorEvent(this.getClass().getName());
}
/**
*
*/
protected void unregisterDialogFromMonitor() {
this.fireDialogShutdown(this);
}
/*
* (non-Javadoc)
*
@ -203,8 +285,29 @@ public class FogZoneTableDlg extends ZoneTableDlg {
*/
@Override
protected void shellDisposeAction() {
// TODO Auto-generated method stub
// Not used
}
@Override
protected void setZoneSortColumnAndDirection() {
if (zoneTblData != null) {
zoneSortColumn = zoneTblData.getSortColumn();
zoneSortDirection = zoneTblData.getSortDirection();
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#
* setStnSortColumnAndDirection()
*/
@Override
protected void setStnSortColumnAndDirection() {
if (stnTblData != null) {
stnSortColumn = stnTblData.getSortColumn();
stnSortDirection = stnTblData.getSortDirection();
}
}
}

View file

@ -19,9 +19,8 @@
**/
package com.raytheon.uf.viz.monitor.fog.ui.resource;
import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.widgets.Display;
import org.opengis.referencing.FactoryException;
@ -29,51 +28,39 @@ import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.dataplugin.fog.FogRecord;
import com.raytheon.uf.common.dataplugin.fog.FogRecord.FOG_THREAT;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogCell;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogDataCorrector;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogMonitorUtils;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.geospatial.ReferencedObject.Type;
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.monitor.fog.FogCommonThreat;
import com.raytheon.uf.viz.monitor.fog.FogMonitor;
import com.raytheon.uf.viz.monitor.fog.xml.FogMonitorAlgorithmXML;
import com.vividsolutions.jts.algorithm.locate.SimplePointInAreaLocator;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
public class FogThreat {
/**
* Fog monitor threat calculation
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 1, 2012 skorolev Changed HashMap to Map and cleaned code.
* Nov 13, 2012 1297 skorolev Made abstract class FogCommonThreat
*
* </pre>
*
* @author skorolev
* @version 1.0
*/
public class FogThreat extends FogCommonThreat {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(FogThreat.class);
/** list of coordinates for each zone **/
public HashMap<String, ArrayList<Coordinate>> zoneCoordinates = null;
private final GeometryFactory geoFactory = new GeometryFactory();
private FogRecord fog = null;
private FogMonitorAlgorithmXML fogAlgXML = null;
private Geometry geoAdjAreas = null;
public FOG_THREAT[] threats = null;
public ArrayList<FogCell> cells = null;
public float[] ir_diff_thresholds = null;
public float[] vis_thresholds = null;
public int twilight_angle_offset = 0;
// boolean filter switches
public boolean isSnowIce = true;
public boolean isFractalDimension = true;
public boolean isSmoothness = true;
public boolean isAdjacency = true;
private FogMonitor monitor;
/** Fog monitor **/
private FogMonitor fmonitor = FogMonitor.getInstance();
/**
* serialization constructor
@ -84,732 +71,38 @@ public class FogThreat {
/**
* used constructor
*
* @param fogAlgXML
*/
public FogThreat(FogMonitorAlgorithmXML fogAlgXML) {
this.fogAlgXML = fogAlgXML;
setThresholdArrays();
zoneGeos = fmonitor.getMonitoringAreaGeometries();
geoAdjAreas = fmonitor.getGeoAdjAreas();
}
/**
* This method will be called with the switches from the GUI front end
/*
* (non-Javadoc)
*
* Fog Product [T(10.7) - (T(3.9)] or VIS (normalized count) Maximum cloud
* temperature Daytime Ice/Snow vs Fog Threshold (c) (FogSnowIceFilter) Cool
* Fog vs Warm Surface threshold Daytime Smoothness Algorithm
* (FogSmoothnessFilter) Adjacency Threshold Twilight Angle Threshold
* Fractal Dimension Threshold (FogFractalFilter)
* @see
* com.raytheon.uf.viz.monitor.fog.FogCommonThreat#setMonitorAreaThreats()
*/
public FogRecord getFogThreat(FogRecord fog) {
this.fog = fog;
System.out.println("FogThreat: Start analyzing Fog Threat...");
long start = System.currentTimeMillis();
this.geoAdjAreas = getFogMonitor().getGeoAdjAreas();
// clear threats array, make gray (SK)i=>x j=>y
for (int i = 0; i < fog.getNx(); i++) {
for (int j = 0; j < fog.getNy(); j++) {
// (SK) getThreats()[fog.getNy() * i + j] = FOG_THREAT.GRAY;
getThreats()[fog.getNx() * j + i] = FOG_THREAT.GRAY;
}
}
// First execute the data corrector, this divides up the FogRecord field
// into Day, Night, and Twilight.
FogDataCorrector fdc = new FogDataCorrector(getFog(),
fogAlgXML.getTwilightAngle());
fog = fdc.execute();
// Second, core processor. Gets you the cells, sets non-filtered values.
executeCoreProcessor();
// Third, apply filters
for (FogCell cell : getCells()) {
// *********** APPLY FILTERS *******************
// Area Size filter
if (fogAlgXML.isAdjacencyThreshOn()
&& cell.getCellThreat() != FOG_THREAT.GREEN
&& cell.getCellThreat() != FOG_THREAT.GRAY) {
if (cell.getArea() < fogAlgXML.getAdjacencyThresh()) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
}
}
// Snow & Ice filter
if (fogAlgXML.isIceSnowVsFogOn()
&& cell.getImageGroup() == FogRecord.IMAGE_GROUP.VIS_GROUP
&& (cell.getCellThreat() != FOG_THREAT.GREEN || cell
.getCellThreat() != FOG_THREAT.GRAY)) {
float tempMean = calAverageTemp(cell);
if (tempMean < fogAlgXML.getIceSnowVsFog()) {
downgradeThreat(cell);
}
}
// Smoothness filter
if (fogAlgXML.isDaytimeSmoothThreshOn()
&& cell.getCellThreat() != FOG_THREAT.GREEN
|| cell.getCellThreat() != FOG_THREAT.GRAY) {
float tem_smoothness = calSmoothness(cell);
if (tem_smoothness < fogAlgXML.getDaytimeSmoothThresh()) {
downgradeThreat(cell);
}
}
// Fractal filter
if (fogAlgXML.isFractalDimensionOn()
&& cell.getCellThreat() != FOG_THREAT.GREEN
&& cell.getCellThreat() != FOG_THREAT.GRAY) {
float temFD = calRegularity(cell);
if (temFD > fogAlgXML.getFractalDimension() && temFD > 0.0f) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
}
}
// We extract the zone threat differently than the GI filter
// Hence it is not needed.
}
setThreats();
setMonitorAreaThreats();
System.out.println("FogThreat: Analyzed Fog Threat...Duration: "
+ (System.currentTimeMillis() - start));
return fog;
}
/**
* Remember J is X and I is Y, totally against convention! Gets the threat
* level
*
* @param i
* (SK y)
* @param j
* (SK x)
* @param group
* @return
*/
private FOG_THREAT getThreatLevel(int i, int j, FogRecord.IMAGE_GROUP group) {
// (SK) i=>x, j=>y
// default return
FOG_THREAT returnValue = FOG_THREAT.GRAY;
// (SK) idx = fog.getNy() * i + j
int idx = fog.getNx() * j + i;
switch (group) {
case VIS_GROUP:
float ir4_temp = bTemp(i, j, FogRecord.CHANNEL.IR10_7);
int CLOUD_FREE_BRIGHTNESS = 68; // empirical value
// Too cold
if (ir4_temp < fogAlgXML.getMaxCloudTemp()) {
returnValue = FOG_THREAT.GRAY;
}
// overlapping high/middle cloud
else if (fog.getVisArray()[idx] <= vis_thresholds[2]
&& fog.getVisArray()[idx] >= vis_thresholds[1]) {
returnValue = FOG_THREAT.RED;
} else if (fog.getVisArray()[idx] < vis_thresholds[1]
&& fog.getVisArray()[idx] >= vis_thresholds[0]
|| fog.getVisArray()[idx] <= vis_thresholds[3]
&& fog.getVisArray()[idx] > vis_thresholds[2]) {
returnValue = FOG_THREAT.YELLOW;
}
// This is essentially the Cool Fog vs. Warm surface threshold check
else if (fogAlgXML.isCoolFogVsWarmSurfaceOn()
&& ir4_temp >= fogAlgXML.getCoolFogVsWarmSurface()) {
returnValue = FOG_THREAT.GREEN;
}
else if (fog.getVisArray()[idx] < CLOUD_FREE_BRIGHTNESS) {
returnValue = FOG_THREAT.GREEN;
}
return returnValue;
case IR_GROUP:
// for some odd reason j is x and i is y,
// not sure why AWIPS 1 does it this way.
// It is completely against convention.
// Point tempoint = new Point(j, i);
// (SK) here i=>x and j=>y
Point tempoint = new Point(i, j);
float tempIR10_7 = temp_at_vis_pixel(tempoint,
FogRecord.CHANNEL.IR10_7);
if (tempIR10_7 < fogAlgXML.getMaxCloudTemp()) {
// Too cold
returnValue = FOG_THREAT.GRAY;
}
// Overlapping high/middle cloud
float tempIR3_9 = temp_at_vis_pixel(tempoint,
FogRecord.CHANNEL.IR3_9);
float tempDiff = tempIR10_7 - tempIR3_9;
if (tempDiff <= ir_diff_thresholds[2]
&& tempDiff >= ir_diff_thresholds[1]) {
returnValue = FOG_THREAT.RED;
} else if (tempDiff < ir_diff_thresholds[1]
&& tempDiff >= ir_diff_thresholds[0]
|| tempDiff <= ir_diff_thresholds[3]
&& tempDiff > ir_diff_thresholds[2]) {
returnValue = FOG_THREAT.YELLOW;
} else {
returnValue = FOG_THREAT.GREEN;
}
case TWILIGHT_GROUP:
// do nothing, stays gray
}
return returnValue;
}
/**
* Precursor call to get temp at pixel
*
* @param i
* @param j
* @param imgtype
* @return
*/
private float bTemp(int i, int j, FogRecord.CHANNEL imgtype) {
// (SK) here i=>x and j=>y
// for some odd reason j is x and i is y,
// not sure why AWIPS 1 does it this way.
// It is completely against convention.
Point tempoint = new Point(i, j);
return temp_at_vis_pixel(tempoint, imgtype);
}
/**
* Get the temp at the pixel
*
* @param pointVis
* @param channel
* @return
*/
private float temp_at_vis_pixel(Point pointVis, FogRecord.CHANNEL channel) {
// The assumption is that Dimensions of IR4 and IR2 are the same.
// IR4 data will be always needed, so attributes for IR4 shall be
// always available.
// **** ATTENTION ***** We have made the vis the same as well for AWIPS
// II
int count_value = 255;
if (channel == FogRecord.CHANNEL.IR3_9) {
count_value = fog.getIR_3_9Array()[fog.getNx() * pointVis.y
+ pointVis.x];
// (SK) count_value = fog.getIR_3_9Array()[fog.getNy() * pointVis.x
// + pointVis.y];
} else if (channel == FogRecord.CHANNEL.IR10_7) {
count_value = fog.getIR_10_7Array()[fog.getNx() * pointVis.y
+ pointVis.x];
// (SK) count_value = fog.getIR_10_7Array()[fog.getNy() * pointVis.x
// + pointVis.y];
}
return FogMonitorUtils.count2temp(count_value, channel);
}
/**
* Gets the fog
*
* @return
*/
public FogRecord getFog() {
return fog;
}
/**
* Gets the existing array of threats
*
* @return
*/
public FOG_THREAT[] getThreats() {
if (threats == null) {
threats = new FOG_THREAT[getFog().getNx() * getFog().getNy()];
}
return threats;
}
/**
* Gets the cells of this analysis
*
* @return
*/
public ArrayList<FogCell> getCells() {
return cells;
}
/**
* Gets the existing threat value at that point
*
* @return
*/
public FOG_THREAT getThreat(int i, int j) {
return getThreats()[fog.getNx() * j + i];
// (SK) return getThreats()[fog.getNy() * i + j];
}
/**
* Set fog threat at threat level point
*
* @param i
* @param j
* @param threat
*/
private void setThreat(int i, int j, FOG_THREAT threat) {
// (SK) getThreats()[fog.getNy() * i + j] = threat;
getThreats()[fog.getNx() * j + i] = threat;
}
/**
* Downgrade the Fog Threat
*
* @param current
* @param i
* @param j
*/
private void downgradeThreat(FogCell cell) {
if (cell.getCellThreat() == FOG_THREAT.YELLOW) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
} else if (cell.getCellThreat() == FOG_THREAT.RED) {
setCellThreats(cell.getPoints(), FOG_THREAT.YELLOW);
}
}
// // *********************** FILTERS **************************** /////
// -Private--------------------------------------------------------------------
// NAME: CalRegularity()
//
// TYPE: Private Member function
//
// Descript:
// Given a cell, calculate its regularity i.e. the fractal dimension
// Input Arguments:
// cell: The Fog_Cell whose fractal dimension is to be measured
// Output Arguments:
// Return float: fractal dimension. the value is between 1 to 2
// smaller means more regular.
// Here use the perimeter and area relation to represent
// fractal dimension (one of the simply ways)
// History:
// May 2004 Qin Zeng (GDMB/MDL) -- created
// Dec 2009 D Hladky translated to Java
// -----------------------------------------------------------------------------
private float calRegularity(FogCell cell) {
int nx = cell.right - cell.left + 1;
int ny = cell.bottom - cell.top + 1;
int i;
boolean[] flag = new boolean[nx * ny];
for (i = 0; i < nx * ny; i++) {
flag[i] = false;
}
int pixels_num = (int) cell.getArea();
int flagPos;
for (i = 0; i < pixels_num; i++) {
Coordinate coor = cell.getPixelCoordinate(i);
flagPos = (int) ((coor.y - cell.top) * nx + coor.x - cell.left);
if (flagPos >= 0 && flagPos < nx * ny) {
flag[flagPos] = true;
}
}
// From here, perimeter of the fog cell will be calculated;
// |...| 1 |...|
// | 4 | 0 | 2 |
// |...| 3 |...|
//
// If the any of the 0's surrounding pixels(1,2,3,4) is flagged as
// false,
// which means that surrounding pixel(1,2,3,or 4) is not included in
// the cell, pixel 0 then will be at the edge of the cell cluster.
// And the edge connecting to the outside pixel will be counted into the
// perimeter of the cell cluster.
int pos1, pos2, pos3, pos4;
float perimeter = 0;
for (i = 0; i < pixels_num; i++) {
Coordinate coor = cell.getPixelCoordinate(i);
pos1 = (int) ((i - cell.top - 1) * nx + coor.y - cell.left);
if (pos1 >= 0 && pos1 < nx * ny && !flag[pos1]
|| i - coor.x < cell.top) {
perimeter++;
}
pos2 = (int) ((coor.y - cell.top) * nx + coor.x + 1 - cell.left);
if (pos2 >= 0 && pos2 < nx * ny && !flag[pos2]
|| coor.x + 1 > cell.right) {
perimeter++;
}
pos3 = (int) ((coor.y - cell.top + 1) * nx + coor.x - cell.left);
if (pos3 >= 0 && pos3 < nx * ny && !flag[pos3]
|| coor.y + 1 > cell.bottom) {
perimeter++;
}
pos4 = (int) ((coor.y - cell.top) * nx + coor.x - 1 - cell.left);
if (pos4 >= 0 && pos4 < nx * ny && !flag[pos4]
|| coor.x - 1 < cell.left) {
perimeter++;
}
}
float fractalDimension = 1.0f;
if (cell.getArea() != 1) {
fractalDimension = (float) (2 * Math.log(perimeter / 4.0) / Math
.log(cell.getArea()));
}
// Note : fractalDimension is a data between 1 and 2 and the larger
// fractalDimension is , the more irregular the shape of the cell will
// be.
return fractalDimension;
}
// -Private--------------------------------------------------------------------
// NAME: CalSmoothness()
//
// TYPE: Private Member function
//
// Descript:
// Given a cell, calculate the its smoothness
// Input Arguments:
// cell: The Fog_Cell whose smoothness is to be measured
// Output Arguments:
// return float: smoothness defined above
// History:
// May 2004 Qin Zeng (GDMB/MDL) -- created
// Dec 2009 D Hladky ported to AWIPS II
// -----------------------------------------------------------------------------
private float calSmoothness(FogCell cell) {
float mean = 0; // mean grayscale value of pixels in the cell from VIS.
float stdDev = 0; // standard deviation
int pixels_num = (int) cell.getArea();
if (pixels_num == 0) {
return 0;
}
int i;
for (i = 0; i < pixels_num; i++) {
Coordinate pixr = cell.getPixelRelativeCoordinate(i);
// (SK) mean += getFog().getVisArray()[(int) (getFog().getNy() *
// pixr.x + pixr.y)];
mean += getFog().getVisArray()[(int) (getFog().getNx() * pixr.y + pixr.x)];
}
mean /= pixels_num;
float tem_float;
for (i = 0; i < pixels_num; i++) {
Coordinate pixr = cell.getPixelRelativeCoordinate(i);
// (SK) tem_float = getFog().getVisArray()[(int) (getFog().getNy() *
// pixr.x + pixr.y)];
tem_float = getFog().getVisArray()[(int) (getFog().getNx() * pixr.y + pixr.x)];
stdDev += (tem_float - mean) * (tem_float - mean);
}
stdDev /= pixels_num;
stdDev = (float) Math.sqrt(stdDev);
// mean should not be zero, so no need to check mean here.
return (1 - stdDev / mean) * 100; // use percent as unit
}
// -Private---------------------------------------------------------------------
// NAME: Cal()
//
// TYPE: Private Member function
//
// Descript:
// Calculate the average temperature for a Fog_Cell in channel 3.9 um
// History:
// May 2004 Qin Zeng (GDMB/MDL) -- created
// -----------------------------------------------------------------------------
private float calAverageTemp(FogCell cell) {
float mean = 0; // mean temperature value of pixels in the cell.
int pixels_num = (int) cell.getArea();
if (pixels_num == 0) {
return -999.9f;
}
for (int i = 0; i < pixels_num; i++) {
Coordinate pixc = cell.getPixelRelativeCoordinate(i);
mean += temp_at_vis_pixel(new Point((int) pixc.x, (int) pixc.y),
FogRecord.CHANNEL.IR3_9);
}
mean /= pixels_num;
return mean;
}
// -Public---------------------------------------------------------------------
// NAME: Execute()
//
// TYPE: Private Member function
//
// Descript:
// Based on the thresholds of the VIS image data and the IR image data,
// a number of patches of the contiguous suspected fog areas will be
// extracted from the satellite image data.
// This is an implementation of the feature extraction algorithm based
// on the contiguous gray scale values.
//
// Arguments: None
// History:
// March 2004 Qin Zeng (GDMB/MDL) -- created
// Dec 2009 D Hladky ported to Java for AWIPS II
// -----------------------------------------------------------------------------
private void executeCoreProcessor() {
cells = new ArrayList<FogCell>();
ArrayList<Point> parent = new ArrayList<Point>();
ArrayList<Point> child = new ArrayList<Point>();
ArrayList<Point> single_segment = new ArrayList<Point>();
int x_dim = getFog().getNx();
int y_dim = getFog().getNy();
int i; // (SK) x
int j; // (SK) y
// To flag whether a pixel has been visited or not
boolean[][] visited = new boolean[x_dim][y_dim];
Point[] s = new Point[8]; // 8 surrounding points of one specific point
for (int z = 0; z < s.length; z++) {
s[z] = new Point();
}
Point tempoint = new Point();
getCells().clear();
for (i = 0; i < x_dim; i++) {
for (j = 0; j < y_dim; j++) {
visited[i][j] = false;
}
}
for (j = 0; j < y_dim; j++) {
Point firstone = new Point();
FOG_THREAT threat_level = FOG_THREAT.BLACK;
FogRecord.IMAGE_GROUP imggroup;
for (i = 0; i < x_dim; i++) {
if (visited[i][j]) {
continue;
}
Coordinate cellCoor = this.getCellCoor(i, j);
visited[i][j] = true;
imggroup = getFog().findGroup(i, j);
threat_level = getThreatLevel(i, j, imggroup);
// Sets the initial threat level
setThreat(i, j, threat_level);
firstone.x = i;
firstone.y = j;
parent.clear();
tempoint.y = j;
tempoint.x = i;
single_segment.add(tempoint);
parent.add(tempoint);
while (parent.size() != 0) {
// the variables(s[1],s[2]...) below mean surrounding 1,2
// | 0 | 1 | 2 |
// | 7 | i | 3 |
// | 6 | 5 | 4 |
// iteratively search the 8-connected surrounding pixels
child.clear();
for (int k = 0; k < parent.size(); k++) {
// y's too small, too big
if (parent.get(k).y == 0) {
s[0].y = parent.get(k).y;
s[1].y = parent.get(k).y;
s[2].y = parent.get(k).y;
}
if (parent.get(k).y == y_dim - 1) {
s[4].y = parent.get(k).y;
s[5].y = parent.get(k).y;
s[6].y = parent.get(k).y;
}
// x's too small, too big
if (parent.get(k).x == 0) {
s[0].x = parent.get(k).x;
s[6].x = parent.get(k).x;
s[7].x = parent.get(k).x;
}
if (parent.get(k).x == x_dim - 1) {
s[2].x = parent.get(k).x;
s[3].x = parent.get(k).x;
s[4].x = parent.get(k).x;
}
// all others
if (parent.get(k).x > 0 && parent.get(k).x < x_dim - 1
&& parent.get(k).y < y_dim - 1
&& parent.get(k).y > 0) {
s[0].y = parent.get(k).y - 1;
s[0].x = parent.get(k).x - 1;
s[1].y = parent.get(k).y - 1;
s[1].x = parent.get(k).x;
s[2].y = parent.get(k).y - 1;
s[2].x = parent.get(k).x + 1;
s[3].y = parent.get(k).y;
s[3].x = parent.get(k).x + 1;
s[4].y = parent.get(k).y + 1;
s[4].x = parent.get(k).x + 1;
s[5].y = parent.get(k).y + 1;
s[5].x = parent.get(k).x;
s[6].y = parent.get(k).y + 1;
s[6].x = parent.get(k).x - 1;
s[7].y = parent.get(k).y;
s[7].x = parent.get(k).x - 1;
}
FogRecord.IMAGE_GROUP temgroup;
FOG_THREAT temthreat;
for (int m = 0; m < 8; m++) {
if (s[m].y >= 0 && s[m].y < y_dim && s[m].x >= 0
&& s[m].x < x_dim) {
int ii = s[m].x;
int jj = s[m].y;
// (SK) int ii = s[m].y;
// (SK) int jj = s[m].x;
if (!visited[ii][jj]) {
temgroup = getFog().findGroup(ii, jj);
temthreat = getThreatLevel(ii, jj, temgroup);
if (temgroup == imggroup
&& temthreat == threat_level) {
child.add(s[m]);
visited[ii][jj] = true;
single_segment.add(s[m]);
}
}// end of if
}// end of if
}// end of for m
}// end of for k
parent = child;
}// end of while
// if (!this.geoAdjAreas
// .contains(geoFactory.createPoint(cellCoor))) {
int lct = SimplePointInAreaLocator.locate(cellCoor,
this.geoAdjAreas);
if (lct == 2) {
threat_level = FOG_THREAT.BLACK;
setThreat(i, j, threat_level);
}
getCells().add(
new FogCell(single_segment, threat_level, imggroup));
single_segment.clear();
} // end of for i
} // end of for j
}
/**
* Sets all points in the cell to the cell filtered value threat
*
* @param cells
* @param threat
*/
private void setCellThreats(ArrayList<Point> points, FOG_THREAT threat) {
for (Point point : points) {
getThreats()[fog.getNx() * point.y + point.x] = threat;
// (SK) getThreats()[fog.getNy() * point.x + point.y] = threat;
}
}
/**
* Gets the drawable float array of threats
*
* @return
*/
private void setThreats() {
float[] floats = new float[getThreats().length];
int i = 0;
for (FOG_THREAT threat : getThreats()) {
floats[i] = getThreatValue(threat);
i++;
}
getFog().setThreats(floats);
}
/**
* Sets the thresholds
*/
private void setThresholdArrays() {
ir_diff_thresholds = new float[4];
vis_thresholds = new float[4];
ir_diff_thresholds[0] = (float) fogAlgXML.getFogProductYLo();
ir_diff_thresholds[1] = (float) fogAlgXML.getFogProductYHi();
ir_diff_thresholds[2] = (float) fogAlgXML.getFogProductRLo();
ir_diff_thresholds[3] = (float) fogAlgXML.getFogProductRHi();
vis_thresholds[0] = (float) fogAlgXML.getVisYLo();
vis_thresholds[1] = (float) fogAlgXML.getVisYHi();
vis_thresholds[2] = (float) fogAlgXML.getVisRLo();
vis_thresholds[3] = (float) fogAlgXML.getVisRHi();
}
/**
* Quick static method to get the float to threat mapping
*
* @param threat
* @return
*/
public static float getThreatValue(FOG_THREAT threat) {
float value = 0;
if (threat == FOG_THREAT.BLACK) {
value = 0.0f;
} else if (threat == FOG_THREAT.GRAY) {
value = 15.0f;
} else if (threat == FOG_THREAT.GREEN) {
value = 60.0f;
} else if (threat == FOG_THREAT.YELLOW) {
value = 110.0f;
} else if (threat == FOG_THREAT.RED) {
value = 220.0f;
}
return value;
}
/**
* Gets the zone threats (ALG) with worst case for zone area
*
* @return HashMap<String, FOG_THREAT>
*/
public void setMonitorAreaThreats() {
@Override
protected void setMonitorAreaThreats() {
final FogRecord ffogRec = getFog();
final FogMonitor fmonitor = getFogMonitor();
// TODO: async or sync ????
Display.getDefault().asyncExec(new Runnable() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
long start = System.currentTimeMillis();
HashMap<String, Geometry> zoneGeos = fmonitor
.getMonitoringAreaGeometries();
// set to lowest for default
HashMap<String, FOG_THREAT> zoneThreats = new HashMap<String, FOG_THREAT>();
Map<String, FOG_THREAT> zoneThreats = new HashMap<String, FOG_THREAT>();
for (String zone : zoneGeos.keySet()) {
zoneThreats.put(zone, FOG_THREAT.BLACK);
}
for (int i = 0; i < ffogRec.getNx(); i++) {
for (int j = 0; j < ffogRec.getNy(); j++) {
ReferencedCoordinate rc = new ReferencedCoordinate(
new Coordinate(i, j),
ffogRec.getGridGeometry(), Type.GRID_CENTER);
@ -817,9 +110,9 @@ public class FogThreat {
try {
coor = rc.asLatLon();
} catch (TransformException e) {
e.printStackTrace();
statusHandler.handle(Priority.ERROR, e.getMessage());
} catch (FactoryException e) {
e.printStackTrace();
statusHandler.handle(Priority.ERROR, e.getMessage());
}
for (String zone : zoneGeos.keySet()) {
@ -833,42 +126,25 @@ public class FogThreat {
getThreat(i, j));
}
} catch (Exception e) {
e.printStackTrace();
statusHandler.handle(Priority.ERROR,
e.getMessage());
}
}
}
}
}
}
} // end zone loop
} // end j loop
} // end i loop
fmonitor.setAlgorithmData(ffogRec.getRefHour().getTime(),
zoneThreats);
System.out.println("FogThreat: Set algorithm zone values..."
+ (System.currentTimeMillis() - start));
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.handle(Priority.DEBUG,
"FogThreat for SS: Set algorithm zone values..."
+ (System.currentTimeMillis() - start));
}
}
});
}
private Coordinate getCellCoor(int i, int j) {
ReferencedCoordinate rc = new ReferencedCoordinate(
new Coordinate(i, j), this.getFog().getGridGeometry(),
Type.GRID_CENTER);
Coordinate crd = null;
try {
crd = rc.asLatLon();
} catch (TransformException e) {
e.printStackTrace();
} catch (FactoryException e) {
e.printStackTrace();
}
return crd;
}
/** Get the Fog monitor **/
public FogMonitor getFogMonitor() {
if (monitor == null) {
monitor = FogMonitor.getInstance();
}
return monitor;
}
}

View file

@ -1,61 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.monitor.safeseas;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
/**
* Kick off the SAFESEAS dialog and application backend processes.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 1/27/09 dhladky Initial Creation.
*
* </pre>
*
* @author dhladky
*
*/
public class SafeSeasAction extends AbstractHandler {
@Override
public Object execute(ExecutionEvent arg0) throws ExecutionException {
System.out.println("Activating/Action the SAFESEAS plugin...");
SafeSeasMonitor ssm = SafeSeasMonitor.getInstance();
if (ssm.zoneDialog == null || ssm.zoneDialog.isDisposed()) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell();
ssm.launchDialog("zone", shell);
}
return null;
}
}

View file

@ -23,7 +23,8 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.eclipse.swt.graphics.RGB;
@ -38,8 +39,9 @@ import com.raytheon.uf.common.monitor.config.SSMonitorConfigurationManager;
import com.raytheon.uf.common.monitor.data.AdjacentWfoMgr;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.CommonTableConfig.CellType;
import com.raytheon.uf.common.monitor.data.ObConst.ChosenAppKey;
import com.raytheon.uf.common.time.DataTime;
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.alerts.AlertMessage;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.notification.NotificationMessage;
@ -78,6 +80,8 @@ import com.vividsolutions.jts.geom.Geometry;
* Dec 30, 2009 3424 zhao use ObMultiHrsReports for obs data archive over time
* July 20,2010 4891 skorolev Added resource listener
* May 15, 2012 14510 zhao Modified processing at startup
* Oct 26, 2012 1280 skorolev Clean code and made changes for non-blocking dialog
* Oct 30, 2012 1297 skorolev Changed HashMap to Map
*
* </pre>
*
@ -87,24 +91,27 @@ import com.vividsolutions.jts.geom.Geometry;
*/
public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(SafeSeasMonitor.class);
/** Singleton instance of this class */
private static SafeSeasMonitor monitor = null;
/** zone table dialog **/
public SSZoneTableDlg zoneDialog = null;
private SSZoneTableDlg zoneDialog;
/**
* monitoring area config dialog
*/
SSMonitoringAreaConfigDlg areaDialog = null;
/** monitoring area config dialog **/
private SSMonitoringAreaConfigDlg areaDialog = null;
/** configuration manager **/
private SSMonitorConfigurationManager safeseasConfig = null;
/**
* This object contains all observation data necessary for the table dialogs
* and trending plots
*/
private ObMultiHrsReports obData;
private ObMultiHrsReports obData;
/** table data for the zone table **/
private final TableData zoneTableData = new TableData(
@ -114,116 +121,157 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
private final TableData stationTableData = new TableData(
CommonConfig.AppName.SAFESEAS);
/** All SafeSeas plugins start with this */
private static String OBS = "fssobs";
/** All SafeSeas datauri start with this */
private final String OBS = "fssobs";
/** regex wild card filter */
protected static String wildCard = "[\\w\\(\\)-_:.]+";
private final String wildCard = "[\\w\\(\\)-_:.]+";
/** The application key */
ChosenAppKey chosenAppKey = ChosenAppKey.SAFESEAS;
/** List of SAFESEAS resource listeners **/
private final List<ISSResourceListener> safeSeasResources = new ArrayList<ISSResourceListener>();
private final ArrayList<ISSResourceListener> safeSeasResources = new ArrayList<ISSResourceListener>();
/** Time which Zone/County dialog shows. **/
private Date dialogTime = null;
/**
* Time which Zone/County dialog shows.
*/
public Date dialogTime = null;
/** list of coordinates for each zone **/
private Map<String, Geometry> zoneGeometries = null;
/** list of coordinates for each zone **/
public HashMap<String, Geometry> zoneGeometries = null;
/** data holder for FOG data **/
public HashMap<Date, HashMap<String, FOG_THREAT>> algorithmData = null;
/** data holder for FOG data **/
private Map<Date, Map<String, FOG_THREAT>> algorithmData = null;
/** Adjacent areas for current cwa **/
private Geometry geoAdjAreas;
/** Array of fogAlg listeners **/
private final ArrayList<ISSResourceListener> fogResources = new ArrayList<ISSResourceListener>();
/** List of fogAlg listeners **/
private final List<ISSResourceListener> fogResources = new ArrayList<ISSResourceListener>();
/** Pattern for SAFESEAS **/
private final Pattern ssPattern = Pattern
.compile(URIFilter.uriSeperator + OBS + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + cwa + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + "ss");
/**
* Private constructor, singleton
*/
private SafeSeasMonitor() {
pluginPatterns.add(ssPattern);
pluginPatterns.add(ssPattern);
readTableConfig(MonitorThresholdConfiguration.SAFESEAS_THRESHOLD_CONFIG);
initObserver("fssobs", this);
initObserver(OBS, this);
}
/**
* @return instance of monitor
*/
public static synchronized SafeSeasMonitor getInstance() {
if (monitor == null) {
monitor = new SafeSeasMonitor();
// Pre-populate dialog with an observation (METAR) for KOMA
monitor.createDataStructures();
// Pre-populate dialog with an observation (METAR) for KOMA
monitor.createDataStructures();
monitor.getAdjAreas();
monitor.processProductAtStartup("ss");
monitor.fireMonitorEvent(monitor);
monitor.processProductAtStartup("ss");
monitor.fireMonitorEvent(monitor);
}
return monitor;
}
// TODO: Provide the changes in EDEX URIFilters when area configuration file
// has been changed.
/**
* DR#11279:
* When monitor area configuration is changed,
* this module is called to re-initialize monitor
* using new monitor area configuration
* DR#11279: When monitor area configuration is changed, this module is
* called to re-initialize monitor using new monitor area configuration
*/
public static void reInitialize() {
if ( monitor != null ) {
monitor = null;
monitor = new SafeSeasMonitor();
}
}
/**
* Creates the maps
*/
private void createDataStructures() {
// [Jan 21, 2010, zhao]
obData = new ObMultiHrsReports(CommonConfig.AppName.SAFESEAS);
obData.setThresholdMgr(SSThresholdMgr.getInstance());
algorithmData = new HashMap<Date, HashMap<String, FOG_THREAT>>();
}
public void launchDialog(String type, Shell shell) {
if (type.equals("zone")) {
if (zoneDialog == null) {
zoneDialog = new SSZoneTableDlg(shell, obData);
addMonitorListener(zoneDialog);
zoneDialog.addMonitorControlListener(this);
}
zoneDialog.open();
fireMonitorEvent(zoneDialog.getClass().getName());
} else if (type.equals("area")) {
areaDialog = new SSMonitoringAreaConfigDlg(shell,
"Safe Seas Monitor Area Configuration");
areaDialog.open();
if (monitor != null) {
monitor = null;
monitor = new SafeSeasMonitor();
}
}
/**
* Creates the maps
*/
private void createDataStructures() {
obData = new ObMultiHrsReports(CommonConfig.AppName.SAFESEAS);
obData.setThresholdMgr(SSThresholdMgr.getInstance());
algorithmData = new HashMap<Date, Map<String, FOG_THREAT>>();
}
/**
* Launch SAFESEAS Zone Dialog
*
* @param type
* @param shell
*/
public void launchDialog(String type, Shell shell) {
if (type.equals("zone")) {
if (zoneDialog == null || zoneDialog.getShell() == null
|| zoneDialog.isDisposed()) {
zoneDialog = new SSZoneTableDlg(shell, obData);
addMonitorListener(zoneDialog);
zoneDialog.addMonitorControlListener(this);
fireMonitorEvent(zoneDialog.getClass().getName());
zoneDialog.open();
} else {
zoneDialog.bringToTop();
}
} else if (type.equals("area")) {
if (areaDialog == null) {
areaDialog = new SSMonitoringAreaConfigDlg(shell,
"Safe Seas Monitor Area Configuration");
areaDialog.open();
}
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#filterNotifyMessage(com.raytheon
* .uf.viz.core.notification.NotificationMessage)
*/
@Override
public boolean filterNotifyMessage(NotificationMessage alertMessage) {
return false;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processNotifyMessage(com.raytheon
* .uf.viz.core.notification.NotificationMessage)
*/
@Override
public void processNotifyMessage(NotificationMessage filtered) {
// Not used
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processProductMessage(com.raytheon
* .uf.viz.core.alerts.AlertMessage)
*/
@Override
public void processProductMessage(final AlertMessage filtered) {
if (ssPattern.matcher(filtered.dataURI).matches()) {
// System.out.println("Found match: " + ssPattern + " URI: "
// + filtered.dataURI);
processURI(filtered.dataURI, filtered);
}
if (ssPattern.matcher(filtered.dataURI).matches()) {
processURI(filtered.dataURI, filtered);
}
}
/**
* Adds data to station table
*
* @param trd
* @param stationID
*/
public void addToStationDataTable(TableRowData trd, String stationID) {
int numberCell = trd.getNumberOfCellData();
TableRowData stationRowData = new TableRowData(numberCell + 1);
@ -233,7 +281,6 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
for (int i = 0; i < numberCell; i++) {
stationRowData.setTableCellData(i + 1, trd.getTableCellData(i));
}
stationTableData.addReplaceDataRow(stationRowData);
}
@ -245,22 +292,28 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
* -- the xml configuration filename
*/
public void readTableConfig(String file) {
HashMap<String, ArrayList<String>> zones = new HashMap<String, ArrayList<String>>();
Map<String, List<String>> zones = new HashMap<String, List<String>>();
// create zones and station list
try {
SSMonitorConfigurationManager areaConfig = getMonitorAreaConfig();
for (String zone : areaConfig.getAreaList()) {
ArrayList<String> stations = areaConfig.getAreaStations(zone);
List<String> stations = areaConfig.getAreaStations(zone);
zones.put(zone, stations);
}
} catch (Exception e) {
System.out.println("SafeSeas failed to load configuration..."
+ this.getClass().getName());
statusHandler.handle(Priority.CRITICAL,
"SafeSeas failed to load configuration..."
+ this.getClass().getName(), e);
}
MonitoringArea.setPlatformMap(zones);
}
public SSMonitorConfigurationManager getMonitorAreaConfig() {
/**
* Gets configuration manager
*
* @return safeseasConfig
*/
private SSMonitorConfigurationManager getMonitorAreaConfig() {
if (safeseasConfig == null) {
LocalizationManager mgr = LocalizationManager.getInstance();
String siteScope = mgr.getCurrentSite();
@ -271,104 +324,144 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
return safeseasConfig;
}
private Pattern ssPattern = Pattern
.compile(URIFilter.uriSeperator + OBS + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + cwa + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + "ss");
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.Monitor#initObserver(java.lang.String,
* com.raytheon.uf.viz.monitor.Monitor)
*/
@Override
public void initObserver(String pluginName, Monitor monitor) {
ProductAlertObserver.addObserver(pluginName, this);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#thresholdUpdate(com.raytheon.uf
* .viz.monitor.events.IMonitorThresholdEvent)
*/
@Override
public void thresholdUpdate(IMonitorThresholdEvent me) {
fireMonitorEvent(zoneDialog.getClass().getName());
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#configUpdate(com.raytheon.uf.viz
* .monitor.events.IMonitorConfigurationEvent)
*/
@Override
public void configUpdate(IMonitorConfigurationEvent me) {
// Not used
}
/**
* Kill this monitor by nullifying the monitor's private instance variable.
* Kills this monitor by nullifying the monitor's private instance variable.
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ObsMonitor#nullifyMonitor()
*/
@Override
public void nullifyMonitor() {
// /**
// * Before making the monitor null, remove observers
// */
// for (String p : pluginName) {
// if (!pluginName.equals("")) {
// stopObserver(p, this);
// }
// }
monitor.removeMonitorListener(zoneDialog);
monitor.fogResources.removeAll(getMonitorListeners());
stopObserver("fssobs", this);
stopObserver(OBS, this);
monitor = null;
}
/**
* @return zoneTableData
*/
public TableData getZoneTableData() {
return zoneTableData;
}
/**
* @return stationTableData
*/
public TableData getStationTableData() {
return stationTableData;
}
/**
* Gets data
*
* @return obData
*/
public ObMultiHrsReports getObData() {
return obData;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#process(com.raytheon.uf.viz.monitor
* .data.ObReport)
*/
@Override
protected void process(ObReport result)
throws Exception {
// ProcessSafeSeasReport safeSeas = new ProcessSafeSeasReport(result);
// safeSeas.processSafeSeasReport();
// add data to obData
protected void process(ObReport result) throws Exception {
obData.addReport(result);
fireMonitorEvent(this);
}
/**
* SSResource sets the dialogTime
* SSResource updates the dialogTime
*
* @param dialogTime
*/
public void updateDialogTime(Date dialogTime) {
this.dialogTime = dialogTime;
fireMonitorEvent(zoneDialog.getClass().getName());
this.dialogTime = dialogTime;
fireMonitorEvent(zoneDialog.getClass().getName());
}
/**
* @return dialogTime
*/
public Date getDialogTime() {
return dialogTime;
}
/**
* Sets the dialogTime
*
* @param dialogTime
*/
public void setDialogTime(Date dialogTime) {
this.dialogTime = dialogTime;
}
/**
* Add recourse listener
*
* @param issr
*/
public void addSSResourceListener(ISSResourceListener issr) {
safeSeasResources.add(issr);
}
/**
* Remove recourse listener
*
* @param issr
*/
public void removeSSResourceListener(ISSResourceListener issr) {
safeSeasResources.remove(issr);
}
/**
* Close dialog
*/
public void closeDialog() {
if (zoneDialog != null) {
monitor.nullifyMonitor();
zoneDialog.removeMonitorContorlListener(this);
zoneDialog.shellDisposeDialog();
zoneDialog.close();
zoneDialog = null;
}
if (areaDialog != null) {
@ -378,124 +471,130 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
}
/**
* Order the dates
*
* @param type
* @return
*
* (non-Javadoc)
* @see com.raytheon.uf.viz.monitor.IMonitor#getTimeOrderedKeys(com.raytheon.
* uf.viz.monitor.IMonitor, java.lang.String)
*/
@Override
public ArrayList<Date> getTimeOrderedKeys(IMonitor monitor, String type) {
// Not used
return null;
}
/**
* Get most recent time
* Gets area geometries
*
* @param type
* @return
* @return zoneGeometries
*/
public DataTime getMostRecent(IMonitor monitor, String type) {
return null;
public Map<String, Geometry> getMonitoringAreaGeometries() {
if (zoneGeometries == null) {
ArrayList<String> zones = getMonitorAreaConfig().getAreaList();
zoneGeometries = new HashMap<String, Geometry>();
for (String zone : zones) {
try {
zoneGeometries.put(zone,
MonitorAreaUtils.getZoneGeometry(zone));
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Error get Monitoring Area Config", e);
}
}
}
return zoneGeometries;
}
public HashMap<String, Geometry> getMonitoringAreaGeometries() {
if (zoneGeometries == null) {
ArrayList<String> zones = getMonitorAreaConfig().getAreaList();
zoneGeometries = new HashMap<String, Geometry>();
for (String zone : zones) {
try {
zoneGeometries.put(zone,
MonitorAreaUtils.getZoneGeometry(zone));
} catch (Exception e) {
e.printStackTrace();
}
}
}
return zoneGeometries;
}
/**
* Gets threats
*
* @param refTime
* @param zoneThreats
*/
public void setAlgorithmData(Date refTime,
Map<String, FOG_THREAT> zoneThreats) {
if (algorithmData.containsKey(refTime)) {
algorithmData.remove(refTime);
}
algorithmData.put(refTime, zoneThreats);
}
public void setAlgorithmData(Date refTime,
HashMap<String, FOG_THREAT> zoneThreats) {
if (algorithmData.containsKey(refTime)) {
algorithmData.remove(refTime);
}
algorithmData.put(refTime, zoneThreats);
}
/**
* Gets the algorithm threat by time
*
* @param time
* @return algData
*/
public Map<String, FOG_THREAT> getAlgorithmData(Date time) {
/**
* Gets the algorithm threat
*
* @param zone
* @return
*/
public HashMap<String, FOG_THREAT> getAlgorithmData(Date time) {
Map<String, FOG_THREAT> algData = new HashMap<String, FOG_THREAT>();
HashMap<String, FOG_THREAT> algData = new HashMap<String, FOG_THREAT>();
if ((algorithmData != null) && algorithmData.containsKey(time)) {
algData = algorithmData.get(time);
} else {
// by default is nothing in the Fog column
for (String zone : MonitoringArea.getPlatformMap().keySet()) {
algData.put(zone, FOG_THREAT.GRAY);
}
}
return algData;
}
if ((algorithmData != null) && algorithmData.containsKey(time)) {
algData = algorithmData.get(time);
} else {
// default nothing in Fog column
for (String zone : MonitoringArea.getPlatformMap().keySet()) {
algData.put(zone, FOG_THREAT.GRAY);
}
}
return algData;
}
/**
* Gets Fog threat types.
*
* @param fogAlgThreats
* @return types
*/
public Map<String, CellType> getAlgCellTypes(
Map<String, FOG_THREAT> fogAlgThreats) {
Map<String, CellType> types = new HashMap<String, CellType>();
for (String zone : fogAlgThreats.keySet()) {
CellType type = getAlgorithmCellType(fogAlgThreats.get(zone));
types.put(zone, type);
}
return types;
}
public HashMap<String, CellType> getAlgCellTypes(
HashMap<String, FOG_THREAT> fogAlgThreats) {
HashMap<String, CellType> types = new HashMap<String, CellType>();
for (String zone : fogAlgThreats.keySet()) {
CellType type = getAlgorithmCellType(fogAlgThreats.get(zone));
types.put(zone, type);
}
return types;
}
/**
* Gets cell threat type
*
* @param fog_THREAT
* @return type
*/
private CellType getAlgorithmCellType(FOG_THREAT fog_THREAT) {
CellType type = CellType.NotDetermined;
if (fog_THREAT == FogRecord.FOG_THREAT.GREEN) {
type = CellType.G;
} else if (fog_THREAT == FogRecord.FOG_THREAT.YELLOW) {
type = CellType.Y;
} else if (fog_THREAT == FogRecord.FOG_THREAT.RED) {
type = CellType.R;
}
return type;
}
private CellType getAlgorithmCellType(FOG_THREAT fog_THREAT) {
CellType type = CellType.NotDetermined;
if (fog_THREAT == FogRecord.FOG_THREAT.GREEN) {
type = CellType.G;
} else if (fog_THREAT == FogRecord.FOG_THREAT.YELLOW) {
type = CellType.Y;
} else if (fog_THREAT == FogRecord.FOG_THREAT.RED) {
type = CellType.R;
}
return type;
}
/**
* Get most recent time
*
* @param type
* @return
*/
public DataTime getMostRecent() {
DataTime time = null;
Set<Date> ds = this.algorithmData.keySet();
DataTime[] times = new DataTime[ds.size()];
int i = 0;
for (Date d : ds) {
times[i] = new DataTime(d);
i++;
}
java.util.Arrays.sort(times);
if (times.length > 0) {
time = times[times.length - 1]; // most recent
}
return time;
}
public ZoneTableDlg getDialog() {
return zoneDialog;
}
/**
* Gets zone dialog
*
* @return zoneDialog
*/
public ZoneTableDlg getDialog() {
return zoneDialog;
}
/**
* Gets adjacent areas
*/
public void getAdjAreas() {
this.setGeoAdjAreas(AdjacentWfoMgr.getAdjacentAreas(cwa));
}
/**
* Sets geometry of adjacent areas
*
* @param geoAdjAreas
* the geoAdjAreas to set
*/
@ -504,6 +603,8 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
}
/**
* Gets geometry of adjacent areas
*
* @return the geoAdjAreas
*/
public Geometry getGeoAdjAreas() {
@ -511,6 +612,8 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
}
/*
* Updates data of Fog monitor
*
* (non-Javadoc)
*
* @see
@ -531,9 +634,25 @@ public class SafeSeasMonitor extends ObsMonitor implements ISSResourceListener {
}
@Override
protected void processAtStartup(ObReport report) {
obData.addReport(report);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processAtStartup(com.raytheon.
* uf.viz.monitor.data.ObReport)
*/
@Override
protected void processAtStartup(ObReport report) {
obData.addReport(report);
}
/**
* Gets SAFESEAS zone table dialog
*
* @return
*/
public SSZoneTableDlg getZoneDialog() {
return zoneDialog;
}
}

View file

@ -19,9 +19,8 @@
**/
package com.raytheon.uf.viz.monitor.safeseas.resources;
import java.awt.Point;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.widgets.Display;
import org.opengis.referencing.FactoryException;
@ -29,17 +28,16 @@ import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.dataplugin.fog.FogRecord;
import com.raytheon.uf.common.dataplugin.fog.FogRecord.FOG_THREAT;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogCell;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogDataCorrector;
import com.raytheon.uf.common.dataplugin.fog.analysis.FogMonitorUtils;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.geospatial.ReferencedObject.Type;
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.monitor.fog.FogCommonThreat;
import com.raytheon.uf.viz.monitor.fog.xml.FogMonitorAlgorithmXML;
import com.raytheon.uf.viz.monitor.safeseas.SafeSeasMonitor;
import com.vividsolutions.jts.algorithm.locate.SimplePointInAreaLocator;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
/**
* FogThreat for SafeSeas monitor
@ -49,47 +47,22 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 30, 2011 #4981 skorolev Initial creation
* ------------ ---------- ----------- -----------------
* Apr 30, 2011 #4981 skorolev Initial creation
* Oct.30, 2012 #1297 skorolev Changed HashMap to Map
*
* </pre>
*
* @author skorolev
* @version 1.0
*/
public class SSFogThreat {
public class SSFogThreat extends FogCommonThreat {
/** list of coordinates for each zone **/
public HashMap<String, ArrayList<Coordinate>> zoneCoordinates = null;
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(SSFogThreat.class);
private final GeometryFactory geoFactory = new GeometryFactory();
private FogRecord fog = null;
private FogMonitorAlgorithmXML fogAlgXML = null;
private Geometry geoAdjAreas = null;
public FOG_THREAT[] threats = null;
public ArrayList<FogCell> cells = null;
public float[] ir_diff_thresholds = null;
public float[] vis_thresholds = null;
public int twilight_angle_offset = 0;
// boolean filter switches
public boolean isSnowIce = true;
public boolean isFractalDimension = true;
public boolean isSmoothness = true;
public boolean isAdjacency = true;
private SafeSeasMonitor monitor;
/** SafeSeasMonitor monitor **/
private SafeSeasMonitor ssmonitor = SafeSeasMonitor.getInstance();
/**
* serialization constructor
@ -104,696 +77,27 @@ public class SSFogThreat {
public SSFogThreat(FogMonitorAlgorithmXML fogAlgXML) {
this.fogAlgXML = fogAlgXML;
setThresholdArrays();
}
/**
* This method will be called with the switches from the GUI front end
*
* Fog Product [T(10.7) - (T(3.9)] or VIS (normalized count) Maximum cloud temperature Daytime
* Ice/Snow vs Fog Threshold (c) (FogSnowIceFilter) Cool Fog vs Warm Surface threshold Daytime
* Smoothness Algorithm (FogSmoothnessFilter) Adjacency Threshold Twilight Angle Threshold
* Fractal Dimension Threshold (FogFractalFilter)
*/
public FogRecord getFogThreat(FogRecord fog) {
this.fog = fog;
if (fog.getVisArray() == null)
return fog;
System.out.println("FogThreat for SS: Start analyzing Fog Threat...");
long start = System.currentTimeMillis();
// String cwa = fog.getCwa();
geoAdjAreas = getSafeSeasMonitor().getGeoAdjAreas();
// clear threats array, make gray (SK)i=>x j=>y
for (int i = 0; i < fog.getNx(); i++) {
for (int j = 0; j < fog.getNy(); j++) {
//(SK) getThreats()[fog.getNy() * i + j] = FOG_THREAT.GRAY;
getThreats()[fog.getNx() * j + i] = FOG_THREAT.GRAY;
}
}
// First execute the data corrector, this divides up the FogRecord field
// into Day, Night, and Twilight.
FogDataCorrector fdc = new FogDataCorrector(getFog(), fogAlgXML.getTwilightAngle());
fog = fdc.execute();
// Second, core processor. Gets you the cells, sets non-filtered values.
executeCoreProcessor();
// Third, apply filters
for (FogCell cell : getCells()) {
// *********** APPLY FILTERS *******************
// Area Size filter
if (fogAlgXML.isAdjacencyThreshOn() && cell.getCellThreat() != FOG_THREAT.GREEN
&& cell.getCellThreat() != FOG_THREAT.GRAY) {
if (cell.getArea() < fogAlgXML.getAdjacencyThresh()) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
}
}
// Snow & Ice filter
if (fogAlgXML.isIceSnowVsFogOn()
&& cell.getImageGroup() == FogRecord.IMAGE_GROUP.VIS_GROUP
&& (cell.getCellThreat() != FOG_THREAT.GREEN || cell.getCellThreat() != FOG_THREAT.GRAY)) {
float tempMean = calAverageTemp(cell);
if (tempMean < fogAlgXML.getIceSnowVsFog()) {
downgradeThreat(cell);
}
}
// Smoothness filter
if (fogAlgXML.isDaytimeSmoothThreshOn() && cell.getCellThreat() != FOG_THREAT.GREEN
|| cell.getCellThreat() != FOG_THREAT.GRAY) {
float tem_smoothness = calSmoothness(cell);
if (tem_smoothness < fogAlgXML.getDaytimeSmoothThresh()) {
downgradeThreat(cell);
}
}
// Fractal filter
if (fogAlgXML.isFractalDimensionOn() && cell.getCellThreat() != FOG_THREAT.GREEN
&& cell.getCellThreat() != FOG_THREAT.GRAY) {
float temFD = calRegularity(cell);
if (temFD > fogAlgXML.getFractalDimension() && temFD > 0.0f) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
}
}
// We extract the zone threat differently than the GI filter
// Hence it is not needed.
}
setThreats();
setMonitorAreaThreats();
System.out
.println("FogThreat for SS: Analyzed Fog Threat...Duration: "
+ (System.currentTimeMillis() - start));
return fog;
}
/**
* Remember J is X and I is Y, totally against convention!
* Gets the threat level
* @param i (SK y)
* @param j (SK x)
* @param group
* @return
*/
private FOG_THREAT getThreatLevel(int i, int j, FogRecord.IMAGE_GROUP group) {
//(SK) i=>x, j=>y
// default return
FOG_THREAT returnValue = FOG_THREAT.GRAY;
//(SK) idx = fog.getNy() * i + j
int idx = fog.getNx() * j + i;
switch (group) {
case VIS_GROUP:
float ir4_temp = bTemp(i, j, FogRecord.CHANNEL.IR10_7);
int CLOUD_FREE_BRIGHTNESS = 68; // empirical value
// Too cold
if (ir4_temp < fogAlgXML.getMaxCloudTemp()) {
returnValue = FOG_THREAT.GRAY;
}
// overlapping high/middle cloud
else if (fog.getVisArray()[idx] <= vis_thresholds[2]
&& fog.getVisArray()[idx] >= vis_thresholds[1]) {
returnValue = FOG_THREAT.RED;
} else if (fog.getVisArray()[idx] < vis_thresholds[1]
&& fog.getVisArray()[idx] >= vis_thresholds[0]
|| fog.getVisArray()[idx] <= vis_thresholds[3]
&& fog.getVisArray()[idx] > vis_thresholds[2]) {
returnValue = FOG_THREAT.YELLOW;
}
// This is essentially the Cool Fog vs. Warm surface threshold check
else if (fogAlgXML.isCoolFogVsWarmSurfaceOn()
&& ir4_temp >= fogAlgXML.getCoolFogVsWarmSurface()) {
returnValue = FOG_THREAT.GREEN;
}
else if (fog.getVisArray()[idx] < CLOUD_FREE_BRIGHTNESS) {
returnValue = FOG_THREAT.GREEN;
}
return returnValue;
case IR_GROUP:
// for some odd reason j is x and i is y,
// not sure why AWIPS 1 does it this way.
// It is completely against convention.
//Point tempoint = new Point(j, i);
//(SK) here i=>x and j=>y
Point tempoint = new Point(i, j);
float tempIR10_7 = temp_at_vis_pixel(tempoint, FogRecord.CHANNEL.IR10_7);
if (tempIR10_7 < fogAlgXML.getMaxCloudTemp()) {
// Too cold
returnValue = FOG_THREAT.GRAY;
}
// Overlapping high/middle cloud
float tempIR3_9 = temp_at_vis_pixel(tempoint, FogRecord.CHANNEL.IR3_9);
float tempDiff = tempIR10_7 - tempIR3_9;
if (tempDiff <= ir_diff_thresholds[2] && tempDiff >= ir_diff_thresholds[1]) {
returnValue = FOG_THREAT.RED;
} else if (tempDiff < ir_diff_thresholds[1] && tempDiff >= ir_diff_thresholds[0]
|| tempDiff <= ir_diff_thresholds[3] && tempDiff > ir_diff_thresholds[2]) {
returnValue = FOG_THREAT.YELLOW;
} else {
returnValue = FOG_THREAT.GREEN;
}
case TWILIGHT_GROUP:
// do nothing, stays gray
}
return returnValue;
}
/**
* Precursor call to get temp at pixel
*
* @param i
* @param j
* @param imgtype
* @return
*/
private float bTemp(int i, int j, FogRecord.CHANNEL imgtype) {
//(SK) here i=>x and j=>y
// for some odd reason j is x and i is y,
// not sure why AWIPS 1 does it this way.
// It is completely against convention.
Point tempoint = new Point(i, j);
return temp_at_vis_pixel(tempoint, imgtype);
}
/**
* Get the temp at the pixel
*
* @param pointVis
* @param channel
* @return
*/
private float temp_at_vis_pixel(Point pointVis, FogRecord.CHANNEL channel) {
// The assumption is that Dimensions of IR4 and IR2 are the same.
// IR4 data will be always needed, so attributes for IR4 shall be
// always available.
// **** ATTENTION ***** We have made the vis the same as well for AWIPS
// II
int count_value = 255;
if (channel == FogRecord.CHANNEL.IR3_9) {
count_value = fog.getIR_3_9Array()[fog.getNx() * pointVis.y + pointVis.x];
//(SK) count_value = fog.getIR_3_9Array()[fog.getNy() * pointVis.x + pointVis.y];
} else if (channel == FogRecord.CHANNEL.IR10_7) {
count_value = fog.getIR_10_7Array()[fog.getNx() * pointVis.y + pointVis.x];
//(SK) count_value = fog.getIR_10_7Array()[fog.getNy() * pointVis.x + pointVis.y];
}
return FogMonitorUtils.count2temp(count_value, channel);
}
/**
* Gets the fog
*
* @return
*/
public FogRecord getFog() {
return fog;
}
/**
* Gets the existing array of threats
*
* @return
*/
public FOG_THREAT[] getThreats() {
if (threats == null) {
threats = new FOG_THREAT[getFog().getNx() * getFog().getNy()];
}
return threats;
}
/**
* Gets the cells of this analysis
*
* @return
*/
public ArrayList<FogCell> getCells() {
return cells;
}
/**
* Gets the existing threat value at that point
*
* @return
*/
public FOG_THREAT getThreat(int i, int j) {
return getThreats()[fog.getNx() * j + i];
//(SK) return getThreats()[fog.getNy() * i + j];
}
/**
* Set fog threat at threat level point
*
* @param i
* @param j
* @param threat
*/
private void setThreat(int i, int j, FOG_THREAT threat) {
//(SK) getThreats()[fog.getNy() * i + j] = threat;
getThreats()[fog.getNx() * j + i] = threat;
}
/**
* Downgrade the Fog Threat
*
* @param current
* @param i
* @param j
*/
private void downgradeThreat(FogCell cell) {
if (cell.getCellThreat() == FOG_THREAT.YELLOW) {
setCellThreats(cell.getPoints(), FOG_THREAT.GREEN);
} else if (cell.getCellThreat() == FOG_THREAT.RED) {
setCellThreats(cell.getPoints(), FOG_THREAT.YELLOW);
}
}
// // *********************** FILTERS **************************** /////
// -Private--------------------------------------------------------------------
// NAME: CalRegularity()
//
// TYPE: Private Member function
//
// Descript:
// Given a cell, calculate its regularity i.e. the fractal dimension
// Input Arguments:
// cell: The Fog_Cell whose fractal dimension is to be measured
// Output Arguments:
// Return float: fractal dimension. the value is between 1 to 2
// smaller means more regular.
// Here use the perimeter and area relation to represent
// fractal dimension (one of the simply ways)
// History:
// May 2004 Qin Zeng (GDMB/MDL) -- created
// Dec 2009 D Hladky translated to Java
// -----------------------------------------------------------------------------
private float calRegularity(FogCell cell) {
int nx = cell.right - cell.left + 1;
int ny = cell.bottom - cell.top + 1;
int i;
boolean[] flag = new boolean[nx * ny];
for (i = 0; i < nx * ny; i++) {
flag[i] = false;
}
int pixels_num = (int) cell.getArea();
int flagPos;
for (i = 0; i < pixels_num; i++) {
Coordinate coor = cell.getPixelCoordinate(i);
flagPos = (int) ((coor.y - cell.top) * nx + coor.x - cell.left);
if (flagPos >= 0 && flagPos < nx * ny) {
flag[flagPos] = true;
}
}
// From here, perimeter of the fog cell will be calculated;
// |...| 1 |...|
// | 4 | 0 | 2 |
// |...| 3 |...|
//
// If the any of the 0's surrounding pixels(1,2,3,4) is flagged as false,
// which means that surrounding pixel(1,2,3,or 4) is not included in
// the cell, pixel 0 then will be at the edge of the cell cluster.
// And the edge connecting to the outside pixel will be counted into the
// perimeter of the cell cluster.
int pos1, pos2, pos3, pos4;
float perimeter = 0;
for (i = 0; i < pixels_num; i++) {
Coordinate coor = cell.getPixelCoordinate(i);
pos1 = (int) ((i - cell.top - 1) * nx + coor.y - cell.left);
if (pos1 >= 0 && pos1 < nx * ny && !flag[pos1] || i - coor.x < cell.top) {
perimeter++;
}
pos2 = (int) ((coor.y - cell.top) * nx + coor.x + 1 - cell.left);
if (pos2 >= 0 && pos2 < nx * ny && !flag[pos2] || coor.x + 1 > cell.right) {
perimeter++;
}
pos3 = (int) ((coor.y - cell.top + 1) * nx + coor.x - cell.left);
if (pos3 >= 0 && pos3 < nx * ny && !flag[pos3] || coor.y + 1 > cell.bottom) {
perimeter++;
}
pos4 = (int) ((coor.y - cell.top) * nx + coor.x - 1 - cell.left);
if (pos4 >= 0 && pos4 < nx * ny && !flag[pos4] || coor.x - 1 < cell.left) {
perimeter++;
}
}
float fractalDimension = 1.0f;
if (cell.getArea() != 1) {
fractalDimension = (float) (2 * Math.log(perimeter / 4.0) / Math.log(cell.getArea()));
}
// Note : fractalDimension is a data between 1 and 2 and the larger
// fractalDimension is , the more irregular the shape of the cell will
// be.
return fractalDimension;
}
// -Private--------------------------------------------------------------------
// NAME: CalSmoothness()
//
// TYPE: Private Member function
//
// Descript:
// Given a cell, calculate the its smoothness
// Input Arguments:
// cell: The Fog_Cell whose smoothness is to be measured
// Output Arguments:
// return float: smoothness defined above
// History:
// May 2004 Qin Zeng (GDMB/MDL) -- created
// Dec 2009 D Hladky ported to AWIPS II
// -----------------------------------------------------------------------------
private float calSmoothness(FogCell cell) {
float mean = 0; // mean grayscale value of pixels in the cell from VIS.
float stdDev = 0; // standard deviation
int pixels_num = (int) cell.getArea();
if (pixels_num == 0) {
return 0;
}
int i;
for (i = 0; i < pixels_num; i++) {
Coordinate pixr = cell.getPixelRelativeCoordinate(i);
//(SK) mean += getFog().getVisArray()[(int) (getFog().getNy() * pixr.x + pixr.y)];
mean += getFog().getVisArray()[(int) (getFog().getNx() * pixr.y + pixr.x)];
}
mean /= pixels_num;
float tem_float;
for (i = 0; i < pixels_num; i++) {
Coordinate pixr = cell.getPixelRelativeCoordinate(i);
//(SK) tem_float = getFog().getVisArray()[(int) (getFog().getNy() * pixr.x + pixr.y)];
tem_float = getFog().getVisArray()[(int) (getFog().getNx() * pixr.y + pixr.x)];
stdDev += (tem_float - mean) * (tem_float - mean);
}
stdDev /= pixels_num;
stdDev = (float) Math.sqrt(stdDev);
// mean should not be zero, so no need to check mean here.
return (1 - stdDev / mean) * 100; // use percent as unit
}
// -Private---------------------------------------------------------------------
// NAME: Cal()
//
// TYPE: Private Member function
//
// Descript:
// Calculate the average temperature for a Fog_Cell in channel 3.9 um
// History:
// May 2004 Qin Zeng (GDMB/MDL) -- created
// -----------------------------------------------------------------------------
private float calAverageTemp(FogCell cell) {
float mean = 0; // mean temperature value of pixels in the cell.
int pixels_num = (int) cell.getArea();
if (pixels_num == 0) {
return -999.9f;
}
for (int i = 0; i < pixels_num; i++) {
Coordinate pixc = cell.getPixelRelativeCoordinate(i);
mean += temp_at_vis_pixel(new Point((int) pixc.x, (int) pixc.y),
FogRecord.CHANNEL.IR3_9);
}
mean /= pixels_num;
return mean;
}
// -Public---------------------------------------------------------------------
// NAME: Execute()
//
// TYPE: Private Member function
//
// Descript:
// Based on the thresholds of the VIS image data and the IR image data,
// a number of patches of the contiguous suspected fog areas will be
// extracted from the satellite image data.
// This is an implementation of the feature extraction algorithm based
// on the contiguous gray scale values.
//
// Arguments: None
// History:
// March 2004 Qin Zeng (GDMB/MDL) -- created
// Dec 2009 D Hladky ported to Java for AWIPS II
// -----------------------------------------------------------------------------
private void executeCoreProcessor() {
cells = new ArrayList<FogCell>();
ArrayList<Point> parent = new ArrayList<Point>();
ArrayList<Point> child = new ArrayList<Point>();
ArrayList<Point> single_segment = new ArrayList<Point>();
int x_dim = getFog().getNx();
int y_dim = getFog().getNy();
int i; //(SK) x
int j; //(SK) y
// To flag whether a pixel has been visited or not
boolean[][] visited = new boolean[x_dim][y_dim];
Point[] s = new Point[8]; // 8 surrounding points of one specific point
for (int z = 0; z < s.length; z++) {
s[z] = new Point();
}
Point tempoint = new Point();
getCells().clear();
for (i = 0; i < x_dim; i++) {
for (j = 0; j < y_dim; j++) {
visited[i][j] = false;
}
}
for (j = 0; j < y_dim; j++) {
Point firstone = new Point();
FOG_THREAT threat_level = FOG_THREAT.BLACK;
FogRecord.IMAGE_GROUP imggroup;
for (i = 0; i < x_dim; i++) {
if (visited[i][j]) {
continue;
}
Coordinate cellCoor = this.getCellCoor(i, j);
visited[i][j] = true;
imggroup = getFog().findGroup(i, j);
threat_level = getThreatLevel(i, j, imggroup);
// Sets the initial threat level
setThreat(i, j, threat_level);
firstone.x = i;
firstone.y = j;
parent.clear();
tempoint.y = j;
tempoint.x = i;
single_segment.add(tempoint);
parent.add(tempoint);
while (parent.size() != 0) {
// the variables(s[1],s[2]...) below mean surrounding 1,2
// | 0 | 1 | 2 |
// | 7 | i | 3 |
// | 6 | 5 | 4 |
// iteratively search the 8-connected surrounding pixels
child.clear();
for (int k = 0; k < parent.size(); k++) {
// y's too small, too big
if (parent.get(k).y == 0) {
s[0].y = parent.get(k).y;
s[1].y = parent.get(k).y;
s[2].y = parent.get(k).y;
}
if (parent.get(k).y == y_dim - 1) {
s[4].y = parent.get(k).y;
s[5].y = parent.get(k).y;
s[6].y = parent.get(k).y;
}
// x's too small, too big
if (parent.get(k).x == 0) {
s[0].x = parent.get(k).x;
s[6].x = parent.get(k).x;
s[7].x = parent.get(k).x;
}
if (parent.get(k).x == x_dim - 1) {
s[2].x = parent.get(k).x;
s[3].x = parent.get(k).x;
s[4].x = parent.get(k).x;
}
// all others
if (parent.get(k).x > 0 && parent.get(k).x < x_dim - 1
&& parent.get(k).y == y_dim - 1 && parent.get(k).y > 0) {
s[0].y = parent.get(k).y - 1;
s[0].x = parent.get(k).x - 1;
s[1].y = parent.get(k).y - 1;
s[1].x = parent.get(k).x;
s[2].y = parent.get(k).y - 1;
s[2].x = parent.get(k).x + 1;
s[3].y = parent.get(k).y;
s[3].x = parent.get(k).x + 1;
s[4].y = parent.get(k).y + 1;
s[4].x = parent.get(k).x + 1;
s[5].y = parent.get(k).y + 1;
s[5].x = parent.get(k).x;
s[6].y = parent.get(k).y + 1;
s[6].x = parent.get(k).x - 1;
s[7].y = parent.get(k).y;
s[7].x = parent.get(k).x - 1;
}
FogRecord.IMAGE_GROUP temgroup;
FOG_THREAT temthreat;
for (int m = 0; m < 8; m++) {
if (s[m].y >= 0 && s[m].y < y_dim && s[m].x >= 0 && s[m].x < x_dim) {
int ii = s[m].x;
int jj = s[m].y;
//(SK) int ii = s[m].y;
//(SK) int jj = s[m].x;
if (!visited[ii][jj]) {
temgroup = getFog().findGroup(ii, jj);
temthreat = getThreatLevel(ii, jj, temgroup);
if (temgroup == imggroup && temthreat == threat_level) {
child.add(s[m]);
visited[ii][jj] = true;
single_segment.add(s[m]);
}
}// end of if
}// end of if
}// end of for m
}// end of for k
parent = child;
}// end of while
// if
// (!this.geoAdjAreas.contains(geoFactory.createPoint(cellCoor)))
// {
int lct = SimplePointInAreaLocator.locate(cellCoor,
this.geoAdjAreas);
if (lct == 2) {
threat_level = FOG_THREAT.BLACK;
setThreat(i, j, threat_level);
}
getCells().add(new FogCell(single_segment, threat_level, imggroup));
single_segment.clear();
} // end of for j
} // end of for i
}
/**
* Sets all points in the cell to the cell filtered value threat
*
* @param cells
* @param threat
*/
private void setCellThreats(ArrayList<Point> points, FOG_THREAT threat) {
for (Point point : points) {
getThreats()[fog.getNx() * point.y + point.x] = threat;
//(SK) getThreats()[fog.getNy() * point.x + point.y] = threat;
}
}
/**
* Gets the drawable float array of threats
*
* @return
*/
private void setThreats() {
float[] floats = new float[getThreats().length];
int i = 0;
for (FOG_THREAT threat : getThreats()) {
floats[i] = getThreatValue(threat);
i++;
}
getFog().setThreats(floats);
}
/**
* Sets the thresholds
*/
private void setThresholdArrays() {
ir_diff_thresholds = new float[4];
vis_thresholds = new float[4];
ir_diff_thresholds[0] = (float) fogAlgXML.getFogProductYLo();
ir_diff_thresholds[1] = (float) fogAlgXML.getFogProductYHi();
ir_diff_thresholds[2] = (float) fogAlgXML.getFogProductRLo();
ir_diff_thresholds[3] = (float) fogAlgXML.getFogProductRHi();
vis_thresholds[0] = (float) fogAlgXML.getVisYLo();
vis_thresholds[1] = (float) fogAlgXML.getVisYHi();
vis_thresholds[2] = (float) fogAlgXML.getVisRLo();
vis_thresholds[3] = (float) fogAlgXML.getVisRHi();
}
/**
* Quick static method to get the float to threat mapping
*
* @param threat
* @return
*/
public static float getThreatValue(FOG_THREAT threat) {
float value = 0;
if (threat == FOG_THREAT.BLACK) {
value = 0.0f;
} else if (threat == FOG_THREAT.GRAY) {
value = 15.0f;
} else if (threat == FOG_THREAT.GREEN) {
value = 60.0f;
} else if (threat == FOG_THREAT.YELLOW) {
value = 110.0f;
} else if (threat == FOG_THREAT.RED) {
value = 220.0f;
}
return value;
zoneGeos = ssmonitor.getMonitoringAreaGeometries();
geoAdjAreas = ssmonitor.getGeoAdjAreas();
}
/**
* Gets the zone threats (ALG) with worst case for zone area
*
* @return HashMap<String, FOG_THREAT>
* @return Map<String, FOG_THREAT> zoneThreats
*/
public void setMonitorAreaThreats() {
final FogRecord ffogRec = getFog();
final SafeSeasMonitor fmonitor = getSafeSeasMonitor();
// TODO: async or sync ????
Display.getDefault().asyncExec(new Runnable() {
public void run() {
public void run() {
long start = System.currentTimeMillis();
HashMap<String, Geometry> zoneGeos = fmonitor.getMonitoringAreaGeometries();
Map<String, Geometry> zoneGeos = ssmonitor
.getMonitoringAreaGeometries();
// set to lowest for default
HashMap<String, FOG_THREAT> zoneThreats = new HashMap<String, FOG_THREAT>();
Map<String, FOG_THREAT> zoneThreats = new HashMap<String, FOG_THREAT>();
for (String zone : zoneGeos.keySet()) {
zoneThreats.put(zone, FOG_THREAT.BLACK);
}
@ -801,75 +105,47 @@ public class SSFogThreat {
for (int i = 0; i < ffogRec.getNx(); i++) {
for (int j = 0; j < ffogRec.getNy(); j++) {
ReferencedCoordinate rc = new ReferencedCoordinate(new Coordinate(i, j),
ReferencedCoordinate rc = new ReferencedCoordinate(
new Coordinate(i, j),
ffogRec.getGridGeometry(), Type.GRID_CENTER);
Coordinate coor = null;
try {
coor = rc.asLatLon();
} catch (TransformException e) {
e.printStackTrace();
statusHandler.handle(Priority.ERROR, e.getMessage());
} catch (FactoryException e) {
e.printStackTrace();
statusHandler.handle(Priority.ERROR, e.getMessage());
}
for (String zone : zoneGeos.keySet()) {
if (zoneGeos.get(zone) != null) {
if (zoneGeos.get(zone).contains(
geoFactory.createPoint(coor))) {
try {
if (getThreatValue(getThreat(i, j)) > getThreatValue(zoneThreats
.get(zone))) {
zoneThreats.put(zone,
getThreat(i, j));
}
} catch (Exception e) {
e.printStackTrace();
for (String zone : zoneGeos.keySet()) {
if (zoneGeos.get(zone) != null) {
if (zoneGeos.get(zone).contains(
geoFactory.createPoint(coor))) {
try {
if (getThreatValue(getThreat(i, j)) > getThreatValue(zoneThreats
.get(zone))) {
zoneThreats.put(zone,
getThreat(i, j));
}
} catch (Exception e) {
statusHandler.handle(Priority.ERROR,
e.getMessage());
}
}
}
}
}
}
}
} // end zone loop
} // end j loop
} // end i loop
fmonitor.setAlgorithmData(ffogRec.getRefHour().getTime(),
ssmonitor.setAlgorithmData(ffogRec.getRefHour().getTime(),
zoneThreats);
System.out
.println("FogThreat for SS: Set algorithm zone values..."
+ (System.currentTimeMillis() - start));
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.handle(Priority.DEBUG,
"FogThreat for SS: Set algorithm zone values..."
+ (System.currentTimeMillis() - start));
}
}
});
}
private Coordinate getCellCoor(int i, int j) {
ReferencedCoordinate rc = new ReferencedCoordinate(new Coordinate(i, j), this.getFog()
.getGridGeometry(), Type.GRID_CENTER);
Coordinate crd = null;
try {
crd = rc.asLatLon();
} catch (TransformException e) {
e.printStackTrace();
} catch (FactoryException e) {
e.printStackTrace();
}
return crd;
}
public Geometry getGeoAdjAreas() {
return geoAdjAreas;
}
public void setGeoAdjAreas(Geometry geoAdjAreas) {
this.geoAdjAreas = geoAdjAreas;
}
/**
* @return SafeSeasMonitor
*/
private SafeSeasMonitor getSafeSeasMonitor() {
if (monitor == null) {
monitor = SafeSeasMonitor.getInstance();
}
return monitor;
}
}

View file

@ -39,6 +39,7 @@ import com.raytheon.uf.viz.monitor.safeseas.SafeSeasMonitor;
* Nov 30, 2009 3424 zhao/Slav/wkwock launch safeseas from SafeseasMonitor.getInstance()
* Dec 30, 2009 3424 zhao Launch SS monitor and SS zone/station table dialog separately here
* Feb 26, 2010 4282 zhao Changed to follow the same dialog launch mechanism as in FOG
* Nov 15, 2012 1297 skorolev Cleaned code
*
* </pre>
*
@ -50,13 +51,15 @@ public class SafeSeasAction extends AbstractHandler {
@Override
public Object execute(ExecutionEvent arg0) throws ExecutionException {
System.out.println("Activating/Action for Safeseas...");
SafeSeasMonitor monitor = SafeSeasMonitor.getInstance();
if ( monitor.zoneDialog == null || monitor.zoneDialog.isDisposed()) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
monitor.launchDialog("zone", shell);
}
System.out.println("Activating/Action for Safeseas...");
SafeSeasMonitor monitor = SafeSeasMonitor.getInstance();
if (monitor.getZoneDialog() == null
|| monitor.getZoneDialog().isDisposed()) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell();
monitor.launchDialog("zone", shell);
}
return null;
}

View file

@ -68,11 +68,10 @@ public class SSMonitoringAreaConfigDlg extends MonitoringAreaConfigDlg {
configManager.setTimeWindow(timeScale.getSelection());
configManager.setUseAlgorithms(fogChk.getSelection());
configManager.saveConfigData();
/**
* DR#11279:
* re-initialize threshold manager and the monitor
* using new monitor area configuration
* DR#11279: re-initialize threshold manager and the monitor using
* new monitor area configuration
*/
SSThresholdMgr.reInitialize();
SafeSeasMonitor.reInitialize();
@ -81,7 +80,8 @@ public class SSMonitoringAreaConfigDlg extends MonitoringAreaConfigDlg {
"You're updating the SAFESEAS monitoring settings."
+ "\n\nIf SAFESEAS is running anywhere within "
+ "the office, please clear it.\n");
if ( configManager.getAddedZones().size() > 0 || addedZones.size() > 0 ) {
if (configManager.getAddedZones().size() > 0
|| addedZones.size() > 0) {
String message2 = "New zones have been added, and their monitoring thresholds "
+ "have been set to default values; would you like to modify "
+ "their threshold values now?";

View file

@ -21,8 +21,10 @@ package com.raytheon.uf.viz.monitor.safeseas.ui.dialogs;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.common.dataplugin.fog.FogRecord.FOG_THREAT;
@ -30,6 +32,7 @@ import com.raytheon.uf.common.monitor.config.MonitorConfigurationManager;
import com.raytheon.uf.common.monitor.config.SSMonitorConfigurationManager;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.ObConst.DataUsageKey;
import com.raytheon.uf.common.monitor.data.ObConst.DisplayVarName;
import com.raytheon.uf.viz.monitor.IMonitor;
import com.raytheon.uf.viz.monitor.data.ObMultiHrsReports;
import com.raytheon.uf.viz.monitor.events.IMonitorConfigurationEvent;
@ -38,16 +41,34 @@ import com.raytheon.uf.viz.monitor.events.IMonitorThresholdEvent;
import com.raytheon.uf.viz.monitor.listeners.IMonitorListener;
import com.raytheon.uf.viz.monitor.safeseas.SafeSeasMonitor;
import com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg;
import com.raytheon.uf.viz.monitor.util.MonitorConfigConstants;
/**
* ( where is the "SOFTWARE HISTORY" section of this file? )
* SAFESEAS Zone Table Dialog
*
* Dec 30, 2009 3424 zhao use ObMultiHrsReports for obs data archive
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec 30, 2009 3424 zhao use ObMultiHrsReports for obs data archive
* Oct 30, 2012 1297 skorolev Changed HashMap to Map
* Nov 10, 2012 1297 skorolev Added initiateProdArray
*
* </pre>
*
* @author zhao
* @version 1.0
*/
public class SSZoneTableDlg extends ZoneTableDlg {
/** SAFESEAS threshold dialog. **/
private SSDispMonThreshDlg ssThreshDlg;
/** Swell column names in the zone and station table. **/
private String[] ssSwellCols = { "SSZT_SwellPeriod", "SSZT_Swell2Period" };
/**
* Constructor (Dec 30, 2009, zhao)
*
@ -57,10 +78,50 @@ public class SSZoneTableDlg extends ZoneTableDlg {
super(parent, obData, CommonConfig.AppName.SAFESEAS);
}
/**
* Constructor
*
* @param parent
*/
public SSZoneTableDlg(Shell parent) {
super(parent, CommonConfig.AppName.SAFESEAS);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#initiateProdArray()
*/
@Override
public void initiateProdArray() {
varName = config.getSafeseasZoneStnTableColVarNames()[colIndex];
// Fill product arrays
prodArray = new ArrayList<String>();
String[] varprefs = { "VAR_", "SCA_", "GALE_", "STORM_", "HURRICANE_" };
for (DisplayVarName var : DisplayVarName.values()) {
String dispVarName = var.name();
if (colIndex == 1 && dispVarName.startsWith(varprefs[1])) {
prodArray.add(dispVarName);
} else if (colIndex == 2 && dispVarName.startsWith(varprefs[2])) {
prodArray.add(dispVarName);
} else if (colIndex == 3 && dispVarName.startsWith(varprefs[3])) {
prodArray.add(dispVarName);
} else if (colIndex == 4 && dispVarName.startsWith(varprefs[4])) {
prodArray.add(dispVarName);
} else if (dispVarName.startsWith(varprefs[0])
&& dispVarName.equals(varprefs[0] + varName.name())) {
prodArray.add(dispVarName);
}
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#configThreshAction()
*/
@Override
protected void configThreshAction() {
if (ssThreshDlg == null) {
@ -71,70 +132,123 @@ public class SSZoneTableDlg extends ZoneTableDlg {
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.listeners.IMonitorListener#notify(com.raytheon
* .uf.viz.monitor.events.IMonitorEvent)
*/
@Override
public void notify(IMonitorEvent me) {
if (zoneTable.isDisposed()) {
return;
}
if (me.getSource() instanceof SafeSeasMonitor) {
SafeSeasMonitor monitor = (SafeSeasMonitor) me.getSource();
Date date = monitor.getDialogTime();
if (date != null) {
if (me.getSource() instanceof SafeSeasMonitor) {
SafeSeasMonitor monitor = (SafeSeasMonitor) me.getSource();
Date date = monitor.getDialogTime();
if (date != null) {
Date nominalTime = date;
ObMultiHrsReports obData = monitor.getObData();
if (!isLinkedToFrame()) {
nominalTime = obData.getLatestNominalTime();
}
HashMap<String, FOG_THREAT> fogAlgThreats = monitor
ObMultiHrsReports obData = monitor.getObData();
if (!isLinkedToFrame()) {
nominalTime = obData.getLatestNominalTime();
}
Map<String, FOG_THREAT> fogAlgThreats = monitor
.getAlgorithmData(nominalTime);
obData.setFogAlgCellType(monitor.getAlgCellTypes(fogAlgThreats));
this.updateTableDlg(monitor.getObData().getObHourReports(nominalTime));
}
}
obData.setFogAlgCellType(monitor.getAlgCellTypes(fogAlgThreats));
this.updateTableDlg(monitor.getObData().getObHourReports(
nominalTime));
}
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* addMonitorControlListener(com.raytheon.uf.viz.monitor.IMonitor)
*/
@Override
public void addMonitorControlListener(IMonitor monitor) {
getMonitorControlListeners().add(monitor);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireConfigUpdate
* (com.raytheon.uf.viz.monitor.events.IMonitorConfigurationEvent)
*/
@Override
public void fireConfigUpdate(IMonitorConfigurationEvent imce) {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#fireKillMonitor
* ()
*/
@Override
public void fireKillMonitor() {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireThresholdUpdate
* (com.raytheon.uf.viz.monitor.events.IMonitorThresholdEvent)
*/
@Override
public void fireThresholdUpdate(IMonitorThresholdEvent imte) {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#
* getMonitorControlListeners()
*/
@Override
public ArrayList<IMonitor> getMonitorControlListeners() {
public List<IMonitor> getMonitorControlListeners() {
return controlListeners;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* removeMonitorContorlListener(com.raytheon.uf.viz.monitor.IMonitor)
*/
@Override
public void removeMonitorContorlListener(IMonitor monitor) {
getMonitorControlListeners().remove(monitor);
}
@Override
protected MonitorConfigurationManager getConfigMgr() {
return SSMonitorConfigurationManager.getInstance();
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#getConfigMgr()
*/
@Override
protected MonitorConfigurationManager getConfigMgr() {
return SSMonitorConfigurationManager.getInstance();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#handleLinkToFrame()
*/
@Override
protected void handleLinkToFrame() {
linkedToFrame = linkToFrameChk.getSelection();
@ -150,8 +264,7 @@ public class SSZoneTableDlg extends ZoneTableDlg {
*/
@Override
protected void shellDisposeAction() {
// TODO Auto-generated method stub
// Not used
}
/*
@ -163,7 +276,42 @@ public class SSZoneTableDlg extends ZoneTableDlg {
*/
@Override
public void fireDialogShutdown(IMonitorListener iml) {
// TODO Auto-generated method stub
// Not used
}
@Override
protected void setZoneSortColumnAndDirection() {
if (zoneTblData != null) {
zoneSortColumn = zoneTblData.getSortColumn();
zoneSortDirection = zoneTblData.getSortDirection();
if (zoneSortColumn == zoneTable.getColumnIndex(appName,
ssSwellCols[0])
|| zoneSortColumn == zoneTable.getColumnIndex(appName,
ssSwellCols[1])) {
if (MonitorConfigConstants.isRankSwellPeriodHigh()) {
zoneSortDirection = SWT.DOWN;
} else {
zoneSortDirection = SWT.UP;
}
}
}
}
@Override
protected void setStnSortColumnAndDirection() {
if (stnTblData != null) {
stnSortColumn = stnTblData.getSortColumn();
stnSortDirection = stnTblData.getSortDirection();
if (stnSortColumn == stationTable.getColumnIndex(appName,
ssSwellCols[0])
|| stnSortColumn == stationTable.getColumnIndex(appName,
ssSwellCols[1])) {
if (MonitorConfigConstants.isRankSwellPeriodHigh()) {
stnSortDirection = SWT.DOWN;
} else {
stnSortDirection = SWT.UP;
}
}
}
}
}

View file

@ -23,6 +23,8 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.eclipse.swt.widgets.Shell;
@ -30,8 +32,9 @@ import org.eclipse.swt.widgets.Shell;
import com.raytheon.edex.urifilter.URIFilter;
import com.raytheon.uf.common.monitor.config.SnowMonitorConfigurationManager;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.ObConst.ChosenAppKey;
import com.raytheon.uf.common.time.DataTime;
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.alerts.AlertMessage;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.uf.viz.core.notification.NotificationMessage;
@ -67,6 +70,8 @@ import com.raytheon.viz.alerts.observers.ProductAlertObserver;
* Dec 22, 2009 3424 zhao revised processProductAtStartup method to retrieve all data
* July 20,2010 4891 skorolev Added resource listener
* May 15, 2012 14510 zhao Modified processing at startup
* Oct 26, 2012 1280 skorolev Clean code and made changes for non-blocking ZoneTableDlg
* Nov. 1, 2012 1297 skorolev Changed HashMap to Map and clean code
*
* </pre>
*
@ -77,19 +82,19 @@ import com.raytheon.viz.alerts.observers.ProductAlertObserver;
public class SnowMonitor extends ObsMonitor {
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(SnowMonitor.class);
/** Singleton instance of this class */
private static SnowMonitor monitor = null;
/**
* the zone table dialog
*/
public SnowZoneTableDlg zoneDialog = null;
/** Zone table dialog **/
private SnowZoneTableDlg zoneDialog;
/**
* the monitoring area configure dialog
*/
public SnowMonitoringAreaConfigDlg areaDialog = null;
/** Monitoring area configure dialog **/
private SnowMonitoringAreaConfigDlg areaDialog = null;
/** SNOW configuration manager **/
private SnowMonitorConfigurationManager snowConfig = null;
/**
@ -98,113 +103,138 @@ public class SnowMonitor extends ObsMonitor {
*/
private final ObMultiHrsReports obData;
/** The application key */
ChosenAppKey chosenAppKey = ChosenAppKey.SNOW;
/** All SNOW plugins start with this */
private static String OBS = "fssobs";
/** All SNOW datauri start with this */
private final String OBS = "fssobs";
/** regex wild card filter */
protected static String wildCard = "[\\w\\(\\)-_:.]+";
private final String wildCard = "[\\w\\(\\)-_:.]+";
/** date of the data sent **/
// private Date dataDate = null;
/**
* Time which Zone/County dialog shows.
*/
public Date dialogTime = null;
/** Time which Zone/County dialog shows. **/
private Date dialogTime = null;
/** Array of snow listeners **/
private final ArrayList<ISnowResourceListener> snowResources = new ArrayList<ISnowResourceListener>();
private final List<ISnowResourceListener> snowResources = new ArrayList<ISnowResourceListener>();
/** Pattern for SNOW **/
private final Pattern snowPattern = Pattern.compile(URIFilter.uriSeperator
+ OBS + URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + cwa + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ "snow");
/**
* Private constructor, singleton
*/
/**
*
*/
private SnowMonitor() {
pluginPatterns.add(snowPattern);
pluginPatterns.add(snowPattern);
readTableConfig(MonitorThresholdConfiguration.SNOW_THRESHOLD_CONFIG);
initObserver("fssobs", this);
initObserver(OBS, this);
obData = new ObMultiHrsReports(CommonConfig.AppName.SNOW);
obData.setThresholdMgr(SnowThresholdMgr.getInstance());
// Pre-populate dialog with an observation (METAR) for KOMA
}
}
/**
* Gets instance of monitor
*
* @return monitor
*/
public static synchronized SnowMonitor getInstance() {
if (monitor == null) {
monitor = new SnowMonitor();
monitor.processProductAtStartup("snow");
monitor.fireMonitorEvent(monitor);
monitor.processProductAtStartup("snow");
monitor.fireMonitorEvent(monitor);
}
return monitor;
}
// TODO: Provide the changes in EDEX URIFilters when area configuration file
// has been changed.
/**
* DR#11279:
* When monitor area configuration is changed,
* this module is called to re-initialize monitor
* using new monitor area configuration
* DR#11279: When monitor area configuration is changed, this module is
* called to re-initialize monitor using new monitor area configuration
*/
public static void reInitialize() {
if ( monitor != null ) {
monitor = null;
monitor = new SnowMonitor();
}
if (monitor != null) {
monitor = null;
monitor = new SnowMonitor();
}
}
/**
* Launches SNOW zone table dialog
*
* @param type
* @param shell
*/
public void launchDialog(String type, Shell shell) {
if (type.equals("zone")) {
if (zoneDialog == null) {
if (zoneDialog == null || zoneDialog.getShell() == null
|| zoneDialog.isDisposed()) {
zoneDialog = new SnowZoneTableDlg(shell, obData);
addMonitorListener(zoneDialog);
zoneDialog.addMonitorControlListener(this);
fireMonitorEvent(zoneDialog.getClass().getName());
zoneDialog.open();
} else {
zoneDialog.bringToTop();
}
zoneDialog.open();
fireMonitorEvent(zoneDialog.getClass().getName());
} else if (type.equals("area")) {
areaDialog = new SnowMonitoringAreaConfigDlg(shell,
"SNOW Monitor Area Configuration");
areaDialog.open();
if (areaDialog == null) {
areaDialog = new SnowMonitoringAreaConfigDlg(shell,
"SNOW Monitor Area Configuration");
areaDialog.open();
}
}
}
/**
* Gets data
*
* @return obData
*/
public ObMultiHrsReports getObData() {
return obData;
}
private Pattern snowPattern = Pattern.compile(URIFilter.uriSeperator + OBS
+ URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + cwa + URIFilter.uriSeperator
+ wildCard + URIFilter.uriSeperator + wildCard
+ URIFilter.uriSeperator + wildCard + URIFilter.uriSeperator
+ "snow");
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#filterNotifyMessage(com.raytheon
* .uf.viz.core.notification.NotificationMessage)
*/
@Override
public boolean filterNotifyMessage(NotificationMessage alertMessage) {
return false;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processNotifyMessage(com.raytheon
* .uf.viz.core.notification.NotificationMessage)
*/
@Override
public void processNotifyMessage(NotificationMessage filtered) {
// Not used
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processProductMessage(com.raytheon
* .uf.viz.core.alerts.AlertMessage)
*/
@Override
public void processProductMessage(final AlertMessage filtered) {
if (snowPattern.matcher(filtered.dataURI).matches()) {
// System.out.println("Found match: " + snowPattern + " URI: "
// + filtered.dataURI);
processURI(filtered.dataURI, filtered);
}
if (snowPattern.matcher(filtered.dataURI).matches()) {
processURI(filtered.dataURI, filtered);
}
}
/**
@ -214,7 +244,6 @@ public class SnowMonitor extends ObsMonitor {
*
*/
public class SortByDate implements Comparator<Date> {
@Override
public int compare(Date o1, Date o2) {
return o1.compareTo(o2);
@ -229,7 +258,7 @@ public class SnowMonitor extends ObsMonitor {
* -- the xml configuration filename
*/
public void readTableConfig(String file) {
HashMap<String, ArrayList<String>> zones = new HashMap<String, ArrayList<String>>();
Map<String, List<String>> zones = new HashMap<String, List<String>>();
// create zones and station list
try {
SnowMonitorConfigurationManager areaConfig = getMonitorAreaConfig();
@ -238,72 +267,103 @@ public class SnowMonitor extends ObsMonitor {
zones.put(zone, stations);
}
} catch (Exception e) {
System.out.println("Snow failed to load configuration..."
+ this.getClass().getName());
statusHandler.handle(Priority.PROBLEM,
"Snow failed to load configuration..."
+ this.getClass().getName());
}
MonitoringArea.setPlatformMap(zones);
}
/**
* Gets configuration manager
*
* @return snowConfig
*/
public SnowMonitorConfigurationManager getMonitorAreaConfig() {
if (snowConfig == null) {
LocalizationManager mgr = LocalizationManager.getInstance();
String siteScope = mgr.getCurrentSite();
snowConfig = SnowMonitorConfigurationManager.getInstance();
snowConfig.readConfigXml(siteScope);
}
return snowConfig;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.Monitor#initObserver(java.lang.String,
* com.raytheon.uf.viz.monitor.Monitor)
*/
@Override
public void initObserver(String pluginName, Monitor monitor) {
ProductAlertObserver.addObserver(pluginName, this);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#thresholdUpdate(com.raytheon.uf
* .viz.monitor.events.IMonitorThresholdEvent)
*/
@Override
public void thresholdUpdate(IMonitorThresholdEvent me) {
fireMonitorEvent(zoneDialog.getClass().getName());
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#configUpdate(com.raytheon.uf.viz
* .monitor.events.IMonitorConfigurationEvent)
*/
@Override
public void configUpdate(IMonitorConfigurationEvent me) {
fireMonitorEvent(zoneDialog.getClass().getName());
}
/**
* Kill this monitor by nullifying the monitor's private instance variable.
* Kills this monitor by nullifying the monitor's private instance variable.
*/
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ObsMonitor#nullifyMonitor()
*/
@Override
public void nullifyMonitor() {
// /**
// * Before making the monitor null, remove observers
// */
// for (String p : pluginName) {
// if (!pluginName.equals("")) {
// stopObserver(p, this);
// }
// }
monitor.removeMonitorListener(zoneDialog);
stopObserver("fssobs", this);
stopObserver(OBS, this);
monitor = null;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#process(com.raytheon.uf.viz.monitor
* .data.ObReport)
*/
@Override
protected void process(ObReport result)
throws Exception {
//final ProcessSnowReport snow = new ProcessSnowReport(result);
//snow.processSnowReport();
// add data to obData
protected void process(ObReport result) throws Exception {
obData.addReport(result);
fireMonitorEvent(this);
}
/**
* @return dialogTime
*/
public Date getDialogTime() {
return dialogTime;
}
/**
* Sets dialog time
*
* @param dialogTime
*/
public void setDialogTime(Date dialogTime) {
this.dialogTime = dialogTime;
}
@ -336,12 +396,15 @@ public class SnowMonitor extends ObsMonitor {
fireMonitorEvent(this);
}
/**
* Close SNOW zone table dialog
*/
public void closeDialog() {
if (zoneDialog != null) {
monitor.nullifyMonitor();
zoneDialog.removeMonitorContorlListener(this);
zoneDialog.shellDisposeDialog();
zoneDialog.close();
zoneDialog = null;
}
if (areaDialog != null) {
@ -350,43 +413,47 @@ public class SnowMonitor extends ObsMonitor {
}
}
/**
* Order the dates
/*
* (non-Javadoc)
*
* @param type
* @return
* @see
* com.raytheon.uf.viz.monitor.IMonitor#getTimeOrderedKeys(com.raytheon.
* uf.viz.monitor.IMonitor, java.lang.String)
*/
@Override
public ArrayList<Date> getTimeOrderedKeys(IMonitor monitor, String type) {
// not used
return null;
}
/**
* Get most recent time
*
* @param type
* @return
*/
public DataTime getMostRecent(IMonitor monitor, String type) {
return null;
}
/**
* @return the zoneDialog
* @return zoneDialog
*/
public SnowZoneTableDlg getZoneDialog() {
return zoneDialog;
}
/**
* Sets the zoneDialog
*
* @param zoneDialog
* the zoneDialog to set
*/
public void setZoneDialog(SnowZoneTableDlg zoneDialog) {
this.zoneDialog = zoneDialog;
}
@Override
protected void processAtStartup(ObReport report) {
obData.addReport(report);
}
/**
* First start
*/
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ObsMonitor#processAtStartup(com.raytheon.
* uf.viz.monitor.data.ObReport)
*/
@Override
protected void processAtStartup(ObReport report) {
obData.addReport(report);
}
}

View file

@ -19,11 +19,9 @@
**/
package com.raytheon.uf.viz.monitor.snow.ui.actions;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
@ -42,22 +40,32 @@ import com.raytheon.uf.viz.monitor.snow.SnowMonitor;
* Nov 30, 2009 3424 zhao/wkwock/slav zhao/wkwock/slav Automatically updates snow display. Display station data.
* Dec 18, 2009 3424 zhao Launch snow monitor and snow zone/station table dialog separately here
* Feb 26, 2010 4282 zhao changed to follow the same launch mechanism in FOG
* Nov.15, 2012 1297 skorolev Cleaned code
*
* </pre>
*
* @author grichard
* @version 1.0
*/
public class SnowAction extends AbstractHandler {
public class SnowAction extends AbstractHandler {
/*
* (non-Javadoc)
*
* @see
* org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands
* .ExecutionEvent)
*/
@Override
public Object execute(ExecutionEvent arg0) throws ExecutionException {
System.out.println("Activating/Action for SNOW...");
SnowMonitor snow = SnowMonitor.getInstance();
if ( snow.zoneDialog == null || snow.zoneDialog.isDisposed()) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
snow.launchDialog("zone", shell);
if (snow.getZoneDialog() == null || snow.getZoneDialog().isDisposed()) {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell();
snow.launchDialog("zone", shell);
}
return null;
}

View file

@ -68,9 +68,8 @@ public class SnowMonitoringAreaConfigDlg extends MonitoringAreaConfigDlg {
configManager.saveConfigData();
/**
* DR#11279:
* re-initialize threshold manager and the monitor
* using new monitor area configuration
* DR#11279: re-initialize threshold manager and the monitor using
* new monitor area configuration
*/
SnowThresholdMgr.reInitialize();
SnowMonitor.reInitialize();
@ -81,7 +80,8 @@ public class SnowMonitoringAreaConfigDlg extends MonitoringAreaConfigDlg {
+ "\n\nIf SNOW is running anywhere within "
+ "the office, please clear it.\n");
if ( configManager.getAddedZones().size() > 0 || addedZones.size() > 0 ) {
if (configManager.getAddedZones().size() > 0
|| addedZones.size() > 0) {
String message2 = "New zones have been added, and their monitoring thresholds "
+ "have been set to default values; would you like to modify "
+ "their threshold values now?";

View file

@ -21,6 +21,7 @@ package com.raytheon.uf.viz.monitor.snow.ui.dialogs;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.eclipse.swt.widgets.Shell;
@ -28,6 +29,7 @@ import com.raytheon.uf.common.monitor.config.MonitorConfigurationManager;
import com.raytheon.uf.common.monitor.config.SnowMonitorConfigurationManager;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.ObConst.DataUsageKey;
import com.raytheon.uf.common.monitor.data.ObConst.DisplayVarName;
import com.raytheon.uf.viz.monitor.IMonitor;
import com.raytheon.uf.viz.monitor.data.ObMultiHrsReports;
import com.raytheon.uf.viz.monitor.events.IMonitorConfigurationEvent;
@ -49,6 +51,7 @@ import com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg;
* Dec 2, 2009 3424 zhao/wkwock/slav Fix display SNOW 2nd time problem.
* Dec 18, 2009 3424 zhao use ObMultiHrsReports for obs data archive
* July 20,2010 4891 skorolev added code to fireDialogShutdown
* Nov. 8, 2012 1297 skorolev Added initiateProdArray method
*
* </pre>
*
@ -57,14 +60,12 @@ import com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg;
*/
public class SnowZoneTableDlg extends ZoneTableDlg {
// private ZoneTableComp zoneTableComp;
private SnowMonDispThreshDlg snowThreshDlg;
/**
* Constructor (Dec 16, 2009, zhao)
*
* @param parent
* @param obData
*/
public SnowZoneTableDlg(Shell parent, ObMultiHrsReports obData) {
super(parent, obData, CommonConfig.AppName.SNOW);
@ -79,6 +80,39 @@ public class SnowZoneTableDlg extends ZoneTableDlg {
super(parent, CommonConfig.AppName.SNOW);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#initiateProdArray()
*/
@Override
public void initiateProdArray() {
varName = config.getSnowZoneStnTableColVarNames()[colIndex];
// Fill product array
prodArray = new ArrayList<String>();
String[] varprefs = { "VAR_", "BLIZ_", "FRZ_", "HSW_" };
for (DisplayVarName var : DisplayVarName.values()) {
String dispVarName = var.name();
if (colIndex == 1 && dispVarName.startsWith(varprefs[1])) {
prodArray.add(dispVarName);
} else if (colIndex == 2 && dispVarName.startsWith(varprefs[2])) {
prodArray.add(dispVarName);
} else if (colIndex == 3 && dispVarName.startsWith(varprefs[3])) {
prodArray.add(dispVarName);
} else if (dispVarName.startsWith(varprefs[0])
&& dispVarName.equals(varprefs[0] + varName.name())) {
prodArray.add(dispVarName);
}
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#configThreshAction()
*/
@Override
protected void configThreshAction() {
if (snowThreshDlg == null) {
@ -89,6 +123,13 @@ public class SnowZoneTableDlg extends ZoneTableDlg {
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.listeners.IMonitorListener#notify(com.raytheon
* .uf.viz.monitor.events.IMonitorEvent)
*/
@Override
public void notify(IMonitorEvent me) {
if (zoneTable.isDisposed()) {
@ -97,7 +138,7 @@ public class SnowZoneTableDlg extends ZoneTableDlg {
if (me.getSource() instanceof SnowMonitor) {
SnowMonitor monitor = (SnowMonitor) me.getSource();
Date date = monitor.getDialogTime();
Date date = monitor.getDialogTime();
if (date != null) {
if (!isLinkedToFrame()) {
date = monitor.getObData().getLatestNominalTime();
@ -107,64 +148,108 @@ public class SnowZoneTableDlg extends ZoneTableDlg {
}
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* addMonitorControlListener(com.raytheon.uf.viz.monitor.IMonitor)
*/
@Override
public void addMonitorControlListener(IMonitor monitor) {
getMonitorControlListeners().add(monitor);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireConfigUpdate
* (com.raytheon.uf.viz.monitor.events.IMonitorConfigurationEvent)
*/
@Override
public void fireConfigUpdate(IMonitorConfigurationEvent imce) {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireDialogShutdown
* (com.raytheon.uf.viz.monitor.listeners.IMonitorListener)
*/
@Override
public void fireDialogShutdown(IMonitorListener iml) {
// Display.getDefault().asyncExec(new Runnable() {
// public void run() {
// Iterator<IMonitor> iter = getMonitorControlListeners()
// .iterator();
// while (iter.hasNext()) {
// ((SnowMonitor) iter.next()).closeDialog();
// }
// }
// });
// Not used
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#fireKillMonitor
* ()
*/
@Override
public void fireKillMonitor() {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* fireThresholdUpdate
* (com.raytheon.uf.viz.monitor.events.IMonitorThresholdEvent)
*/
@Override
public void fireThresholdUpdate(IMonitorThresholdEvent imte) {
// TODO Auto-generated method stub
// Not used
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#
* getMonitorControlListeners()
*/
@Override
public ArrayList<IMonitor> getMonitorControlListeners() {
public List<IMonitor> getMonitorControlListeners() {
return controlListeners;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.listeners.IMonitorControlListener#
* removeMonitorContorlListener(com.raytheon.uf.viz.monitor.IMonitor)
*/
@Override
public void removeMonitorContorlListener(IMonitor monitor) {
getMonitorControlListeners().remove(monitor);
}
@Override
protected MonitorConfigurationManager getConfigMgr() {
return SnowMonitorConfigurationManager.getInstance();
}
@Override
protected void handleLinkToFrame() {
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#getConfigMgr()
*/
@Override
protected MonitorConfigurationManager getConfigMgr() {
return SnowMonitorConfigurationManager.getInstance();
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#handleLinkToFrame()
*/
@Override
protected void handleLinkToFrame() {
linkedToFrame = linkToFrameChk.getSelection();
SnowMonitor.getInstance().fireMonitorEvent(this.getClass().getName());
}
}
/*
* (non-Javadoc)
@ -174,20 +259,30 @@ public class SnowZoneTableDlg extends ZoneTableDlg {
*/
@Override
protected void shellDisposeAction() {
// shell.addDisposeListener(new DisposeListener() {
// @Override
// public void widgetDisposed(DisposeEvent e) {
// System.out.println("Fog monitor dialog DISPOSED");
// unregisterDialogFromMonitor();
// }
// });
// Not used
}
/**
/*
* (non-Javadoc)
*
* @see com.raytheon.uf.viz.monitor.ui.dialogs.ZoneTableDlg#
* setZoneSortColumnAndDirection()
*/
protected void unregisterDialogFromMonitor() {
fireDialogShutdown(this);
@Override
protected void setZoneSortColumnAndDirection() {
if (zoneTblData != null) {
zoneSortColumn = zoneTblData.getSortColumn();
zoneSortDirection = zoneTblData.getSortDirection();
}
return;
}
@Override
protected void setStnSortColumnAndDirection() {
if (stnTblData != null) {
stnSortColumn = stnTblData.getSortColumn();
stnSortDirection = stnTblData.getSortDirection();
}
}
}

View file

@ -19,74 +19,92 @@
**/
package com.raytheon.uf.viz.monitor.data;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* Keep Areas with Containers of ObReports by Time in Hash
* Template For Silver Springs
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 12/07/09 dhladky Initial Creation.
*
* </pre>
*
* @author dhladky
*
*/
* Keep Areas with Containers of ObReports by Time in Hash Template For Silver
* Springs
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 12/07/09 dhladky Initial Creation.
* Nov. 1, 2012 #1297 skorolev Changed ArrayList to List
*
* </pre>
*
* @author dhladky
*
*/
public class AreaContainer {
public ArrayList<String> stations = null;
public String areaId = null; // zone
public ConcurrentHashMap<String, StationContainer> container = null;
public AreaContainer(ArrayList<String> stations, String areaId) {
this.stations = stations;
/** List of stations **/
private List<String> stations = null;
/** Zone ID **/
private String areaId = null;
/** Map zone - stations **/
private ConcurrentHashMap<String, StationContainer> container = null;
/**
* Keeps station list for every zone.
*
* @param stations
* @param areaId
*/
public AreaContainer(List<String> stations, String areaId) {
this.setStations(stations);
this.areaId = areaId;
this.container = new ConcurrentHashMap<String, StationContainer>();
// creates the stations list for this area
for (String stationId: stations) {
for (String stationId : stations) {
StationContainer sc = new StationContainer(stationId);
container.put(stationId, sc);
}
}
/**
* Gets ObReports for station
*
* @param stationId
* @return StationContainer
*/
public StationContainer getStation(String stationId) {
StationContainer sc = null;
if (container.containsKey(stationId)) {
sc = container.get(stationId);
}
return sc;
}
/**
* Gets the container
*
* @return
*/
public ConcurrentHashMap<String, StationContainer> getContainer() {
return container;
}
/**
* Gets the Area ID
*
* @return
*/
public String getAreaId() {
return areaId;
}
/**
* If it's ever needed
* Removes zone and it's stations. If it's ever needed
*
* @param stationId
*/
public void removeStation(String stationId) {
@ -94,8 +112,7 @@ public class AreaContainer {
container.remove(stationId);
}
}
/**
* Get the best obReport (time)
*
@ -104,23 +121,20 @@ public class AreaContainer {
*/
public ObReport getBestAreaReport(Date key) {
ObReport report = new ObReport();
for (String station : container.keySet()) {
if (key != null) {
report = container.get(station).getMostRecent(key);
}
}
if (report == null) {
report = new ObReport();
}
return report;
}
/**
* Adds a report for this area.
*
* @param date
* @param report
*/
@ -129,4 +143,22 @@ public class AreaContainer {
container.get(report.getPlatformId()).addReport(date, report);
}
}
/**
* Sets station list
*
* @param stations
*/
public void setStations(List<String> stations) {
this.stations = stations;
}
/**
* Gets station list
*
* @return stations
*/
public List<String> getStations() {
return stations;
}
}

View file

@ -42,6 +42,7 @@ import com.raytheon.uf.common.monitor.data.ObConst;
* Feb 17, 2009 1999 grichard Initial creation.
* 3/16/2009 2047 grichard Add zone related routines.
* Dec 9, 2009 3424 zhao Added method getZoneId(platformId)
* Nov. 1, 2012 1297 skorolev Changed ArrayList to List.
*
* </pre>
*
@ -51,42 +52,73 @@ import com.raytheon.uf.common.monitor.data.ObConst;
public final class MonitoringArea {
// Private constructor -- all contents must be public static
/**
* Private constructor -- all contents must be public static
*/
private MonitoringArea() {
}
// The map that contains the zoneIds for all platform identifiers
private static Map<String, ArrayList<String>> zoneMap = new HashMap<String, ArrayList<String>>();
/**
* The map that contains the zoneIds for all platform identifiers
*/
private static Map<String, List<String>> zoneMap = new HashMap<String, List<String>>();
// The map that contains the platformIds for all zone identifiers
private static Map<String, ArrayList<String>> platformMap = new HashMap<String, ArrayList<String>>();
/**
* The map that contains the platformIds for all zone identifiers
*/
private static Map<String, List<String>> platformMap = new HashMap<String, List<String>>();
// Get the monitoring area time window
/**
* Get the monitoring area time window
*
* @return
*/
public static int getTimeWindow() {
return ObConst.THREAT_INTERVAL_HOURS;
}
// Getter for zone map
public static Map<String, ArrayList<String>> getZoneMap() {
/**
* Getter for zone map
*
* @return
*/
public static Map<String, List<String>> getZoneMap() {
return zoneMap;
}
// Setter for zone map
public static void setZoneMap(Map<String, ArrayList<String>> zoneMap) {
/**
* Setter for zone map
*
* @param zoneMap
*/
public static void setZoneMap(Map<String, List<String>> zoneMap) {
MonitoringArea.zoneMap = zoneMap;
}
// Getter for platform map
public static Map<String, ArrayList<String>> getPlatformMap() {
/**
* Getter for platform map
*
* @return
*/
public static Map<String, List<String>> getPlatformMap() {
return platformMap;
}
// Setter for platform map
public static void setPlatformMap(Map<String, ArrayList<String>> platformMap) {
/**
* Setter for platform map
*
* @param platformMap
*/
public static void setPlatformMap(Map<String, List<String>> platformMap) {
MonitoringArea.platformMap = platformMap;
}
// Getter for the List of all zones which associate with the given platform
/**
* Getter for the List of all zones which associate with the given platform
*
* @param platformId
* @return
*/
public static List<String> listZonesToPlatform(String platformId) {
return getZoneMap().get(platformId);
}
@ -112,17 +144,19 @@ public final class MonitoringArea {
return theZones;
}
/**
* @return list of stations
*/
public static String getPlatformIdList() {
StringBuilder stList = new StringBuilder();
Set<String> stns = new HashSet<String>();
for (String zone : platformMap.keySet()) {
ArrayList<String> platfrms = platformMap.get(zone);
List<String> platfrms = platformMap.get(zone);
stns.addAll(platfrms);
}
stList.append(stns.toString());
stList.deleteCharAt(0);
stList.deleteCharAt(stList.length() - 1);
// System.out.println("============ stList = " + stList.toString());
return stList.toString();
}

View file

@ -22,17 +22,20 @@ package com.raytheon.uf.viz.monitor.data;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.CommonConfig.AppName;
import com.raytheon.uf.common.monitor.data.CommonTableConfig.CellType;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.monitor.thresholds.AbstractThresholdMgr;
/**
* This class is a container of ObZoneHourReports objects for a
* caller-specified nominal date-time.
* (this class corresponds to the RcHourReports c++ class in AWIPS-1)
* This class is a container of ObZoneHourReports objects for a caller-specified
* nominal date-time. (this class corresponds to the RcHourReports c++ class in
* AWIPS-1)
*
* <pre>
*
@ -40,6 +43,8 @@ import com.raytheon.uf.viz.monitor.thresholds.AbstractThresholdMgr;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Dec. 1, 2009 3424 zhao Initial creation.
* Oct.29, 2012 1297 skorolev Changed HashMap to Map
* Oct.31 2012 1297 skorolev Clean code
*
* </pre>
*
@ -48,117 +53,160 @@ import com.raytheon.uf.viz.monitor.thresholds.AbstractThresholdMgr;
*/
public class ObHourReports {
/**
* the nominal time of this ObHourReports object
*/
private Date nominalTime;
private final IUFStatusHandler statusHandler = UFStatus
.getHandler(ObHourReports.class);
/**
* application name (snow, fog, safeseas, etc)
*/
private CommonConfig.AppName appName;
/**
* key is zone id, value is ObZoneHourReports object
*/
private HashMap<String, ObZoneHourReports> hourReports;
/**
* constructor
*
* @param appName
*/
public ObHourReports(Date nominalTime, CommonConfig.AppName appName, AbstractThresholdMgr thresholdMgr) {
this.nominalTime = nominalTime;
this.appName = appName;
hourReports = new HashMap<String, ObZoneHourReports>();
Map<String, ArrayList<String>> zoneStationMap = MonitoringArea.getPlatformMap();
for ( String zone : zoneStationMap.keySet() ) {
hourReports.put(zone, new ObZoneHourReports(nominalTime, zone, appName, thresholdMgr));
}
}
/**
* the nominal time of this ObHourReports object
*/
private Date nominalTime;
public void addReport(ObReport report) {
String station = report.getPlatformId();
ArrayList<String> zones = MonitoringArea.getZoneIds(station);
if ( zones.size() == 0 ) {
System.err.println("Error: station: " + station + " is not associated with any zone in the monitoring area");
return;
}
boolean hasZone = false;
for ( String zone : zones ) {
if ( hourReports.containsKey(zone) ) {
hasZone = true;;
hourReports.get(zone).addReport(report);
}
}
if ( hasZone == false ) {
System.err.println("Error in addreport() of ObHourReports: unable to add obs report to data archive");
}
}
public HashMap<String, ObZoneHourReports> getHourReports() {
return hourReports;
}
public TableData getZoneTableData() {
TableData tblData = new TableData(appName);
for ( String zone : hourReports.keySet() ) {
tblData.addTableRowData(this.getObZoneHourReports(zone).getZoneTableRowData());
//tblData.addTableRowData(hourReports.get(zone).getZoneTableRowData());
}
return tblData;
}
public TableData getFogZoneTableData(HashMap<String, CellType> algCellType) {
TableData tblData = new TableData(AppName.FOG);
for ( String zone : hourReports.keySet() ) {
CellType theAlgCellType;
if ( algCellType.containsKey(zone) ) {
theAlgCellType = algCellType.get(zone);
} else {
theAlgCellType = CellType.NotAvailable;
}
tblData.addTableRowData(this.getObZoneHourReports(zone).getFogZoneTableRowData(theAlgCellType));
}
return tblData;
}
public TableData getSSZoneTableData(HashMap<String, CellType> fogCellType) {
TableData tblData = new TableData(AppName.SAFESEAS);
for (String zone : hourReports.keySet()) {
CellType theFogCellType;
if (fogCellType.containsKey(zone)) {
theFogCellType = fogCellType.get(zone);
} else {
theFogCellType = CellType.NotAvailable;
}
tblData.addTableRowData(this.getObZoneHourReports(zone)
.getSSZoneTableRowData(theFogCellType));
}
return tblData;
}
/**
* application name (snow, fog, safeseas, etc)
*/
private CommonConfig.AppName appName;
/**
* Returns the ObZoneHourReports object of a caller-specified zone.
* If such object not available, returns null.
* @param zone
* @return
*/
public ObZoneHourReports getObZoneHourReports(String zone) {
if ( !hourReports.containsKey(zone) ) {
return null;
}
return hourReports.get(zone);
}
public Date getNominalTime() {
return nominalTime;
}
public CommonConfig.AppName getAppName() {
return appName;
}
/**
* key is zone id, value is ObZoneHourReports object
*/
private Map<String, ObZoneHourReports> hourReports;
/**
* constructor
*
* @param appName
*/
public ObHourReports(Date nominalTime, CommonConfig.AppName appName,
AbstractThresholdMgr thresholdMgr) {
this.nominalTime = nominalTime;
this.appName = appName;
hourReports = new HashMap<String, ObZoneHourReports>();
Map<String, List<String>> zoneStationMap = MonitoringArea
.getPlatformMap();
for (String zone : zoneStationMap.keySet()) {
hourReports.put(zone, new ObZoneHourReports(nominalTime, zone,
appName, thresholdMgr));
}
}
/**
* Adds data to hourReports
*
* @param report
*/
public void addReport(ObReport report) {
String station = report.getPlatformId();
ArrayList<String> zones = MonitoringArea.getZoneIds(station);
if (zones.size() == 0) {
statusHandler
.error("Error: station: "
+ station
+ " is not associated with any zone in the monitoring area");
return;
}
boolean hasZone = false;
for (String zone : zones) {
if (hourReports.containsKey(zone)) {
hasZone = true;
;
hourReports.get(zone).addReport(report);
}
}
if (hasZone == false) {
statusHandler
.error("Error in addreport() of ObHourReports: unable to add obs report to data archive");
}
}
/**
* @return hourReports
*/
public Map<String, ObZoneHourReports> getHourReports() {
return hourReports;
}
/**
* Get data for Zone table.
*
* @return tblData
*/
public TableData getZoneTableData() {
TableData tblData = new TableData(appName);
for (String zone : hourReports.keySet()) {
tblData.addTableRowData(this.getObZoneHourReports(zone)
.getZoneTableRowData());
}
return tblData;
}
/**
* Get data for Fog Table.
*
* @param algCellType
* @return tblData
*/
public TableData getFogZoneTableData(Map<String, CellType> algCellType) {
TableData tblData = new TableData(AppName.FOG);
for (String zone : hourReports.keySet()) {
CellType theAlgCellType;
if (algCellType.containsKey(zone)) {
theAlgCellType = algCellType.get(zone);
} else {
theAlgCellType = CellType.NotAvailable;
}
tblData.addTableRowData(this.getObZoneHourReports(zone)
.getFogZoneTableRowData(theAlgCellType));
}
return tblData;
}
/**
* Gets data for SAFESEAS table.
*
* @param fogCellType
* @return tblData
*/
public TableData getSSZoneTableData(Map<String, CellType> fogCellType) {
TableData tblData = new TableData(AppName.SAFESEAS);
for (String zone : hourReports.keySet()) {
CellType theFogCellType;
if (fogCellType.containsKey(zone)) {
theFogCellType = fogCellType.get(zone);
} else {
theFogCellType = CellType.NotAvailable;
}
tblData.addTableRowData(this.getObZoneHourReports(zone)
.getSSZoneTableRowData(theFogCellType));
}
return tblData;
}
/**
* Returns the ObZoneHourReports object of a caller-specified zone. If such
* object not available, returns null.
*
* @param zone
* @return hour reports
*/
public ObZoneHourReports getObZoneHourReports(String zone) {
if (!hourReports.containsKey(zone)) {
return null;
}
return hourReports.get(zone);
}
/**
* @return nominalTime
*/
public Date getNominalTime() {
return nominalTime;
}
/**
* @return appName
*/
public CommonConfig.AppName getAppName() {
return appName;
}
}

View file

@ -24,6 +24,7 @@ import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@ -49,6 +50,7 @@ import com.raytheon.uf.viz.monitor.thresholds.AbstractThresholdMgr;
* Dec. 1, 2009 3424 zhao Initial creation.
* Dec 24, 2009 3424 zhao added getTrendDataSet() that returns ObTrendDataSet object
* Jan 25, 2010 4281, 3888, 3877 wkwock/zhao added getHistTableData method
* Oct.31, 2012 1297 skorolev Clean code.
*
* </pre>
*
@ -66,7 +68,7 @@ public class ObMultiHrsReports {
/**
* Fog ALG CellType [key is zone, value is cell type]
*/
private HashMap<String, CellType> fogAlgCellType;
private Map<String, CellType> fogAlgCellType;
/**
* application name (snow, fog, safeseas, etc)
@ -86,6 +88,11 @@ public class ObMultiHrsReports {
private int maxFrames = MAX_FRAMES;
/**
* Constructor
*
* @param appName
*/
public ObMultiHrsReports(CommonConfig.AppName appName) {
this.appName = appName;
multiHrsReports = new TreeMap<Date, ObHourReports>();
@ -114,9 +121,10 @@ public class ObMultiHrsReports {
}
/**
* Add an ObReport object to the ObMultiHrsReports object
* Adds an ObReport object to the ObMultiHrsReports object
*
* @param report
* @return returns multiHrsReports
*/
public void addReport(ObReport report) {
// Date nominalTime = TableUtil
@ -129,14 +137,14 @@ public class ObMultiHrsReports {
report.setWindDir(ObConst.MISSING);
}
/**
* DR#11462:
* set DewpointDepr now, avoid using
* DewpointDepr = worstTemp - worstDewpoint
* for Zone/County Table, which
* causes mismatch between Zone/County table and Station table
* DR#11462: set DewpointDepr now, avoid using DewpointDepr = worstTemp
* - worstDewpoint for Zone/County Table, which causes mismatch between
* Zone/County table and Station table
*/
if ( report.getTemperature() != ObConst.MISSING && report.getDewpoint() != ObConst.MISSING ) {
report.setDewpointDepr(report.getTemperature() - report.getDewpoint() );
if (report.getTemperature() != ObConst.MISSING
&& report.getDewpoint() != ObConst.MISSING) {
report.setDewpointDepr(report.getTemperature()
- report.getDewpoint());
}
if (multiHrsReports.containsKey(nominalTime)) {
multiHrsReports.get(nominalTime).addReport(report);
@ -183,10 +191,10 @@ public class ObMultiHrsReports {
return this.getObHourReports(nominalTime).getFogZoneTableData(
fogAlgCellType);
}
if (appName == AppName.SAFESEAS) {
return this.getObHourReports(nominalTime).getSSZoneTableData(
fogAlgCellType);
}
if (appName == AppName.SAFESEAS) {
return this.getObHourReports(nominalTime).getSSZoneTableData(
fogAlgCellType);
}
return this.getObHourReports(nominalTime).getZoneTableData();
// return multiHrsReports.get(nominalTime).getZoneTableData();
@ -232,6 +240,12 @@ public class ObMultiHrsReports {
.getStationTableData();
}
/**
* Gets data for station table
*
* @param zone
* @return station table data
*/
public TableData getEmptyStationTableData(String zone) {
Date nominalTime = TableUtil.getNominalTime(SimulatedTime
.getSystemTime().getTime());
@ -241,6 +255,7 @@ public class ObMultiHrsReports {
}
/**
* Gets data for trend plots
*
* @param zone
* @param Station
@ -294,10 +309,6 @@ public class ObMultiHrsReports {
}
}
// System.out.println("startNominalTime = " + startNominalTime
// + "; latestNominalTime = " + latestNominalTime
// + "; number of nominal times = " + multiHrsReports.size());
// get data
ObTrendDataSet trendData = new ObTrendDataSet(zone, varName,
productName, appName, thresholdMgr);
@ -312,9 +323,6 @@ public class ObMultiHrsReports {
.getObStnHourReports(station).getObsTimes();
if (obsTimes != null) {
for (Date obsTime : obsTimes) {
// System.out.println("obs time = " + obsTime);
trendData.addDataPoint(obsTime,
new Float(this.getObHourReports(nominalTime)
.getObZoneHourReports(zone)
@ -423,9 +431,9 @@ public class ObMultiHrsReports {
}
/**
* Returns a SortedMap object of <nominal time, ObHourReports object>
* Returns a SortedMap object <nominal time, ObHourReports object>
*
* @return
* @return multiHrsReports
*/
public SortedMap<Date, ObHourReports> getMultiHrsReports() {
return multiHrsReports;
@ -512,6 +520,7 @@ public class ObMultiHrsReports {
}
/**
* Gets application name
*
* @return application name
*/
@ -539,27 +548,30 @@ public class ObMultiHrsReports {
/**
* Set the Fog ALG CellType map
*
* @param fogAlgCellType
* @param fogAlgCellType2
*/
public void setFogAlgCellType(HashMap<String, CellType> fogAlgCellType) {
this.fogAlgCellType = fogAlgCellType;
public void setFogAlgCellType(Map<String, CellType> fogAlgCellType2) {
this.fogAlgCellType = fogAlgCellType2;
}
/**
*
* @return fogAlgCellType
*/
public HashMap<String, CellType> getFogAlgCellType() {
public Map<String, CellType> getFogAlgCellType() {
return fogAlgCellType;
}
private void initFogAlgCellType() {
fogAlgCellType = new HashMap<String, CellType>();
Set<String> zones = MonitoringArea.getPlatformMap().keySet();
Iterator<String> itr = zones.iterator();
while (itr.hasNext()) {
fogAlgCellType.put(itr.next(), CellType.NotAvailable);
}
setFogAlgCellType(fogAlgCellType);
}
/**
* Initiates ALG cells for Fog table. Sets all as NotAvailable.
*/
private void initFogAlgCellType() {
fogAlgCellType = new HashMap<String, CellType>();
Set<String> zones = MonitoringArea.getPlatformMap().keySet();
Iterator<String> itr = zones.iterator();
while (itr.hasNext()) {
fogAlgCellType.put(itr.next(), CellType.NotAvailable);
}
setFogAlgCellType(fogAlgCellType);
}
}

View file

@ -19,65 +19,69 @@
**/
package com.raytheon.uf.viz.monitor.data;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* Keeper of the obsData. It is stored in a keyed structure
* Area > Station > Date > ObReport
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 12/07/09 dhladky Initial Creation.
*
* </pre>
*
* @author dhladky
*
*/
* Keeper of the obsData. It is stored in a keyed structure Area > Station >
* Date > ObReport
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 12/07/09 dhladky Initial Creation.
* Nov 11, 2012 1297 skorolev Changed ArrayList to List
*
* </pre>
*
* @author dhladky
*
*/
public class ObsData {
public ConcurrentHashMap<String, AreaContainer> tableData = null;
/**
* public construct
*/
public ObsData() {
tableData = new ConcurrentHashMap<String, AreaContainer>();
}
/**
* Add an area
*
* @param stations
* @param areaId
*/
public void addArea(String areaId, ArrayList<String> stations) {
public void addArea(String areaId, List<String> stations) {
AreaContainer ac = new AreaContainer(stations, areaId);
tableData.put(areaId, ac);
}
/**
* Gets the Area Container
*
* @param areaId
* @return
*/
public AreaContainer getArea(String areaId) {
AreaContainer ac = null;
if (tableData.containsKey(areaId)) {
ac = tableData.get(areaId);
}
return ac;
}
/**
* remove the area
*
* @param areaId
*/
public void removeArea(String areaId) {
@ -85,9 +89,10 @@ public class ObsData {
tableData.remove(areaId);
}
}
/**
* Gets the container
*
* @return
*/
public ConcurrentHashMap<String, AreaContainer> getContainer() {

View file

@ -34,322 +34,404 @@ import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
public class HodographDlg extends Dialog {
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
private Shell shell;
/**
* Hodograph dialog
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 26, 2012 1280 skorolev Changes for non-blocking dialog.
* Nov. 1, 2012 1297 skorolev Cleaned code
*
* </pre>
*
* @author wkwock
* @version 1.0
*/
public class HodographDlg extends CaveSWTDialog {
private String elementName = null;
private String siteName = null;
private String dataName = null;
/** direction names **/
private final String dirName[] = { "N", "NNE", "NE", "ENE", "E", "ESE",
"SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW" };
/*
* direction name
*/
private String dirName[] = { "N", "NNE", "NE", "ENE", "E", "ESE", "SE",
"SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW" };
/*
* red threshold in degree
*/
private float redStartDegree = 0;
private float redDegree = 0;
/** red start threshold in degree **/
private float redStartDegree = 0;
/*
* yellow threshold in degree
*/
private float yellowStartDegree = 0;
private float yellowDegree = 0;
/** red threshold in degree **/
private float redDegree = 0;
/*
* green threshold in degree
*/
private float greenStartDegree = 0;
private float greenDegree = 0;
/** yellow start threshold in degree **/
private float yellowStartDegree = 0;
/*
* Center x and y pixel point
*/
private final int CENTER_X = 285;
private final int CENTER_Y = 280;
/** yellow threshold in degree **/
private float yellowDegree = 0;
/*
* Radius
*/
private final int RADIUS = 260;
/*
* current time
*/
private Calendar curTime = null;
/** green start threshold in degree **/
private float greenStartDegree = 0;
/*
* Hodograph data
*/
private SortedMap<Date, Float> hodographData;
/** green threshold in degree **/
private float greenDegree = 0;
/*
* constant milliseconds in a day
*/
private final double milliSecInADay = 24.0 * 60 * 60 * 1000.0;
/** Center x pixel point **/
private final int CENTER_X = 285;
/*
* display
*/
private Display display;
/** Center y pixel point **/
private final int CENTER_Y = 280;
/**
* @param args
*/
/** Radius **/
private final int RADIUS = 260;
public HodographDlg(Shell parent, String elementName, String siteName,
String dataName) {
super(parent, 0);
this.display = parent.getDisplay();
this.elementName = elementName;
this.siteName = siteName;
this.dataName = dataName;
}
/** current time **/
private Calendar curTime = null;
/**
* In Hodogrpah, the 0 degree is at North, and increase clockwise, opposite
* in geometry.
*
* @param degree
* @return
*/
private float convertDegree(float degree) {
return (360 + 90 - degree) % 360;
}
/** Hodograph data **/
private SortedMap<Date, Float> hodographData;
public void setGreenThreshold(float greenFromDegree, float greenToDegree) {
if (greenToDegree < greenFromDegree)
this.greenDegree = ((greenFromDegree - greenToDegree) - 360) % 360;
else
this.greenDegree = greenFromDegree - greenToDegree;
this.greenStartDegree = convertDegree(greenFromDegree);
}
/** constant milliseconds in a day **/
private final double milliSecInADay = 24.0 * 60 * 60 * 1000.0;
public void setYellowThreshold(float yellowFromDegree, float yellowToDegree) {
if (yellowToDegree < yellowFromDegree)
this.yellowDegree = ((yellowFromDegree - yellowToDegree) - 360) % 360;
else
this.yellowDegree = yellowFromDegree - yellowToDegree;
this.yellowStartDegree = convertDegree(yellowFromDegree);
}
/** display **/
private Display display;
public void setRedThreshold(float redFromDegree, float redToDegree) {
if (redToDegree < redFromDegree)
this.redDegree = ((redFromDegree - redToDegree) - 360) % 360;
else
this.redDegree = redFromDegree - redToDegree;
/**
* Constructor
*
* @param parent
* @param siteName
* @param dataName
* @param title
*/
public HodographDlg(Shell parent, String siteName, String dataName,
String title) {
super(parent, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.DO_NOT_BLOCK
| CAVE.INDEPENDENT_SHELL);
this.display = parent.getDisplay();
setText(title);
setReturnValue(this.getText());
}
this.redStartDegree = convertDegree(redFromDegree);
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#constructShellLayout()
*/
@Override
protected Layout constructShellLayout() {
// Create the main layout for the shell.
GridLayout mainLayout = new GridLayout(1, false);
mainLayout.marginWidth = 2;
mainLayout.verticalSpacing = 2;
return mainLayout;
}
private int degreeToY(double degree) {
int y = CENTER_Y - (int) Math.round((Math.cos(degree) * RADIUS));
return y;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org
* .eclipse.swt.widgets.Shell)
*/
@Override
protected void initializeComponents(Shell shell) {
createHodoGraph();
addCloseBttn();
}
private int degreeToX(double degree) {
int x = CENTER_X + (int) Math.round((Math.sin(degree) * RADIUS));
return x;
}
/**
* In Hodogrpah, the 0 degree is at North, and increase clockwise, opposite
* in geometry.
*
* @param degree
* @return
*/
private float convertDegree(float degree) {
return (360 + 90 - degree) % 360;
}
private void plotTimeLbls(GC gc) {
Calendar currentTime = (Calendar) curTime.clone();
/**
* Sets Green Threshold
*
* @param greenFromDegree
* @param greenToDegree
*/
public void setGreenThreshold(float greenFromDegree, float greenToDegree) {
if (greenToDegree < greenFromDegree)
this.greenDegree = ((greenFromDegree - greenToDegree) - 360) % 360;
else
this.greenDegree = greenFromDegree - greenToDegree;
this.greenStartDegree = convertDegree(greenFromDegree);
}
for (int i = 13; i > 1; i--) {
String timeLabel = String.format("%tH:30", currentTime);
/**
* Sets Yellow Threshold
*
* @param yellowFromDegree
* @param yellowToDegree
*/
public void setYellowThreshold(float yellowFromDegree, float yellowToDegree) {
if (yellowToDegree < yellowFromDegree)
this.yellowDegree = ((yellowFromDegree - yellowToDegree) - 360) % 360;
else
this.yellowDegree = yellowFromDegree - yellowToDegree;
this.yellowStartDegree = convertDegree(yellowFromDegree);
}
int x = CENTER_X - (gc.textExtent(timeLabel).x / 2) - 2;
int y = CENTER_Y + RADIUS / 13 * i - gc.textExtent(timeLabel).y + 2;
gc.drawText(timeLabel, x, y, true);
currentTime.add(Calendar.HOUR_OF_DAY, -2);
}
gc.setLineWidth(1);
}
/**
* Sets Red Threshold
*
* @param redFromDegree
* @param redToDegree
*/
public void setRedThreshold(float redFromDegree, float redToDegree) {
if (redToDegree < redFromDegree)
this.redDegree = ((redFromDegree - redToDegree) - 360) % 360;
else
this.redDegree = redFromDegree - redToDegree;
private void plotDirNames(GC gc) {
for (int i = 0; i < dirName.length; i++) {
double radian = Math.PI * 2.0 * i / dirName.length;
int x = CENTER_X
+ (int) Math.round((Math.sin(radian) * (RADIUS + 10 + gc
.textExtent(dirName[i]).x)));
int y = CENTER_Y
- (int) Math.round((Math.cos(radian) * (RADIUS + 10 + gc
.textExtent(dirName[i]).x)));
gc.drawText(dirName[i], x, y);
}
}
this.redStartDegree = convertDegree(redFromDegree);
}
private void plotElementName(GC gc) {
gc.drawText(elementName, 5, 5);
}
/**
* Converts degrees to plot coordinate Y
*
* @param degree
* @return
*/
private int degreeToY(double degree) {
int y = CENTER_Y - (int) Math.round((Math.cos(degree) * RADIUS));
return y;
}
private void paintBackground(GC gc) {
gc.setBackground(display.getSystemColor(SWT.COLOR_GRAY));
gc.fillOval(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2);
/**
* Converts degrees to plot coordinate X
*
* @param degree
* @return
*/
private int degreeToX(double degree) {
int x = CENTER_X + (int) Math.round((Math.sin(degree) * RADIUS));
return x;
}
gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
gc.fillArc(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2, (int) Math.round(greenStartDegree), (int) Math
.round(greenDegree));
/**
* Plots time labels
*
* @param gc
*/
private void plotTimeLbls(GC gc) {
Calendar currentTime = (Calendar) curTime.clone();
String timeLabel = String.format("%tH:30", currentTime);
for (int i = 13; i > 1; i--) {
int x = CENTER_X - (gc.textExtent(timeLabel).x / 2) - 2;
int y = CENTER_Y + RADIUS / 13 * i - gc.textExtent(timeLabel).y + 2;
gc.drawText(timeLabel, x, y, true);
currentTime.add(Calendar.HOUR_OF_DAY, -2);
}
gc.setLineWidth(1);
}
gc.setBackground(display.getSystemColor(SWT.COLOR_YELLOW));
gc.fillArc(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2, (int) Math.round(yellowStartDegree), (int) Math
.round(yellowDegree));
/**
* Plots direction names.
*
* @param gc
*/
private void plotDirNames(GC gc) {
for (int i = 0; i < dirName.length; i++) {
double radian = Math.PI * 2.0 * i / dirName.length;
int x = CENTER_X
+ (int) Math.round((Math.sin(radian) * (RADIUS + 10 + gc
.textExtent(dirName[i]).x)));
int y = CENTER_Y
- (int) Math.round((Math.cos(radian) * (RADIUS + 10 + gc
.textExtent(dirName[i]).x)));
gc.drawText(dirName[i], x, y);
}
}
gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
gc.fillArc(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2, (int) Math.round(redStartDegree), (int) Math
.round(redDegree));
/**
* Paint Background
*
* @param gc
*/
private void paintBackground(GC gc) {
gc.setBackground(display.getSystemColor(SWT.COLOR_GRAY));
gc.fillOval(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2);
// goes back to original background color
gc.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN));
gc.fillArc(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2, (int) Math.round(greenStartDegree),
(int) Math.round(greenDegree));
}
gc.setBackground(display.getSystemColor(SWT.COLOR_YELLOW));
gc.fillArc(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2, (int) Math.round(yellowStartDegree),
(int) Math.round(yellowDegree));
private void plotWindDir(GC gc) {
gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_BLUE));
if (hodographData == null)
return;
long curSec = curTime.getTimeInMillis();
gc.setBackground(display.getSystemColor(SWT.COLOR_RED));
gc.fillArc(CENTER_X - RADIUS, CENTER_Y - RADIUS, RADIUS * 2,
RADIUS * 2, (int) Math.round(redStartDegree),
(int) Math.round(redDegree));
boolean lastOneExist = false;
int lastX = 0;
int lastY = 0;
// goes back to original background color
gc.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
for (Date obsTime : hodographData.keySet()) {
float obsVal = hodographData.get(obsTime);
/*
* When wind speed is zero, wind direction is
* set to be ObConst.MISSING, which is -9999.0f;
*/
if (obsVal < 0.0f) { // wind direction is missing
lastOneExist = false;
continue; // missing value
}
double obsValInRadian = convertDegree(obsVal) * Math.PI * 2.0
/ 360.0;
long thisSec = obsTime.getTime();
if (thisSec > curSec) {
lastOneExist = false;
continue; // not in the last 24 hour
}
if (thisSec < (curSec - milliSecInADay)) {
lastOneExist = false;
continue; // not in the last 24 hour
}
}
double offsetFromCenter = (milliSecInADay - curSec + thisSec)
/ milliSecInADay * RADIUS;
/**
* Plots wind direction
*
* @param gc
*/
private void plotWindDir(GC gc) {
gc.setBackground(display.getSystemColor(SWT.COLOR_DARK_BLUE));
if (hodographData == null)
return;
long curSec = curTime.getTimeInMillis();
int x = CENTER_X
+ (int) Math.round(offsetFromCenter
* Math.cos(obsValInRadian));
int y = CENTER_Y
- (int) Math.round(offsetFromCenter
* Math.sin(obsValInRadian));
boolean lastOneExist = false;
int lastX = 0;
int lastY = 0;
gc.fillOval(x, y, 5, 6);
if (lastOneExist)
gc.drawLine(x, y, lastX, lastY);
for (Date obsTime : hodographData.keySet()) {
float obsVal = hodographData.get(obsTime);
/*
* When wind speed is zero, wind direction is set to be
* ObConst.MISSING, which is -9999.0f;
*/
if (obsVal < 0.0f) { // wind direction is missing
lastOneExist = false;
continue; // missing value
}
double obsValInRadian = convertDegree(obsVal) * Math.PI * 2.0
/ 360.0;
long thisSec = obsTime.getTime();
if (thisSec > curSec) {
lastOneExist = false;
continue; // not in the last 24 hour
}
if (thisSec < (curSec - milliSecInADay)) {
lastOneExist = false;
continue; // not in the last 24 hour
}
lastX = x;
lastY = y;
lastOneExist = true;
}
double offsetFromCenter = (milliSecInADay - curSec + thisSec)
/ milliSecInADay * RADIUS;
}
int x = CENTER_X
+ (int) Math.round(offsetFromCenter
* Math.cos(obsValInRadian));
int y = CENTER_Y
- (int) Math.round(offsetFromCenter
* Math.sin(obsValInRadian));
public void setHodoGraphData(SortedMap<Date, Float> hodographData) {
this.hodographData = hodographData;
}
gc.fillOval(x, y, 5, 6);
if (lastOneExist)
gc.drawLine(x, y, lastX, lastY);
private void drawCanvas(Canvas drawBoard) {
drawBoard.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.setAntialias(SWT.ON);
e.gc.setLineWidth(1);
paintBackground(e.gc);
// draw circles
e.gc.setForeground(display
.getSystemColor(SWT.COLOR_DARK_MAGENTA));
int numCircle = 13;
for (int i = 1; i <= numCircle; i++)
e.gc.drawOval(CENTER_X - RADIUS / numCircle * i, CENTER_Y
- RADIUS / numCircle * i, RADIUS / numCircle * 2
* i, RADIUS / numCircle * 2 * i);
lastX = x;
lastY = y;
lastOneExist = true;
}
// draw direction lines
e.gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
for (int i = 0; i < 16; i++) {
int x2 = degreeToX(i / 16.0 * Math.PI * 2.0);
int y2 = degreeToY(i / 16.0 * Math.PI * 2.0);
e.gc.drawLine(CENTER_X, CENTER_Y, x2, y2);
}
}
plotDirNames(e.gc);
plotTimeLbls(e.gc);
plotElementName(e.gc);
plotWindDir(e.gc);
}
});
}
/**
* Sets hodograph data
*
* @param hodographData
*/
public void setHodoGraphData(SortedMap<Date, Float> hodographData) {
this.hodographData = hodographData;
}
private void addCloseBttn() {
Composite c = new Composite(shell, SWT.NONE);
GridLayout gl = new GridLayout(1, false);
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
/**
* Creates canvas
*
* @param drawBoard
*/
private void drawCanvas(Canvas drawBoard) {
drawBoard.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.setAntialias(SWT.ON);
e.gc.setLineWidth(1);
paintBackground(e.gc);
// draw circles
e.gc.setForeground(display
.getSystemColor(SWT.COLOR_DARK_MAGENTA));
int numCircle = 13;
for (int i = 1; i <= numCircle; i++)
e.gc.drawOval(CENTER_X - RADIUS / numCircle * i, CENTER_Y
- RADIUS / numCircle * i, RADIUS / numCircle * 2
* i, RADIUS / numCircle * 2 * i);
c.setLayout(gl);
c.setLayoutData(gd);
// draw direction lines
e.gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
for (int i = 0; i < 16; i++) {
int x2 = degreeToX(i / 16.0 * Math.PI * 2.0);
int y2 = degreeToY(i / 16.0 * Math.PI * 2.0);
e.gc.drawLine(CENTER_X, CENTER_Y, x2, y2);
}
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
Button closeBtn = new Button(c, SWT.CLOSE);
closeBtn.setText("Close");
closeBtn.setLayoutData(gd);
final Shell closeShell = shell;
closeBtn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
closeShell.dispose();
}
});
}
plotDirNames(e.gc);
plotTimeLbls(e.gc);
plotWindDir(e.gc);
}
});
}
public void open() {
Shell parent = getParent();
shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE);
/**
* Adds Close button
*/
private void addCloseBttn() {
Composite c = new Composite(getShell(), SWT.NONE);
GridLayout gl = new GridLayout(1, false);
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
shell.setText(elementName + " Hodograph for " + siteName + "#"
+ dataName);
shell.setLayout(new GridLayout(1, false));
c.setLayout(gl);
c.setLayoutData(gd);
Composite c = new Composite(shell, SWT.NONE);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
c.setLayoutData(data);
gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false);
Button closeBtn = new Button(c, SWT.CLOSE);
closeBtn.setText("Close");
closeBtn.setLayoutData(gd);
closeBtn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
close();
}
});
}
Canvas canvas = new Canvas(c, SWT.DIALOG_TRIM);
canvas.setSize(600, 600);
drawCanvas(canvas);
/**
* Plots trend graph
*/
public void createHodoGraph() {
addCloseBttn();
Composite c = new Composite(this.getShell(), SWT.NONE);
display = c.getDisplay();
Canvas canvas = new Canvas(c, SWT.DIALOG_TRIM);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
canvas.setSize(600, 600);
c.setLayoutData(data);
drawCanvas(canvas);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
public void setCurrentTime(Calendar currentTime) {
this.curTime = currentTime;
}
/**
* Sets current time
*
* @param currentTime
*/
public void setCurrentTime(Calendar currentTime) {
this.curTime = currentTime;
}
}

View file

@ -19,7 +19,7 @@
**/
package com.raytheon.uf.viz.monitor.listeners;
import java.util.ArrayList;
import java.util.List;
import com.raytheon.uf.viz.monitor.IMonitor;
import com.raytheon.uf.viz.monitor.events.IMonitorConfigurationEvent;
@ -27,8 +27,8 @@ import com.raytheon.uf.viz.monitor.events.IMonitorThresholdEvent;
/**
*
* IMonitorControlListener, Interface that gives some measure of control to dialogs
* over their corresponding monitors.
* IMonitorControlListener, Interface that gives some measure of control to
* dialogs over their corresponding monitors.
*
* <pre>
* SOFTWARE HISTORY
@ -42,20 +42,19 @@ import com.raytheon.uf.viz.monitor.events.IMonitorThresholdEvent;
*
*/
public interface IMonitorControlListener {
public void fireConfigUpdate(IMonitorConfigurationEvent imce);
public void fireThresholdUpdate(IMonitorThresholdEvent imte);
public void fireKillMonitor();
public void addMonitorControlListener(IMonitor monitor);
public void removeMonitorContorlListener(IMonitor monitor);
public ArrayList<IMonitor> getMonitorControlListeners();
public void removeMonitorContorlListener(IMonitor monitor);
public List<IMonitor> getMonitorControlListeners();
public void fireDialogShutdown(IMonitorListener iml);
}

View file

@ -19,9 +19,9 @@
**/
package com.raytheon.uf.viz.monitor.trendplot;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
@ -45,9 +45,10 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 2009-12-02 vkorolev Initial creation.
* 2010-01-21 4268 vkorolev Fixed Trend Plot
* 2012-10-15 1229 vkorolev Changes for non-blocking TrendPlotDlg
* 2009-12-02 skorolev Initial creation.
* 2010-01-21 4268 skorolev Fixed Trend Plot
* Oct 15,2012 1229 skorolev Changes for non-blocking TrendPlotDlg
* Nov 11,2012 1297 skorolev Added title parameter and cleaned code
* </pre>
*
* @author vkorolev
@ -58,7 +59,7 @@ public class TrendPlotDlg extends CaveSWTDialog {
private String station;
private ArrayList<String> product;
private List<String> product;
private String dataName;
@ -66,21 +67,34 @@ public class TrendPlotDlg extends CaveSWTDialog {
public Date curdate;
public String var;
/**
* Constructor
*
* @param parent
* @param selectedZone
* @param station
* @param product
* @param dataName
* @param title
*/
public TrendPlotDlg(Shell parent, String selectedZone, String station,
ArrayList<String> product, String dataName) {
List<String> product, String dataName, String title) {
super(parent, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.DO_NOT_BLOCK
| CAVE.INDEPENDENT_SHELL);
setText(getTrendPlotName(product) + " Trend Plot for " + station + "#"
+ dataName);
setText(title);
setReturnValue(this.getText());
this.selectedZone = selectedZone;
this.product = product;
this.dataName = dataName;
this.station = station;
}
/*
* (non-Javadoc)
*
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#constructShellLayout()
*/
@Override
protected Layout constructShellLayout() {
// Create the main layout for the shell.
@ -91,9 +105,15 @@ public class TrendPlotDlg extends CaveSWTDialog {
return mainLayout;
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org
* .eclipse.swt.widgets.Shell)
*/
@Override
protected void initializeComponents(Shell shell) {
setReturnValue(product);
// Initialize all layouts
Iterator<String> prodVar = product.iterator();
while (prodVar.hasNext()) {
@ -104,6 +124,9 @@ public class TrendPlotDlg extends CaveSWTDialog {
addCloseBtn();
}
/**
* Adds Close button.
*/
private void addCloseBtn() {
Composite c = new Composite(shell, SWT.NONE);
GridLayout gl = new GridLayout(1, false);
@ -116,44 +139,24 @@ public class TrendPlotDlg extends CaveSWTDialog {
closeBtn.setLayoutData(gd);
closeBtn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
shell.dispose();
close();
}
});
}
/**
* @return shell
*/
public Widget getCurrentShell() {
return shell;
}
/**
* Sets data for table.
*
* @param obData
*/
public void setData(ObMultiHrsReports obData) {
this.obData = obData;
}
private String getTrendPlotName(ArrayList<String> prod) {
String varName = null;
String name = (String) prod.get(0);
int stInd = name.indexOf("_");
if (prod.size() > 1) {
varName = name.substring(0, stInd);
if (varName.equals("SCA")) {
varName = "Small Craft Advisory";
} else if (varName.equals("GALE")) {
varName = "Gale Warning";
} else if (varName.equals("STORM")) {
varName = "Storm Warning";
} else if (varName.equals("HURRICANE")) {
varName = "Hurricane Force Wind Warning";
} else if (varName.equals("BLIZ")) {
varName = "Blizzard Warning";
} else if (varName.equals("FRZ")) {
varName = "Frizing Precipitation";
} else if (varName.equals("HSW")) {
varName = "Heavy Snow Warning";
}
} else {
varName = name.substring(stInd + 1);
}
return varName;
}
}

View file

@ -254,7 +254,7 @@ public class StationTableComp extends TableComp {
* @return Column index.
*/
@Override
protected int getColumnIndex(AppName appName, String sortCol) {
public int getColumnIndex(AppName appName, String sortCol) {
return tableConfig.getTableColumnIndex(appName, sortCol);
}
@ -301,7 +301,7 @@ public class StationTableComp extends TableComp {
* @param name
*/
public void setIdLabel(String name) {
idLbl.setText("Zone/County: "+ this.id +" - "+ name);
idLbl.setText("Zone/County: " + this.id + " - " + name);
controlComp.layout();
}
@ -355,11 +355,11 @@ public class StationTableComp extends TableComp {
}
}
@Override
protected void packColumns() {
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumn(i).pack();
table.getColumn(i).setWidth(defaultColWidth);
}
}
@Override
protected void packColumns() {
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumn(i).pack();
table.getColumn(i).setWidth(defaultColWidth);
}
}
}

View file

@ -30,89 +30,89 @@ import org.eclipse.swt.widgets.TableItem;
import com.raytheon.uf.common.monitor.data.ColumnAttribData;
import com.raytheon.uf.common.monitor.data.CommonConfig;
import com.raytheon.uf.common.monitor.data.CommonTableConfig;
import com.raytheon.uf.common.monitor.data.CommonConfig.AppName;
import com.raytheon.uf.common.monitor.data.CommonTableConfig;
import com.raytheon.uf.viz.monitor.data.TableData;
/**
* Zone table composite that contains the table for the zones.
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 7, 2009 lvenable Initial creation
*
*
* </pre>
*
*
* @author lvenable
* @version 1.0
*/
public class ZoneTableComp extends TableComp
{
public class ZoneTableComp extends TableComp {
/**
* Callback for the zone table.
*/
private IZoneTableAction zoneTableCallback;
/**
* Mouse point.
*/
private Point mousePt = new Point(0,0);
private Point mousePt = new Point(0, 0);
/**
* Common table config data.
*/
private CommonTableConfig tableConfig;
/**
* Constructor.
* @param parent Parent composite.
* @param data Table data.
* @param appName Application name.
* @param callback Zone table action callback.
*
* @param parent
* Parent composite.
* @param data
* Table data.
* @param appName
* Application name.
* @param callback
* Zone table action callback.
*/
public ZoneTableComp(Composite parent, TableData data, CommonConfig.AppName appName,
IZoneTableAction callback)
{
public ZoneTableComp(Composite parent, TableData data,
CommonConfig.AppName appName, IZoneTableAction callback) {
super(parent, data, appName);
this.zoneTableCallback = callback;
tableConfig = CommonTableConfig.getInstance();
tableConfig = CommonTableConfig.getInstance();
init();
}
/**
* Handle the mouse down action.
* @param event Mouse event.
*
* @param event
* Mouse event.
*/
@Override
protected void tableMouseDownAction(MouseEvent event)
{
protected void tableMouseDownAction(MouseEvent event) {
tableIndex = table.getSelectionIndex();
mousePt.x = event.x;
mousePt.y = event.y;
TableItem item = table.getItem(mousePt);
if (item == null)
{
if (item == null) {
return;
}
for (int i = 0; i < table.getColumnCount(); i++)
{
}
for (int i = 0; i < table.getColumnCount(); i++) {
Rectangle rect = item.getBounds(i);
if (rect.contains(mousePt))
{
if (rect.contains(mousePt)) {
int index = table.indexOf(item);
System.out.println("Item " + index + "-" + i);
if (i == 0)
{
if (i == 0) {
this.zoneTableCallback.zoneTableAction(index);
}
}
@ -123,42 +123,42 @@ public class ZoneTableComp extends TableComp
/**
* Handle the table mouse hover action.
* @param event Maouse event.
*
* @param event
* Maouse event.
*/
@Override
protected void tableMouseHoverAction(MouseEvent event)
{
protected void tableMouseHoverAction(MouseEvent event) {
Rectangle rect;
mousePt.x = event.x;
mousePt.y = event.y;
TableItem item = table.getItem(mousePt);
if (item == null)
{
if (item == null) {
table.setToolTipText(null);
return;
}
int index = table.indexOf(item);
for (int i = 0; i < table.getColumnCount(); i++)
{
for (int i = 0; i < table.getColumnCount(); i++) {
rect = item.getBounds(i);
if (rect.contains(mousePt))
{
table.setToolTipText(tableData.getTableRows().get(index).getTableCellDataArray()[i].getHoverText());
if (rect.contains(mousePt)) {
table.setToolTipText(tableData.getTableRows().get(index)
.getTableCellDataArray()[i].getHoverText());
}
}
}
/**
* Add controls above the table on the display.
* @param parentComp Parent composite.
*
* @param parentComp
* Parent composite.
*/
@Override
protected void addTopTableControls(Composite parentComp)
{
protected void addTopTableControls(Composite parentComp) {
GridData gd = new GridData();
gd.horizontalIndent = 10;
Label zoneLbl = new Label(parentComp, SWT.NONE);
@ -168,61 +168,65 @@ public class ZoneTableComp extends TableComp
/**
* Get the column index given the application name and sort column.
* @param appName Application name.
* @param columnName Column name.
*
* @param appName
* Application name.
* @param columnName
* Column name.
*/
@Override
protected int getColumnIndex(AppName appName, String columnName)
{
public int getColumnIndex(AppName appName, String columnName) {
return tableConfig.getTableColumnIndex(appName, columnName);
}
/**
* Get the array of column keys.
* @param appName Application name.
*
* @param appName
* Application name.
* @return String array of column keys.
*/
@Override
protected String[] getColumnKeys(AppName appName)
{
protected String[] getColumnKeys(AppName appName) {
return tableConfig.getTableColumnKeys(appName);
}
/**
* Get the default column width.
* @param appName Application name.
*
* @param appName
* Application name.
* @return The default column width.
*/
@Override
protected int getDefaultColWidth(AppName appName)
{
protected int getDefaultColWidth(AppName appName) {
int colWidth = tableConfig.getTableDefaultColWidth(appName);
return colWidth;
}
/**
* Get the column attribute data.
* @param colName Column name.
*
* @param colName
* Column name.
* @return The column attribute data.
*/
@Override
protected ColumnAttribData getColumnAttribteData(String colName)
{
protected ColumnAttribData getColumnAttribteData(String colName) {
return tableConfig.getTableColumnAttr(colName);
}
@Override
protected void tableColRightMouseAction(MouseEvent event)
{
protected void tableColRightMouseAction(MouseEvent event) {
// TODO Auto-generated method stub
}
@Override
protected void packColumns() {
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumn(i).pack();
table.getColumn(i).setWidth(defaultColWidth);
}
}
@Override
protected void packColumns() {
for (int i = 0; i < table.getColumnCount(); i++) {
table.getColumn(i).pack();
table.getColumn(i).setWidth(defaultColWidth);
}
}
}