Omaha #3226 added filter support for lightning data
Change-Id: Ie5b90aeb3662c01a637803b604ae1488140102a4 Former-commit-id: 6b2a618685dad201b1d88abc132d4a5e31251f58
This commit is contained in:
parent
9b73096d46
commit
a02a7a90c7
12 changed files with 983 additions and 23 deletions
|
@ -9,9 +9,19 @@ Export-Package: com.raytheon.edex.plugin.binlightning.dao
|
||||||
Import-Package: com.raytheon.edex.esb,
|
Import-Package: com.raytheon.edex.esb,
|
||||||
com.raytheon.edex.exception,
|
com.raytheon.edex.exception,
|
||||||
com.raytheon.edex.plugin,
|
com.raytheon.edex.plugin,
|
||||||
|
com.raytheon.uf.common.dataquery.requests,
|
||||||
|
com.raytheon.uf.common.geospatial,
|
||||||
|
com.raytheon.uf.common.localization,
|
||||||
|
com.raytheon.uf.common.localization.exception,
|
||||||
com.raytheon.uf.common.numeric,
|
com.raytheon.uf.common.numeric,
|
||||||
|
com.raytheon.uf.common.serialization,
|
||||||
|
com.raytheon.uf.common.serialization.adapters,
|
||||||
com.raytheon.uf.common.status,
|
com.raytheon.uf.common.status,
|
||||||
com.raytheon.uf.common.wmo,
|
com.raytheon.uf.common.wmo,
|
||||||
|
com.vividsolutions.jts,
|
||||||
|
com.vividsolutions.jts.geom,
|
||||||
|
com.vividsolutions.jts.geom.prep,
|
||||||
|
com.vividsolutions.jts.io,
|
||||||
gov.noaa.nws.ost.edex.plugin.binlightning,
|
gov.noaa.nws.ost.edex.plugin.binlightning,
|
||||||
org.apache.commons.logging
|
org.apache.commons.logging
|
||||||
Require-Bundle: com.raytheon.uf.common.dataplugin.binlightning;bundle-version="1.12.1174",
|
Require-Bundle: com.raytheon.uf.common.dataplugin.binlightning;bundle-version="1.12.1174",
|
||||||
|
|
|
@ -37,6 +37,7 @@ import javax.crypto.IllegalBlockSizeException;
|
||||||
import com.raytheon.edex.esb.Headers;
|
import com.raytheon.edex.esb.Headers;
|
||||||
import com.raytheon.edex.exception.DecoderException;
|
import com.raytheon.edex.exception.DecoderException;
|
||||||
import com.raytheon.edex.plugin.AbstractDecoder;
|
import com.raytheon.edex.plugin.AbstractDecoder;
|
||||||
|
import com.raytheon.edex.plugin.binlightning.filter.LightningGeoFilter;
|
||||||
import com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory;
|
import com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory;
|
||||||
import com.raytheon.edex.plugin.binlightning.impl.IBinLightningDecoder;
|
import com.raytheon.edex.plugin.binlightning.impl.IBinLightningDecoder;
|
||||||
import com.raytheon.edex.plugin.binlightning.impl.LightningDataSource;
|
import com.raytheon.edex.plugin.binlightning.impl.LightningDataSource;
|
||||||
|
@ -86,6 +87,7 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
||||||
* added decodeBinLightningData() and decodeBitShiftedBinLightningData() from BinLightningDecoderUtil
|
* added decodeBinLightningData() and decodeBitShiftedBinLightningData() from BinLightningDecoderUtil
|
||||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor, added extractPData()
|
* Jun 05, 2014 3226 bclement LightningStikePoint refactor, added extractPData()
|
||||||
* Jun 09, 2014 3226 bclement moved data array decrypt prep to EncryptedBinLightingCipher
|
* Jun 09, 2014 3226 bclement moved data array decrypt prep to EncryptedBinLightingCipher
|
||||||
|
* Jun 10, 2014 3226 bclement added filter support
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -190,7 +192,7 @@ public class BinLightningDecoder extends AbstractDecoder {
|
||||||
// post processing data - if not keep-alive record
|
// post processing data - if not keep-alive record
|
||||||
BinLightningRecord report = null;
|
BinLightningRecord report = null;
|
||||||
if (strikes.size() > 0) {
|
if (strikes.size() > 0) {
|
||||||
report = new BinLightningRecord(strikes);
|
report = LightningGeoFilter.createFilteredRecord(strikes);
|
||||||
} else {
|
} else {
|
||||||
return new PluginDataObject[0];
|
return new PluginDataObject[0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/**
|
||||||
|
* 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.edex.plugin.binlightning.filter;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JAXB POJO for filter bounding box
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 11, 2014 3226 bclement Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author bclement
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@XmlAccessorType(XmlAccessType.NONE)
|
||||||
|
public class GeoFilterBbox {
|
||||||
|
|
||||||
|
@XmlAttribute(required = true)
|
||||||
|
private double minx;
|
||||||
|
|
||||||
|
@XmlAttribute(required = true)
|
||||||
|
private double maxx;
|
||||||
|
|
||||||
|
@XmlAttribute(required = true)
|
||||||
|
private double miny;
|
||||||
|
|
||||||
|
@XmlAttribute(required = true)
|
||||||
|
private double maxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public GeoFilterBbox() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param minx
|
||||||
|
* @param maxx
|
||||||
|
* @param miny
|
||||||
|
* @param maxy
|
||||||
|
*/
|
||||||
|
public GeoFilterBbox(double minx, double maxx, double miny, double maxy) {
|
||||||
|
this.minx = minx;
|
||||||
|
this.maxx = maxx;
|
||||||
|
this.miny = miny;
|
||||||
|
this.maxy = maxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the minx
|
||||||
|
*/
|
||||||
|
public double getMinx() {
|
||||||
|
return minx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param minx
|
||||||
|
* the minx to set
|
||||||
|
*/
|
||||||
|
public void setMinx(double minx) {
|
||||||
|
this.minx = minx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the maxx
|
||||||
|
*/
|
||||||
|
public double getMaxx() {
|
||||||
|
return maxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxx
|
||||||
|
* the maxx to set
|
||||||
|
*/
|
||||||
|
public void setMaxx(double maxx) {
|
||||||
|
this.maxx = maxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the miny
|
||||||
|
*/
|
||||||
|
public double getMiny() {
|
||||||
|
return miny;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param miny
|
||||||
|
* the miny to set
|
||||||
|
*/
|
||||||
|
public void setMiny(double miny) {
|
||||||
|
this.miny = miny;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the maxy
|
||||||
|
*/
|
||||||
|
public double getMaxy() {
|
||||||
|
return maxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxy
|
||||||
|
* the maxy to set
|
||||||
|
*/
|
||||||
|
public void setMaxy(double maxy) {
|
||||||
|
this.maxy = maxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/**
|
||||||
|
* 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.edex.plugin.binlightning.filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown during lightning filter config parsing
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 10, 2014 3226 bclement Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author bclement
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class GeoFilterException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -7455324971125247083L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public GeoFilterException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public GeoFilterException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cause
|
||||||
|
*/
|
||||||
|
public GeoFilterException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
* @param cause
|
||||||
|
*/
|
||||||
|
public GeoFilterException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,275 @@
|
||||||
|
/**
|
||||||
|
* 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.edex.plugin.binlightning.filter;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
import javax.xml.stream.XMLStreamException;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||||
|
import com.raytheon.uf.common.geospatial.SpatialException;
|
||||||
|
import com.raytheon.uf.common.geospatial.SpatialQueryFactory;
|
||||||
|
import com.raytheon.uf.common.geospatial.SpatialQueryResult;
|
||||||
|
import com.raytheon.uf.common.serialization.JAXBManager;
|
||||||
|
import com.raytheon.uf.common.serialization.SerializationException;
|
||||||
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses geographic filter configuration files. Example file located in utility
|
||||||
|
* directory.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 10, 2014 3226 bclement Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author bclement
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class GeoFilterParser {
|
||||||
|
|
||||||
|
private static final double LAT_MIN = -90;
|
||||||
|
|
||||||
|
private static final double LAT_MAX = 90;
|
||||||
|
|
||||||
|
private static final double LON_MIN = -180;
|
||||||
|
|
||||||
|
private static final double LON_MAX = 180;
|
||||||
|
|
||||||
|
/* CWA database constants */
|
||||||
|
|
||||||
|
private static final String CWA_TABLE = "cwa";
|
||||||
|
|
||||||
|
private static final String CWA_COLUMN = "cwa";
|
||||||
|
|
||||||
|
/* helper factories */
|
||||||
|
|
||||||
|
private static JAXBManager jaxbManager;
|
||||||
|
|
||||||
|
private static volatile boolean initialized = false;
|
||||||
|
|
||||||
|
private static final GeometryFactory GEOM_FACTORY = new GeometryFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize jaxb manager
|
||||||
|
*
|
||||||
|
* @throws JAXBException
|
||||||
|
*/
|
||||||
|
private static synchronized void initialize() throws JAXBException {
|
||||||
|
if (!initialized) {
|
||||||
|
jaxbManager = new JAXBManager(GeoFilters.class);
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse filter config file from input stream. Does not close input stream.
|
||||||
|
* Any non-fatal parsing errors are returned in result.
|
||||||
|
*
|
||||||
|
* @param in
|
||||||
|
* @return
|
||||||
|
* @throws JAXBException
|
||||||
|
* @throws SerializationException
|
||||||
|
*/
|
||||||
|
public static GeoFilterResult parse(InputStream in) throws JAXBException,
|
||||||
|
SerializationException {
|
||||||
|
if (!initialized) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
Object obj = jaxbManager.unmarshalFromInputStream(in);
|
||||||
|
if (obj instanceof GeoFilters) {
|
||||||
|
return parseInternal((GeoFilters) obj);
|
||||||
|
} else {
|
||||||
|
throw new SerializationException("Unexpected XML object type: "
|
||||||
|
+ obj.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #parse
|
||||||
|
* @param filters
|
||||||
|
* jaxb pojo
|
||||||
|
* @return
|
||||||
|
* @throws XMLStreamException
|
||||||
|
*/
|
||||||
|
private static GeoFilterResult parseInternal(GeoFilters filters) {
|
||||||
|
List<Geometry> geoms = new ArrayList<Geometry>();
|
||||||
|
List<GeoFilterException> errors = new ArrayList<GeoFilterException>(0);
|
||||||
|
List<GeoFilterBbox> bboxes = filters.getBboxes();
|
||||||
|
if (bboxes != null && !bboxes.isEmpty()) {
|
||||||
|
for (GeoFilterBbox bbox : bboxes) {
|
||||||
|
try {
|
||||||
|
geoms.addAll(convertBbox(bbox));
|
||||||
|
} catch (GeoFilterException e) {
|
||||||
|
errors.add(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<String> cwas = filters.getCwas();
|
||||||
|
if (cwas != null && !cwas.isEmpty()) {
|
||||||
|
for (String cwa : cwas) {
|
||||||
|
try {
|
||||||
|
geoms.addAll(getCWA(cwa));
|
||||||
|
} catch (GeoFilterException e) {
|
||||||
|
errors.add(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<Geometry> geometries = filters.getGeometries();
|
||||||
|
if (geometries != null) {
|
||||||
|
geoms.addAll(geometries);
|
||||||
|
}
|
||||||
|
List<PreparedGeometry> rval = new ArrayList<PreparedGeometry>(
|
||||||
|
geoms.size());
|
||||||
|
for (Geometry geom : geoms) {
|
||||||
|
rval.add(PreparedGeometryFactory.prepare(geom));
|
||||||
|
}
|
||||||
|
return new GeoFilterResult(rval, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get county warning area geometries by name. Performs a database lookup.
|
||||||
|
*
|
||||||
|
* @param cwa
|
||||||
|
* @return
|
||||||
|
* @throws GeoFilterException
|
||||||
|
*/
|
||||||
|
private static Collection<Geometry> getCWA(String cwa)
|
||||||
|
throws GeoFilterException {
|
||||||
|
Map<String, RequestConstraint> map = new HashMap<String, RequestConstraint>();
|
||||||
|
map.put(CWA_COLUMN, new RequestConstraint(cwa));
|
||||||
|
SpatialQueryResult[] results;
|
||||||
|
try {
|
||||||
|
results = SpatialQueryFactory.create().query(CWA_TABLE, null, null,
|
||||||
|
map, null);
|
||||||
|
} catch (SpatialException e) {
|
||||||
|
throw new GeoFilterException("Unable to query database for CWA: "
|
||||||
|
+ cwa, e);
|
||||||
|
}
|
||||||
|
if (results == null || results.length == 0) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<Geometry> rval = new ArrayList<Geometry>(results.length);
|
||||||
|
for (SpatialQueryResult result : results) {
|
||||||
|
rval.add(result.geometry);
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate bounding box coordinates in attributes. Converts bounding box to
|
||||||
|
* polygon.
|
||||||
|
*
|
||||||
|
* @param bbox
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static Collection<Geometry> convertBbox(GeoFilterBbox bbox)
|
||||||
|
throws GeoFilterException {
|
||||||
|
|
||||||
|
Coordinate upper = new Coordinate(bbox.getMaxx(), bbox.getMaxy());
|
||||||
|
Coordinate lower = new Coordinate(bbox.getMinx(), bbox.getMiny());
|
||||||
|
|
||||||
|
if (lower.x > upper.x || lower.y > upper.y) {
|
||||||
|
throw new GeoFilterException(
|
||||||
|
"Invalid bounding box tag. Minimum coordinate values "
|
||||||
|
+ "cannot be larger than maximum coordinate values: "
|
||||||
|
+ lower + " " + upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lower.y < LAT_MIN || upper.y > LAT_MAX) {
|
||||||
|
throw new GeoFilterException(
|
||||||
|
"Invalid bounding box tag. Box cannot cross poles: "
|
||||||
|
+ lower.y + "," + upper.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Geometry> rval = null;
|
||||||
|
lower.x = normalizeLon(lower.x);
|
||||||
|
upper.x = normalizeLon(upper.x);
|
||||||
|
/*
|
||||||
|
* if normalization switched order, it means it crossed the antimeridian
|
||||||
|
* and needs to be split into two boxes
|
||||||
|
*/
|
||||||
|
if (lower.x > upper.x) {
|
||||||
|
/* create a new box on the left of the map */
|
||||||
|
Coordinate leftLower = new Coordinate(LON_MIN, lower.y);
|
||||||
|
Coordinate leftUpper = new Coordinate(upper.x, upper.y);
|
||||||
|
/* change the old box to only cover the right of the map */
|
||||||
|
upper.x = LON_MAX;
|
||||||
|
Geometry left = createPolygon(leftLower, leftUpper);
|
||||||
|
Geometry right = createPolygon(lower, upper);
|
||||||
|
rval = Arrays.asList(left, right);
|
||||||
|
} else {
|
||||||
|
rval = Arrays.asList(createPolygon(lower, upper));
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lon
|
||||||
|
* @return longitude normalized to be between -180 and 180
|
||||||
|
*/
|
||||||
|
private static double normalizeLon(double lon) {
|
||||||
|
/* 360 degrees */
|
||||||
|
final double LON_TOTAL = LON_MAX * 2;
|
||||||
|
/* account for any far out degrees */
|
||||||
|
double rval = lon % LON_TOTAL;
|
||||||
|
/* subtract or add to get in range */
|
||||||
|
if (rval > LON_MAX) {
|
||||||
|
rval -= LON_TOTAL;
|
||||||
|
} else if (rval < LON_MIN) {
|
||||||
|
rval += LON_TOTAL;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mins
|
||||||
|
* @param maxes
|
||||||
|
* @return polygon defining a bounding box using corner points
|
||||||
|
*/
|
||||||
|
private static Geometry createPolygon(Coordinate mins, Coordinate maxes) {
|
||||||
|
Coordinate[] coordinates = new Coordinate[5];
|
||||||
|
coordinates[0] = new Coordinate(mins.x, mins.y);
|
||||||
|
coordinates[1] = new Coordinate(mins.x, maxes.y);
|
||||||
|
coordinates[2] = new Coordinate(maxes.x, maxes.y);
|
||||||
|
coordinates[3] = new Coordinate(maxes.x, mins.y);
|
||||||
|
/* polygons need a closed ring */
|
||||||
|
coordinates[4] = coordinates[0];
|
||||||
|
return GEOM_FACTORY.createPolygon(coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.edex.plugin.binlightning.filter;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Geographic filter parsing results. Wraps parsed data and any parsing errors.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 10, 2014 3226 bclement Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author bclement
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class GeoFilterResult {
|
||||||
|
|
||||||
|
private final Collection<GeoFilterException> errors;
|
||||||
|
|
||||||
|
private final Collection<PreparedGeometry> filters;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filters
|
||||||
|
*/
|
||||||
|
public GeoFilterResult(Collection<PreparedGeometry> filters) {
|
||||||
|
this(filters, Collections.<GeoFilterException> emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filters
|
||||||
|
* @param errors
|
||||||
|
*/
|
||||||
|
public GeoFilterResult(Collection<PreparedGeometry> filters,
|
||||||
|
Collection<GeoFilterException> errors) {
|
||||||
|
this.filters = filters;
|
||||||
|
this.errors = errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if any errors were encountered during parsing
|
||||||
|
* @see #getErrors()
|
||||||
|
*/
|
||||||
|
public boolean hasErrors() {
|
||||||
|
return !errors.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the errors
|
||||||
|
* @see #hasErrors()
|
||||||
|
*/
|
||||||
|
public Collection<GeoFilterException> getErrors() {
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the filters
|
||||||
|
*/
|
||||||
|
public Collection<PreparedGeometry> getFilters() {
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/**
|
||||||
|
* 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.edex.plugin.binlightning.filter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.serialization.adapters.GeometryAdapter;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root JAXB POJO for geographic filter configuration
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 11, 2014 3226 bclement Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author bclement
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@XmlRootElement(name = "filters")
|
||||||
|
@XmlAccessorType(XmlAccessType.NONE)
|
||||||
|
public class GeoFilters {
|
||||||
|
|
||||||
|
@XmlElement(name = "wkt")
|
||||||
|
@XmlJavaTypeAdapter(value = GeometryAdapter.class)
|
||||||
|
private List<Geometry> geometries;
|
||||||
|
|
||||||
|
@XmlElement(name = "cwa")
|
||||||
|
private List<String> cwas;
|
||||||
|
|
||||||
|
@XmlElement(name = "bbox")
|
||||||
|
private List<GeoFilterBbox> bboxes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public GeoFilters() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param geometries
|
||||||
|
* @param cwas
|
||||||
|
* @param bboxes
|
||||||
|
*/
|
||||||
|
public GeoFilters(List<Geometry> geometries,
|
||||||
|
List<String> cwas,
|
||||||
|
List<GeoFilterBbox> bboxes) {
|
||||||
|
this.geometries = geometries;
|
||||||
|
this.cwas = cwas;
|
||||||
|
this.bboxes = bboxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the geometries
|
||||||
|
*/
|
||||||
|
public List<Geometry> getGeometries() {
|
||||||
|
return geometries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param geometries
|
||||||
|
* the geometries to set
|
||||||
|
*/
|
||||||
|
public void setGeometries(List<Geometry> geometries) {
|
||||||
|
this.geometries = geometries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the cwas
|
||||||
|
*/
|
||||||
|
public List<String> getCwas() {
|
||||||
|
return cwas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cwas
|
||||||
|
* the cwas to set
|
||||||
|
*/
|
||||||
|
public void setCwas(List<String> cwas) {
|
||||||
|
this.cwas = cwas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the bboxes
|
||||||
|
*/
|
||||||
|
public List<GeoFilterBbox> getBboxes() {
|
||||||
|
return bboxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bboxes
|
||||||
|
* the bboxes to set
|
||||||
|
*/
|
||||||
|
public void setBboxes(List<GeoFilterBbox> bboxes) {
|
||||||
|
this.bboxes = bboxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
/**
|
||||||
|
* 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.edex.plugin.binlightning.filter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||||
|
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||||
|
import com.raytheon.uf.common.localization.IPathManager;
|
||||||
|
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||||
|
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||||
|
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||||
|
import com.raytheon.uf.common.localization.exception.LocalizationException;
|
||||||
|
import com.raytheon.uf.common.serialization.SerializationException;
|
||||||
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||||
|
import com.vividsolutions.jts.geom.Point;
|
||||||
|
import com.vividsolutions.jts.geom.prep.PreparedGeometry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Geographic filtering utility for lightning data. Configured in localization.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Jun 10, 2014 3226 bclement Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author bclement
|
||||||
|
* @version 1.0
|
||||||
|
* @see {@link GeoFilterParser}
|
||||||
|
*/
|
||||||
|
public class LightningGeoFilter {
|
||||||
|
|
||||||
|
private static final IUFStatusHandler log = UFStatus
|
||||||
|
.getHandler(LightningGeoFilter.class);
|
||||||
|
|
||||||
|
public static final String LOCALIZATION_FILTER_DIR = "binlightning/filters";
|
||||||
|
|
||||||
|
private static final GeometryFactory GEOM_FACTORY = new GeometryFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* map of lightning source names to filter geometries
|
||||||
|
*/
|
||||||
|
private static final Map<String, Collection<PreparedGeometry>> geometryMap = new ConcurrentHashMap<String, Collection<PreparedGeometry>>(
|
||||||
|
4);
|
||||||
|
|
||||||
|
private static volatile boolean initialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read filter configuration files from localization. Threadsafe and
|
||||||
|
* idempotent
|
||||||
|
*/
|
||||||
|
private static void initialize() {
|
||||||
|
synchronized (geometryMap) {
|
||||||
|
if (!initialized) {
|
||||||
|
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||||
|
|
||||||
|
LocalizationFile[] files = pathMgr.listFiles(pathMgr
|
||||||
|
.getLocalSearchHierarchy(LocalizationType.EDEX_STATIC),
|
||||||
|
LOCALIZATION_FILTER_DIR, new String[] { ".xml" }, true,
|
||||||
|
true);
|
||||||
|
|
||||||
|
for (LocalizationFile file : files) {
|
||||||
|
Collection<PreparedGeometry> filters = getFilterGeometries(file);
|
||||||
|
if (!filters.isEmpty()) {
|
||||||
|
String bareName = getFileNameWithoutExtension(file
|
||||||
|
.getName());
|
||||||
|
geometryMap.put(bareName.toLowerCase(), filters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse filter geometries from filter config file
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* @return empty list on error
|
||||||
|
*/
|
||||||
|
private static Collection<PreparedGeometry> getFilterGeometries(
|
||||||
|
LocalizationFile file) {
|
||||||
|
Collection<PreparedGeometry> rval;
|
||||||
|
InputStream in = null;
|
||||||
|
try {
|
||||||
|
in = file.openInputStream();
|
||||||
|
GeoFilterResult result = GeoFilterParser.parse(in);
|
||||||
|
if (result.hasErrors()) {
|
||||||
|
for (GeoFilterException e : result.getErrors()) {
|
||||||
|
log.error(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
log.warn("Filter parsing included errors, filters will be incomplete");
|
||||||
|
}
|
||||||
|
return result.getFilters();
|
||||||
|
} catch (JAXBException e) {
|
||||||
|
log.error("Unable to parse filter file: " + file.getName(), e);
|
||||||
|
rval = Collections.emptyList();
|
||||||
|
} catch (LocalizationException e) {
|
||||||
|
log.error("Unable to open filter file: " + file.getName(), e);
|
||||||
|
rval = Collections.emptyList();
|
||||||
|
} catch (SerializationException e) {
|
||||||
|
log.error("Unable to parse filter file: " + file.getName(), e);
|
||||||
|
rval = Collections.emptyList();
|
||||||
|
} finally {
|
||||||
|
if (in != null) {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(
|
||||||
|
"Problem closing localization file: "
|
||||||
|
+ file.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip the bare file name from path. Removes path and file suffix (if
|
||||||
|
* either exist)
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getFileNameWithoutExtension(String path) {
|
||||||
|
int slashIndex = path.lastIndexOf(IPathManager.SEPARATOR);
|
||||||
|
int start = slashIndex < 0 ? 0 : slashIndex + 1;
|
||||||
|
int dotIndex = path.lastIndexOf('.');
|
||||||
|
if (dotIndex < 0) {
|
||||||
|
return path.substring(start);
|
||||||
|
} else {
|
||||||
|
return path.substring(start, dotIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies data source filter to strikes. Source is determined from sample
|
||||||
|
* strike. If no filter exists for source, provided collection is returned.
|
||||||
|
*
|
||||||
|
* @param strikes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Collection<LightningStrikePoint> filterStrikes(
|
||||||
|
Collection<LightningStrikePoint> strikes) {
|
||||||
|
if (!initialized) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
Collection<LightningStrikePoint> rval = strikes;
|
||||||
|
if (!strikes.isEmpty()) {
|
||||||
|
LightningStrikePoint sample = strikes.iterator().next();
|
||||||
|
String source = BinLightningRecord.getDataSource(sample);
|
||||||
|
Collection<PreparedGeometry> filter = geometryMap.get(source
|
||||||
|
.toLowerCase());
|
||||||
|
if (filter != null && !filter.isEmpty()) {
|
||||||
|
rval = new ArrayList<LightningStrikePoint>(strikes.size());
|
||||||
|
for (LightningStrikePoint strike : strikes) {
|
||||||
|
if (passesFilter(filter, strike)) {
|
||||||
|
rval.add(strike);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filter
|
||||||
|
* @param strike
|
||||||
|
* @return true if strike is located in any of the filter geometries
|
||||||
|
*/
|
||||||
|
private static boolean passesFilter(Collection<PreparedGeometry> filter,
|
||||||
|
LightningStrikePoint strike) {
|
||||||
|
boolean passes = false;
|
||||||
|
Point p = GEOM_FACTORY.createPoint(new Coordinate(
|
||||||
|
strike.getLongitude(), strike.getLatitude()));
|
||||||
|
for (PreparedGeometry g : filter) {
|
||||||
|
/* covers instead of contains to include points at boundary */
|
||||||
|
if (g.covers(p)) {
|
||||||
|
passes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return passes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a BinLightningRecord after applying data source filter to list of
|
||||||
|
* strikes
|
||||||
|
*
|
||||||
|
* @see #filterStrikes(Collection)
|
||||||
|
* @param strikes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static BinLightningRecord createFilteredRecord(
|
||||||
|
Collection<LightningStrikePoint> strikes) {
|
||||||
|
return new BinLightningRecord(filterStrikes(strikes));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ import java.util.List;
|
||||||
import com.raytheon.edex.esb.Headers;
|
import com.raytheon.edex.esb.Headers;
|
||||||
import com.raytheon.edex.exception.DecoderException;
|
import com.raytheon.edex.exception.DecoderException;
|
||||||
import com.raytheon.edex.plugin.binlightning.BinLightningDecoder;
|
import com.raytheon.edex.plugin.binlightning.BinLightningDecoder;
|
||||||
|
import com.raytheon.edex.plugin.binlightning.filter.LightningGeoFilter;
|
||||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.BaseLightningPoint;
|
import com.raytheon.uf.common.dataplugin.binlightning.impl.BaseLightningPoint;
|
||||||
|
@ -56,6 +57,7 @@ import com.raytheon.uf.common.wmo.WMOTimeParser;
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* May 30, 2014 3226 bclement Initial creation
|
* May 30, 2014 3226 bclement Initial creation
|
||||||
* Jun 09, 2014 3226 bclement added encryption support
|
* Jun 09, 2014 3226 bclement added encryption support
|
||||||
|
* Jun 10, 2014 3226 bclement added filter support
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -193,7 +195,8 @@ public class TotalLightningDecoder {
|
||||||
}
|
}
|
||||||
List<LightningStrikePoint> strikes = decodeStrikes(fileName, pdata);
|
List<LightningStrikePoint> strikes = decodeStrikes(fileName, pdata);
|
||||||
if (!strikes.isEmpty()) {
|
if (!strikes.isEmpty()) {
|
||||||
BinLightningRecord record = new BinLightningRecord(strikes);
|
BinLightningRecord record = LightningGeoFilter
|
||||||
|
.createFilteredRecord(strikes);
|
||||||
return new PluginDataObject[] { record };
|
return new PluginDataObject[] { record };
|
||||||
} else {
|
} else {
|
||||||
return new PluginDataObject[0];
|
return new PluginDataObject[0];
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!-- example binlightning geospatial filter file
|
||||||
|
name of file corresponds to data source (eg NLDN.xml)
|
||||||
|
data is persisted if lightning strike point is in any of the filter areas
|
||||||
|
if a data source does not have any filters, all data is persisted -->
|
||||||
|
<filters>
|
||||||
|
<!-- bounding box filter: x is degrees longitude, y is degrees latitude-->
|
||||||
|
<bbox minx="-98.23" maxx="-97.24" miny="38.27" maxy="39.39" />
|
||||||
|
<!-- CWA filters: correspond to polygons defining the county warning areas -->
|
||||||
|
<cwa>OAX</cwa>
|
||||||
|
<cwa>DMX</cwa>
|
||||||
|
<cwa>FSD</cwa>
|
||||||
|
<!-- well known text geometries: x coordinates are longitude, y coordinates are latitude
|
||||||
|
first coordinate is always the same as last to close the polygon region -->
|
||||||
|
<wkt>POLYGON ((-101.24 41.4, -100.6 41.15, -101.01 40.75, -101.24 41.4))</wkt>
|
||||||
|
</filters>
|
|
@ -44,6 +44,7 @@ import com.raytheon.uf.common.time.util.TimeUtil;
|
||||||
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract
|
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract
|
||||||
* Feb 12, 2014 2655 njensen Set source
|
* Feb 12, 2014 2655 njensen Set source
|
||||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
|
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
|
||||||
|
* Jun 10, 2014 3226 bclement fixed source
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -56,6 +57,12 @@ public class TextLightningDecoder extends AbstractDecoder implements
|
||||||
|
|
||||||
private String traceId = null;
|
private String traceId = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* inferred from Wufeng Zhou comment in BinLightningDecoderUtil, stands for
|
||||||
|
* World Wide Lightning Location Network
|
||||||
|
*/
|
||||||
|
private static final String SOURCE = "WWLLN";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a TextLightning decoder. Calling hasNext() after construction
|
* Construct a TextLightning decoder. Calling hasNext() after construction
|
||||||
* will return false, decode() will return a null.
|
* will return false, decode() will return a null.
|
||||||
|
@ -96,9 +103,7 @@ public class TextLightningDecoder extends AbstractDecoder implements
|
||||||
|
|
||||||
report.setTraceId(traceId);
|
report.setTraceId(traceId);
|
||||||
|
|
||||||
// TODO anyone have any idea what the source should actually be
|
report.setSource(SOURCE);
|
||||||
// named?
|
|
||||||
report.setSource("text");
|
|
||||||
|
|
||||||
return new PluginDataObject[] { report };
|
return new PluginDataObject[] { report };
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ package com.raytheon.uf.common.dataplugin.binlightning;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -88,6 +89,7 @@ import com.raytheon.uf.common.time.util.TimeUtil;
|
||||||
* May 14, 2014 2536 bclement removed TimeTools usage
|
* May 14, 2014 2536 bclement removed TimeTools usage
|
||||||
* Jun 05, 2014 3226 bclement moved data arrays into map for easier management
|
* Jun 05, 2014 3226 bclement moved data arrays into map for easier management
|
||||||
* replaced addStrike() with List constructor, added pulses
|
* replaced addStrike() with List constructor, added pulses
|
||||||
|
* Jun 10, 2014 3226 bclement collections instead of lists, made data source logic public
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -162,7 +164,7 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
||||||
*
|
*
|
||||||
* @param strikes
|
* @param strikes
|
||||||
*/
|
*/
|
||||||
public BinLightningRecord(final List<LightningStrikePoint> strikes) {
|
public BinLightningRecord(final Collection<LightningStrikePoint> strikes) {
|
||||||
final int arraysSize = strikes.size();
|
final int arraysSize = strikes.size();
|
||||||
long[] obsTimes = new long[arraysSize];
|
long[] obsTimes = new long[arraysSize];
|
||||||
float[] latitudes = new float[arraysSize];
|
float[] latitudes = new float[arraysSize];
|
||||||
|
@ -191,8 +193,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
||||||
sensorCounts);
|
sensorCounts);
|
||||||
|
|
||||||
if (arraysSize > 0) {
|
if (arraysSize > 0) {
|
||||||
LightningStrikePoint sample = strikes.get(0);
|
LightningStrikePoint sample = strikes.iterator().next();
|
||||||
setDataSource(sample);
|
this.source = getDataSource(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
long startTimeMillis = Long.MAX_VALUE;
|
long startTimeMillis = Long.MAX_VALUE;
|
||||||
|
@ -248,7 +250,7 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
||||||
* @param pulseDataCount
|
* @param pulseDataCount
|
||||||
* total number of pulses for all strikes
|
* total number of pulses for all strikes
|
||||||
*/
|
*/
|
||||||
private void setPulseData(final List<LightningStrikePoint> strikes,
|
private void setPulseData(final Collection<LightningStrikePoint> strikes,
|
||||||
final int pulseDataCount) {
|
final int pulseDataCount) {
|
||||||
long[] pulseTimes = new long[pulseDataCount];
|
long[] pulseTimes = new long[pulseDataCount];
|
||||||
float[] pulseLats = new float[pulseDataCount];
|
float[] pulseLats = new float[pulseDataCount];
|
||||||
|
@ -292,22 +294,15 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
||||||
* Extract data source from strike
|
* Extract data source from strike
|
||||||
*
|
*
|
||||||
* @param strike
|
* @param strike
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
private void setDataSource(LightningStrikePoint strike) {
|
public static String getDataSource(LightningStrikePoint strike) {
|
||||||
if (source == null) {
|
if (strike.getLightSource() == null) {
|
||||||
if (strike.getLightSource() == null) {
|
return "NLDN";
|
||||||
source = "NLDN";
|
} else if (strike.getLightSource().isEmpty()) {
|
||||||
} else if (strike.getLightSource().isEmpty()) {
|
return "UNKN";
|
||||||
source = "UNKN";
|
|
||||||
} else {
|
|
||||||
source = strike.getLightSource();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (strike.getLightSource() == null) {
|
return strike.getLightSource();
|
||||||
source = "NLDN";
|
|
||||||
} else if (!source.equals(strike.getLightSource())) {
|
|
||||||
source = "UNKN";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue