Merge "Omaha #3226 added total lightning decoder" into omaha_14.4.1

Former-commit-id: ffa3e069c0beb5678ecb863b2950556d8c289ae1
This commit is contained in:
Nate Jensen 2014-06-09 09:38:50 -05:00 committed by Gerrit Code Review
commit c8b6324240
33 changed files with 1724 additions and 701 deletions

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.
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.
-->
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml"
menuText="1hr CG flash plot" id="1HrLightningFlashPlot">
</contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml"
menuText="15min CG flash plot" id="15MinLightningFlashPlot">
</contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml"
menuText="15min Pos/Neg CG flash plot" id="15MinPNLightningFlashPlot">
</contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml"
menuText="5min CG flash plot" id="5MinLightningFlashPlot">
</contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
menuText="1min Lgtng Seq CG flash" id="1MinLightningFlashSeq">
</contribute>
</menuTemplate>

View file

@ -20,27 +20,18 @@
--> -->
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml"
menuText="1hr CG stroke plot" id="1HrLightningStrokePlot" menuText="1hr CG stroke plot" id="1HrLightningStrokePlot">
productInterval="3600">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml"
menuText="15min CG stroke plot" id="15MinLightningStrokePlot" menuText="15min CG stroke plot" id="15MinLightningStrokePlot">
productInterval="900">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml"
menuText="15min Pos/Neg CG stroke plot" id="15MinPNLightningStrokePlot" menuText="15min Pos/Neg CG stroke plot" id="15MinPNLightningStrokePlot">
productInterval="900">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml"
menuText="5min CG stroke plot" id="5MinLightningStrokePlot" menuText="5min CG stroke plot" id="5MinLightningStrokePlot">
productInterval="300">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml" <contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
menuText="1min Lgtng Seq CG stroke" id="1MinLightningStrokeSeq"> menuText="1min Lgtng Seq CG stroke" id="1MinLightningStrokeSeq">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
</menuTemplate> </menuTemplate>

View file

@ -29,4 +29,9 @@
<substitute key="source" value="GLD"/> <substitute key="source" value="GLD"/>
</contribute> </contribute>
</contribute> </contribute>
<contribute xsi:type="subMenu" menuText="Total Lightning" id="ENTLNSubMenu">
<contribute xsi:type="subinclude" fileName="menus/lightning/entlnLightningBundleItems.xml">
<substitute key="source" value="ENTLN"/>
</contribute>
</contribute>
</menuTemplate> </menuTemplate>

View file

@ -20,27 +20,18 @@
--> -->
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml"
menuText="1hr CG flash plot" id="1HrLightningFlashPlot" menuText="1hr CG flash plot" id="1HrLightningFlashPlot">
productInterval="3600">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml"
menuText="15min CG flash plot" id="15MinLightningFlashPlot" menuText="15min CG flash plot" id="15MinLightningFlashPlot">
productInterval="900">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml"
menuText="15min Pos/Neg CG flash plot" id="15MinPNLightningFlashPlot" menuText="15min Pos/Neg CG flash plot" id="15MinPNLightningFlashPlot">
productInterval="900">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml" <contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml"
menuText="5min CG flash plot" id="5MinLightningFlashPlot" menuText="5min CG flash plot" id="5MinLightningFlashPlot">
productInterval="300">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml" <contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
menuText="1min Lgtng Seq CG flash" id="1MinLightningFlashSeq"> menuText="1min Lgtng Seq CG flash" id="1MinLightningFlashSeq">
<dataURI>/binlightning/%</dataURI>
</contribute> </contribute>
</menuTemplate> </menuTemplate>

View file

@ -35,6 +35,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.raytheon.uf.common.dataplugin.HDF5Util; import com.raytheon.uf.common.dataplugin.HDF5Util;
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.LightningConstants;
import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.Request; import com.raytheon.uf.common.datastorage.Request;
@ -94,6 +95,7 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
* fields when magnification set to 0 * fields when magnification set to 0
* Feb 27, 2013 DCS 152 jgerth/elau Support for WWLLN and multiple sources * Feb 27, 2013 DCS 152 jgerth/elau Support for WWLLN and multiple sources
* Jan 21, 2014 2667 bclement renamed record's lightSource field to source * Jan 21, 2014 2667 bclement renamed record's lightSource field to source
* Jun 05, 2014 3226 bclement reference datarecords by LightningConstants
* *
* </pre> * </pre>
* *
@ -637,7 +639,15 @@ public class LightningResource extends
recordList.add(rec); recordList.add(rec);
} }
List<IDataRecord> times = recordMap.get("obsTime"); List<IDataRecord> times = recordMap
.get(LightningConstants.TIME_DATASET);
List<IDataRecord> intensities = recordMap
.get(LightningConstants.INTENSITY_DATASET);
List<IDataRecord> lats = recordMap
.get(LightningConstants.LAT_DATASET);
List<IDataRecord> lons = recordMap
.get(LightningConstants.LON_DATASET);
int k = 0; int k = 0;
for (IDataRecord timeRec : times) { for (IDataRecord timeRec : times) {
@ -647,12 +657,13 @@ public class LightningResource extends
int numRecords = (int) time.getSizes()[0]; int numRecords = (int) time.getSizes()[0];
long[] timeData = time.getLongData(); long[] timeData = time.getLongData();
int[] intensityData = ((IntegerDataRecord) recordMap.get(
"intensity").get(k)).getIntData(); int[] intensityData = ((IntegerDataRecord) intensities
float[] latitudeData = ((FloatDataRecord) recordMap.get( .get(k)).getIntData();
"latitude").get(k)).getFloatData(); float[] latitudeData = ((FloatDataRecord) lats.get(k))
float[] longitudeData = ((FloatDataRecord) recordMap.get( .getFloatData();
"longitude").get(k)).getFloatData(); float[] longitudeData = ((FloatDataRecord) lons.get(k))
.getFloatData();
for (int i = 0; i < numRecords; i++) { for (int i = 0; i < numRecords; i++) {

View file

@ -0,0 +1,27 @@
#!/usr/bin/env python
import h5py
import os
import sys
# multiplicity was incorrectly interpreted as 'stike count' when
# it was the number of strokes (AKA pulses) in the strike (AKA flash)
LIGHTNING_H5_PATH = '/awips2/edex/data/hdf5/binlightning'
OLD_NAME = 'strikeCount'
NEW_NAME = 'pulseCount'
for file in os.listdir(LIGHTNING_H5_PATH):
if file.endswith('h5'):
h5file = None
try:
fileName = os.path.join(LIGHTNING_H5_PATH, file)
h5file = h5py.File(fileName, 'r+')
for g in h5file.values():
if NEW_NAME not in g and OLD_NAME in g:
g[NEW_NAME] = g[OLD_NAME]
except Exception, e:
print "Error renaming strikeCount in file", fileName, ":", e
finally:
if h5file:
h5file.close()

View file

@ -9,6 +9,7 @@ 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.numeric,
com.raytheon.uf.common.status, com.raytheon.uf.common.status,
com.raytheon.uf.common.wmo, com.raytheon.uf.common.wmo,
gov.noaa.nws.ost.edex.plugin.binlightning, gov.noaa.nws.ost.edex.plugin.binlightning,

View file

@ -5,6 +5,8 @@
<bean id="binlightningDecoder" <bean id="binlightningDecoder"
class="com.raytheon.edex.plugin.binlightning.BinLightningDecoder" /> class="com.raytheon.edex.plugin.binlightning.BinLightningDecoder" />
<bean id="totalLightningDecoder" class="com.raytheon.edex.plugin.binlightning.total.TotalLightningDecoder" />
<bean id="binlightningDistRegistry" factory-bean="distributionSrv" <bean id="binlightningDistRegistry" factory-bean="distributionSrv"
factory-method="register"> factory-method="register">
@ -16,42 +18,37 @@
<constructor-arg ref="clusteredBinLightningRoutes" /> <constructor-arg ref="clusteredBinLightningRoutes" />
</bean> </bean>
<camelContext id="clusteredBinLightningRoutes" <camelContext id="clusteredBinLightningRoutes" xmlns="http://camel.apache.org/schema/spring"
xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
errorHandlerRef="errorHandler">
<!--
<endpoint id="binlightningFileEndpoint"
uri="file:${edex.home}/data/sbn/binlightning?noop=true&amp;idempotent=false" />
<route id="binlightningFileConsumerRoute">
<from ref="binlightningFileEndpoint" />
<bean ref="fileToString" />
<setHeader headerName="pluginName">
<constant>binlightning</constant>
</setHeader>
<to uri="jms-durable:queue:Ingest.binlightning" />
</route>
-->
<!-- Begin binlightning routes --> <!-- Begin binlightning routes -->
<route id="binlightningIngestRoute"> <route id="binlightningIngestRoute">
<from uri="jms-durable:queue:Ingest.binlightning"/> <from uri="jms-durable:queue:Ingest.binlightning" />
<setHeader headerName="pluginName"> <setHeader headerName="pluginName">
<constant>binlightning</constant> <constant>binlightning</constant>
</setHeader> </setHeader>
<doTry> <doTry>
<pipeline> <pipeline>
<bean ref="stringToFile" /> <bean ref="stringToFile" />
<bean ref="binlightningDecoder" method="decode" /> <choice>
<to uri="direct-vm:persistIndexAlert" /> <when>
<simple>${in.header.header} regex '^SFPA42 KWBC.*'</simple>
<bean ref="totalLightningDecoder" method="decode" />
</when>
<otherwise>
<bean ref="binlightningDecoder" method="decode" />
</otherwise>
</choice>
</pipeline> <to uri="direct-vm:persistIndexAlert" />
<doCatch>
<exception>java.lang.Throwable</exception> </pipeline>
<to uri="log:binlightning?level=ERROR"/> <doCatch>
</doCatch> <exception>java.lang.Throwable</exception>
</doTry> <to uri="log:binlightning?level=ERROR" />
</doCatch>
</doTry>
<!-- bean ref="processUtil" method="delete" / --> <!-- bean ref="processUtil" method="delete" / -->
</route> </route>
</camelContext> </camelContext>
</beans> </beans>

View file

@ -47,8 +47,6 @@ import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType; import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.wmo.WMOHeader; import com.raytheon.uf.common.wmo.WMOHeader;
import com.raytheon.uf.common.wmo.WMOTimeParser; import com.raytheon.uf.common.wmo.WMOTimeParser;
@ -58,17 +56,6 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
/** /**
* AWIPS decoder adapter strategy for binary lightning data.<br/> * AWIPS decoder adapter strategy for binary lightning data.<br/>
* *
* Normal usage for this adapter is<br/>
* <code>
* BinLightningDecoder dec = new BinLightningDecoder();
* dec.setMessage(data);
* while(dec.hasNext())
* {
* BinLightningRecord r = dec.decode();
* // do something with record.
* }
* dec.dispose();
* </code>
* *
* <pre> * <pre>
* *
@ -98,6 +85,7 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
* Jun 03, 2014 3226 bclement removed unused WMO patterns, switched to UFStatus * Jun 03, 2014 3226 bclement removed unused WMO patterns, switched to UFStatus
* removed TimeTools usage, removed constructDataURI() call * removed TimeTools usage, removed constructDataURI() call
* added decodeBinLightningData() and decodeBitShiftedBinLightningData() from BinLightningDecoderUtil * added decodeBinLightningData() and decodeBitShiftedBinLightningData() from BinLightningDecoderUtil
* Jun 05, 2014 3226 bclement LightningStikePoint refactor, added extractPData()
* *
* </pre> * </pre>
* *
@ -118,7 +106,7 @@ public class BinLightningDecoder extends AbstractDecoder {
* Default lightning strike type for FLASH messages. RT_FLASH documents * Default lightning strike type for FLASH messages. RT_FLASH documents
* indicate no default, but D2D code defaults to STRIKE_CG also. * indicate no default, but D2D code defaults to STRIKE_CG also.
*/ */
public LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.STRIKE_CG; public LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.CLOUD_TO_GROUND;
private String traceId = null; private String traceId = null;
@ -153,30 +141,37 @@ public class BinLightningDecoder extends AbstractDecoder {
Calendar baseTime = WMOTimeParser.findDataTime( Calendar baseTime = WMOTimeParser.findDataTime(
wmoHdr.getYYGGgg(), fileName); wmoHdr.getYYGGgg(), fileName);
// Because binary nature of the encrypted data, the string created with its byte[] array may not have the same length of the byte[] array length /*
// So when DecoderTools.stripWMOHeader() assumes byte[] length == String length in its logic, it is observed that it may return a shorter byte[] than * Because binary nature of the encrypted data, the string
// the real data array. (Looks like a bug???) * created with its byte[] array may not have the same length of
* the byte[] array length So when DecoderTools.stripWMOHeader()
* assumes byte[] length == String length in its logic, it is
* observed that it may return a shorter byte[] than the real
* data array. (Looks like a bug???)
*/
// byte[] pdata = DecoderTools.stripWMOHeader(data, SFUS_PATTERN); // byte[] pdata = DecoderTools.stripWMOHeader(data, SFUS_PATTERN);
// if (pdata == null) { // if (pdata == null) {
// pdata = DecoderTools.stripWMOHeader(data, SFPA_PATTERN); // pdata = DecoderTools.stripWMOHeader(data, SFPA_PATTERN);
// } // }
// instead the following is used to strip WMO header a little more safely. /*
byte[] pdata = null; * instead the following is used to strip WMO header a little
if (wmoHdr.isValid() && wmoHdr.getMessageDataStart() > 0) { * more safely.
pdata = new byte[data.length - wmoHdr.getMessageDataStart()]; */
System.arraycopy(data, wmoHdr.getMessageDataStart(), pdata, 0, data.length - wmoHdr.getMessageDataStart()); byte[] pdata = extractPData(wmoHdr, data);
}
if ((pdata == null) || (pdata.length == 0)) { if ((pdata == null) || (pdata.length == 0)) {
return new PluginDataObject[0]; return new PluginDataObject[0];
} }
// /*
// Modified by Wufeng Zhou to handle both legacy bit-shifted and new encryted data * Modified by Wufeng Zhou to handle both legacy bit-shifted and
// * new encryted data
// Preserved the legacy decoding in BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(), and added logic to process *
// both encrypted data and legacy data * Preserved the legacy decoding in
// * BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(),
* and added logic to process both encrypted data and legacy
* data
*/
List<LightningStrikePoint> strikes = decodeBinLightningData( List<LightningStrikePoint> strikes = decodeBinLightningData(
data, pdata, traceId, wmoHdr, baseTime.getTime()); data, pdata, traceId, wmoHdr, baseTime.getTime());
@ -186,18 +181,14 @@ public class BinLightningDecoder extends AbstractDecoder {
return reports; return reports;
} }
// /*
// Done MOD by Wufeng Zhou * Done MOD by Wufeng Zhou
// */
// 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.size()); report = new BinLightningRecord(strikes);
for (LightningStrikePoint strike : strikes) {
report.addStrike(strike);
logger.debug(traceId + "-" + strike);
}
} else { } else {
return new PluginDataObject[0]; return new PluginDataObject[0];
} }
@ -215,18 +206,8 @@ public class BinLightningDecoder extends AbstractDecoder {
+ " at " + SDF.format(cStart.getTime())); + " at " + SDF.format(cStart.getTime()));
} }
} else { } else {
Calendar cStop = report.getStopTime(); report.setTraceId(traceId);
reports = new PluginDataObject[] { report };
TimeRange range = new TimeRange(cStart.getTimeInMillis(),
cStop.getTimeInMillis());
DataTime dataTime = new DataTime(cStart, range);
report.setDataTime(dataTime);
if (report != null) {
report.setTraceId(traceId);
reports = new PluginDataObject[] { report };
}
} }
} }
} else { } else {
@ -235,6 +216,23 @@ public class BinLightningDecoder extends AbstractDecoder {
return reports; return reports;
} }
/**
* Remove WMO header from data and return the remaining pdata
*
* @param wmoHdr
* @param data
* @return null if data is invalid
*/
public static byte[] extractPData(WMOHeader wmoHdr, byte[] data) {
byte[] pdata = null;
if (wmoHdr.isValid() && wmoHdr.getMessageDataStart() > 0) {
pdata = new byte[data.length - wmoHdr.getMessageDataStart()];
System.arraycopy(data, wmoHdr.getMessageDataStart(), pdata, 0,
data.length - wmoHdr.getMessageDataStart());
}
return pdata;
}
/** /**
* Decode bin lightning data, able to handle both legacy bit-shifted and new * Decode bin lightning data, able to handle both legacy bit-shifted and new
* encryted data * encryted data
@ -281,50 +279,52 @@ public class BinLightningDecoder extends AbstractDecoder {
boolean decodeDone = false; boolean decodeDone = false;
EncryptedBinLightningCipher cipher = new EncryptedBinLightningCipher(); EncryptedBinLightningCipher cipher = new EncryptedBinLightningCipher();
// /*
// Using different WMO headers to indicate whether the data is encrypted * Using different WMO headers to indicate whether the data is encrypted
// or not would be a nice option. * or not would be a nice option.
// However, that idea has been discussed but not adopted. * However, that idea has been discussed but not adopted.
// If in the future, WMO header can be different for legacy and * If in the future, WMO header can be different for legacy and
// encrypted data, or some other metadata can be used to decide * encrypted data, or some other metadata can be used to decide
// whether deceyption is needed, logic can be added here. * whether deceyption is needed, logic can be added here.
// *
// Before that happens, we'll use hints and trial & error to decode the * Before that happens, we'll use hints and trial & error to decode the
// data * data
// Hints: Per lightning data format spec, there are 3 bytes in the WMO * Hints: Per lightning data format spec, there are 3 bytes in the WMO
// header starting line that indicates the size of the encrypted block * header starting line that indicates the size of the encrypted block
// or the ASCII sequence # for legacy bit-shifted data * or the ASCII sequence # for legacy bit-shifted data
// However, the starting line is optional and AWIPS decode may not see * However, the starting line is optional and AWIPS decode may not see
// it at all because TG will strip that starting line away * it at all because TG will strip that starting line away
// We'll try to use this hint first, if is is not found, then trial and * We'll try to use this hint first, if is is not found, then trial and
// error way to decrypt and decode * error way to decrypt and decode
// *
// As of 11/05/2013, There is change in data spec. that the 3-bytes will * As of 11/05/2013, There is change in data spec. that the 3-bytes will
// not be encoded as encrypted block size anymore (it will always be * not be encoded as encrypted block size anymore (it will always be
// transmission sequence # if present) * transmission sequence # if present)
// So there should have some minor changes in the logic below for * So there should have some minor changes in the logic below for
// decoding the data. * decoding the data.
// However, as reading into the * However, as reading into the
// com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory.getDecoder() * com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory.getDecoder
// and follow-on code, we see the following data patterns * ()
// for legacy bit-shifted data, which could be used to reduce guess-work * and follow-on code, we see the following data patterns
// in data decryption: * for legacy bit-shifted data, which could be used to reduce guess-work
// The bit-shifted data will have multiple groups of the following * in data decryption:
// patterns: * The bit-shifted data will have multiple groups of the following
// 1-byte (unsigned byte): for size count * patterns:
// 1-byte (unsigned byte): for flash type: * 1-byte (unsigned byte): for size count
// 0x96 for FLASH_RPT (message size is 6 bytes each) * 1-byte (unsigned byte): for flash type:
// 0x97 for RT_FLASH_RPT (message size is 8 bytes each) * 0x96 for FLASH_RPT (message size is 6 bytes each)
// 0xd0 for OTHER_RPT (The D2D decoders declare but do not define this * 0x97 for RT_FLASH_RPT (message size is 8 bytes each)
// message, so unimplemented decoder) * 0xd0 for OTHER_RPT (The D2D decoders declare but do not define this
// 0xd1 for COMM_RPT (The D2D decoders declare but do not define this * message, so unimplemented decoder)
// message, so unimplemented decoder) * 0xd1 for COMM_RPT (The D2D decoders declare but do not define this
// 4-bytes: date time * message, so unimplemented decoder)
// multiple of 6 or 8 bytes (as determined by 2nd byte flash type) with * 4-bytes: date time
// count indicated in 1st byte * multiple of 6 or 8 bytes (as determined by 2nd byte flash type) with
// * count indicated in 1st byte
// So this is be used to determine whether the data need to be *
// decrypted. * So this is be used to determine whether the data need to be
* decrypted.
*/
/* /*
* // looks like previous assumption on block size bytes are not valid * // looks like previous assumption on block size bytes are not valid
@ -343,21 +343,23 @@ public class BinLightningDecoder extends AbstractDecoder {
if (needDecrypt) { if (needDecrypt) {
try { try {
// NOTE: 11/14/2013 WZ: /*
// encrypted test data on TNCF (got from Melissa Porricelli) * NOTE: 11/14/2013 WZ:
// seems to have extra 4 bytes (0x0d 0x0d 0x0a 0x03) at the end, * encrypted test data on TNCF (got from Melissa Porricelli)
// making the data size not a multiple of 16. However, original * seems to have extra 4 bytes (0x0d 0x0d 0x0a 0x03) at the end,
// test data do not have this trailing bytes. while NCEP test * making the data size not a multiple of 16. However, original
// data has extra 8 trailing bytes. * test data do not have this trailing bytes. while NCEP test
// Brain Rapp's email on 11/13/2013 confirms that Unidata LDM * data has extra 8 trailing bytes.
// software used by AWIPS II will strips off all SBN protocol * Brain Rapp's email on 11/13/2013 confirms that Unidata LDM
// headers * software used by AWIPS II will strips off all SBN protocol
// that precede the WMO header and adds its own 11 byte header * headers
// like this: "soh cr cr nl 2 5 4 sp cr cr nl". It * that precede the WMO header and adds its own 11 byte header
// also adds a four byte trailer consisting of "cr cr nl etx" * like this: "soh cr cr nl 2 5 4 sp cr cr nl". It
// (0x0d 0x0d 0x0a 0x03) * also adds a four byte trailer consisting of "cr cr nl etx"
// So, it seems necessary to trim trailing bytes if it is not * (0x0d 0x0d 0x0a 0x03)
// multiple of 16, warning messages will be logged though * So, it seems necessary to trim trailing bytes if it is not
* multiple of 16, warning messages will be logged though
*/
int dataLengthToBeDecrypted = pdata.length; int dataLengthToBeDecrypted = pdata.length;
if (pdata.length % 16 != 0) { if (pdata.length % 16 != 0) {
dataLengthToBeDecrypted = pdata.length dataLengthToBeDecrypted = pdata.length
@ -382,8 +384,10 @@ public class BinLightningDecoder extends AbstractDecoder {
decodeDone = true; decodeDone = true;
return null; return null;
} }
// not keep-alive record, then check data validity and decode /*
// into an ArrayList<LightningStrikePoint> of strikes * not keep-alive record, then check data validity and decode
* into an ArrayList<LightningStrikePoint> of strikes
*/
if (BinLightningDecoderUtil if (BinLightningDecoderUtil
.isLightningDataRecords(decryptedData)) { .isLightningDataRecords(decryptedData)) {
strikes = BinLightningDecoderUtil strikes = BinLightningDecoderUtil
@ -418,9 +422,11 @@ public class BinLightningDecoder extends AbstractDecoder {
if (decodeDone == false) { // not decoded through decrypt->decode if (decodeDone == false) { // not decoded through decrypt->decode
// process, try the legacy decoder // process, try the legacy decoder
logger.info(traceId + " - decoding as bit-shifted data"); logger.info(traceId + " - decoding as bit-shifted data");
// bit-shifting data format check call here will get us some more /*
// information on the data, also can compare the strikes with the * bit-shifting data format check call here will get us some more
// decoder result * information on the data, also can compare the strikes with the
* decoder result
*/
int estimatedStrikes = BinLightningDecoderUtil int estimatedStrikes = BinLightningDecoderUtil
.getBitShiftedDataStrikeCount(pdata); .getBitShiftedDataStrikeCount(pdata);
strikes = decodeBitShiftedBinLightningData(pdata, wmoHdr); strikes = decodeBitShiftedBinLightningData(pdata, wmoHdr);
@ -461,13 +467,15 @@ public class BinLightningDecoder extends AbstractDecoder {
switch (decoder.getError()) { switch (decoder.getError()) {
case IBinLightningDecoder.NO_ERROR: { case IBinLightningDecoder.NO_ERROR: {
for (LightningStrikePoint strike : decoder) { for (LightningStrikePoint strike : decoder) {
// use WMO Header to distinguish NLDN or GLD360 data because /*
// no bit-shifted data spec available for GLD360. * use WMO Header to distinguish NLDN or GLD360 data because
// 12/24/2013, WZ * no bit-shifted data spec available for GLD360.
// The WMO header start string is defined in * 12/24/2013, WZ
// BinLightningAESKey.properties file (normally, GLD360 data * The WMO header start string is defined in
// will have WMO header * BinLightningAESKey.properties file (normally, GLD360 data
// starts with SFPA41, or SFPA99 for test data.) * will have WMO header
* starts with SFPA41, or SFPA99 for test data.)
*/
String gld360WMOHeaderString = BinLightningAESKey String gld360WMOHeaderString = BinLightningAESKey
.getProps().getProperty( .getProps().getProperty(
"binlightning.gld360WMOHeaderStartString", "binlightning.gld360WMOHeaderStartString",

View file

@ -20,11 +20,17 @@
package com.raytheon.edex.plugin.binlightning.dao; package com.raytheon.edex.plugin.binlightning.dao;
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord; import java.util.Map;
import java.util.Map.Entry;
import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.PluginException;
import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
import com.raytheon.uf.common.dataplugin.binlightning.LightningConstants;
import com.raytheon.uf.common.dataplugin.persist.IPersistable; import com.raytheon.uf.common.dataplugin.persist.IPersistable;
import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.StorageException;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.edex.database.plugin.PluginDao; import com.raytheon.uf.edex.database.plugin.PluginDao;
@ -36,6 +42,7 @@ import com.raytheon.uf.edex.database.plugin.PluginDao;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 1/08/09 1674 bphillip Initial creation * 1/08/09 1674 bphillip Initial creation
* Jun 05, 2014 3226 bclement record now contains maps for data arrays
* </pre> * </pre>
* *
* @author bphillip * @author bphillip
@ -61,15 +68,38 @@ public class BinLightningDao extends PluginDao {
protected IDataStore populateDataStore(IDataStore dataStore, protected IDataStore populateDataStore(IDataStore dataStore,
IPersistable obj) throws Exception { IPersistable obj) throws Exception {
BinLightningRecord binLightningRec = (BinLightningRecord) obj; BinLightningRecord binLightningRec = (BinLightningRecord) obj;
Map<String, Object> strikeDataArrays = binLightningRec
for (int i = 0; i < binLightningRec.getDataArrays().length; i++) { .getStrikeDataArrays();
IDataRecord record = DataStoreFactory.createStorageRecord( populateFromMap(dataStore, obj, binLightningRec.getDataURI(),
binLightningRec.getDataNames()[i], binLightningRec strikeDataArrays);
.getDataURI(), binLightningRec.getDataArrays()[i]); Map<String, Object> pulseDataArrays = binLightningRec
record.setCorrelationObject(binLightningRec); .getPulseDataArrays();
dataStore.addDataRecord(record); String pulseGroup = binLightningRec.getDataURI() + DataURI.SEPARATOR
} + LightningConstants.PULSE_HDF5_GROUP_SUFFIX;
populateFromMap(dataStore, obj, pulseGroup, pulseDataArrays);
return dataStore; return dataStore;
} }
/**
* Adds each primitive data array object in map to the datastore using the
* provided group and the key of the map entry as the name
*
* @param dataStore
* @param obj
* @param group
* @param data
* @throws StorageException
*/
private void populateFromMap(IDataStore dataStore, IPersistable obj,
String group, Map<String, Object> data)
throws StorageException {
for (Entry<String, Object> e : data.entrySet()) {
String name = e.getKey();
Object dataArray = e.getValue();
IDataRecord record = DataStoreFactory.createStorageRecord(name,
group, dataArray);
record.setCorrelationObject(obj);
dataStore.addDataRecord(record);
}
}
} }

View file

@ -26,7 +26,6 @@ import java.util.List;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint; import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.decodertools.core.BasePoint;
import com.raytheon.uf.edex.decodertools.core.IBinDataSource; import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
/** /**
@ -42,6 +41,7 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
* 20070810 379 jkorman Initial Coding from prototype. * 20070810 379 jkorman Initial Coding from prototype.
* 20070912 379 jkorman Code review cleanup. * 20070912 379 jkorman Code review cleanup.
* May 14, 2014 2536 bclement removed TimeTools * May 14, 2014 2536 bclement removed TimeTools
* Jun 05, 2014 3226 bclement parseDate() now returns calendar
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
@ -87,13 +87,12 @@ abstract class BaseLightningDecoder implements IBinLightningDecoder
/** /**
* Parse the date field from a given data source. It is assumed that the * Parse the date field from a given data source. It is assumed that the
* data source is pointing to the current date/time data. * data source is pointing to the current date/time data.
* @return A BasePoint object with the time fields set to the observation *
* time. * @return A Calendar object with the time fields set to the observation
* time.
*/ */
BasePoint parseDate(IBinDataSource msgData) protected Calendar parseDate(IBinDataSource msgData)
{ {
BasePoint point = new BasePoint();
//********* Don't reorder these reads!!! //********* Don't reorder these reads!!!
int b1 = msgData.getU8(); int b1 = msgData.getU8();
int b2 = msgData.getU8(); int b2 = msgData.getU8();
@ -103,22 +102,18 @@ abstract class BaseLightningDecoder implements IBinLightningDecoder
// number of days since BASE_TIME // number of days since BASE_TIME
int days = ((word1 & DAYS_MASK) >> DAYS_SHFT); int days = ((word1 & DAYS_MASK) >> DAYS_SHFT);
obsTime.add(Calendar.DAY_OF_MONTH, days); obsTime.add(Calendar.DAY_OF_MONTH, days);
point.setYear(obsTime.get(Calendar.YEAR));
//Increment month, Calendar returns 0..11
point.setMonth(obsTime.get(Calendar.MONTH) + 1);
point.setDay(obsTime.get(Calendar.DAY_OF_MONTH));
int hours = (word1 & HOURS_HI_BIT_MASK) << HOURS_HI_BIT_SHFT; int hours = (word1 & HOURS_HI_BIT_MASK) << HOURS_HI_BIT_SHFT;
hours += (b2 & HOURS_LO_NYB_MASK) >>> HOURS_LO_NYB_SHFT; hours += (b2 & HOURS_LO_NYB_MASK) >>> HOURS_LO_NYB_SHFT;
point.setHour(hours); obsTime.set(Calendar.HOUR, hours);
int minutes = (b2 & MIN_P1_MASK) << MIN_P1_SHFT; int minutes = (b2 & MIN_P1_MASK) << MIN_P1_SHFT;
minutes += (b1 & MIN_P2_MASK) >>> MIN_P2_SHFT; minutes += (b1 & MIN_P2_MASK) >>> MIN_P2_SHFT;
point.setMinute(minutes); obsTime.set(Calendar.MINUTE, minutes);
point.setSecond((b1 & SECONDS_MASK)); obsTime.set(Calendar.SECOND, (b1 & SECONDS_MASK));
return point; obsTime.set(Calendar.MILLISECOND, 0);
return obsTime;
} }
/** /**

View file

@ -19,9 +19,11 @@
**/ **/
package com.raytheon.edex.plugin.binlightning.impl; package com.raytheon.edex.plugin.binlightning.impl;
import java.util.Calendar;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint; import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType; import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
import com.raytheon.uf.edex.decodertools.core.BasePoint; import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.edex.decodertools.core.IBinDataSource; import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
/** /**
@ -30,13 +32,14 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
* *
* <pre> * <pre>
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 20070810 379 jkorman Initial Coding from prototype. * 20070810 379 jkorman Initial Coding from prototype.
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
* @version 1.0 * @version 1.0
*/ */
@ -62,7 +65,7 @@ public class FlashLightningDecoder extends BaseLightningDecoder
{ {
if(msgData.available(TIME_SIZE)) if(msgData.available(TIME_SIZE))
{ {
BasePoint base = parseDate(msgData); Calendar baseTime = parseDate(msgData);
if(msgData.available(FLASH_MSG_SIZE * count)) if(msgData.available(FLASH_MSG_SIZE * count))
{ {
@ -70,17 +73,23 @@ public class FlashLightningDecoder extends BaseLightningDecoder
{ {
double lon = getFlashLon(msgData); double lon = getFlashLon(msgData);
double lat = getFlashLat(msgData); double lat = getFlashLat(msgData);
// Create the strike record from the report info and base time information.
LightningStrikePoint strikeData = new LightningStrikePoint(base,lat,lon,LtgMsgType.STRIKE_MSG_FL); double strikeStrength = msgData.getS8() * 2.0;
strikeData.setStrikeStrength(msgData.getS8() * 2.0);
// strike count and 1/10s seconds // strike count and 1/10s seconds
int u8 = msgData.getU8(); int u8 = msgData.getU8();
strikeData.setStrikeCount(u8 & 0x0F); int flashCount = u8 & 0x0F;
strikeData.setMillis(((u8 & 0xF0) >> 4) * 100);
Calendar obsTime = TimeUtil.newCalendar(baseTime);
obsTime.set(Calendar.MILLISECOND, ((u8 & 0xF0) >> 4) * 100);
// Create the strike record from the report info and base
// time information.
LightningStrikePoint strikeData = new LightningStrikePoint(
lat, lon, baseTime, LtgMsgType.STRIKE_MSG_FL);
strikeData.setType(DEFAULT_FLASH_TYPE); strikeData.setType(DEFAULT_FLASH_TYPE);
strikeData.setStrikeStrength(strikeStrength);
strikeData.setPulseCount(flashCount);
addStrike(strikeData); addStrike(strikeData);
} }
} }

View file

@ -26,22 +26,24 @@ import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
* Declare the interface for binary lightning decoding. The decoders are * Declare the interface for binary lightning decoding. The decoders are
* expected to implement an Iterable interface. Data decoding will take place * expected to implement an Iterable interface. Data decoding will take place
* during construction of the element. * during construction of the element.
*
* <pre> * <pre>
* the recommended constructor for this interface is * the recommended constructor for this interface is
* *
* @param data An IBinDataSource data source containing the data to be decoded. * @param data An IBinDataSource data source containing the data to be decoded.
* @param count The number of records that this decoder should see. * @param count The number of records that this decoder should see.
* <code>public X (IBinDataSource data, int count)</code> * <code>public X (IBinDataSource data, int count)</code>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 20070810 379 jkorman Initial Coding from prototype. * 20070810 379 jkorman Initial Coding from prototype.
* 20070912 379 jkorman Code review cleanup. * 20070912 379 jkorman Code review cleanup.
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
* @version 1.0 * @version 1.0
*/ */
@ -59,7 +61,7 @@ public interface IBinLightningDecoder extends Iterable<LightningStrikePoint>
public static final int OTHER_RPT = 0xD0; public static final int OTHER_RPT = 0xD0;
public static final int COMM_RPT = 0xD1; public static final int COMM_RPT = 0xD1;
public static final LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.STRIKE_CG; public static final LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.CLOUD_TO_GROUND;
/* /*
*/ */

View file

@ -19,9 +19,10 @@
**/ **/
package com.raytheon.edex.plugin.binlightning.impl; package com.raytheon.edex.plugin.binlightning.impl;
import java.util.Calendar;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint; import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType; import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
import com.raytheon.uf.edex.decodertools.core.BasePoint;
import com.raytheon.uf.edex.decodertools.core.IBinDataSource; import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
/** /**
@ -37,6 +38,7 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
* 20070810 379 jkorman Initial Coding from prototype. * 20070810 379 jkorman Initial Coding from prototype.
* 20070821 379 jkorman Added default strike type. * 20070821 379 jkorman Added default strike type.
* 20080823 379 jkorman getRTLat was using 24 bits instead of 23. * 20080823 379 jkorman getRTLat was using 24 bits instead of 23.
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
@ -66,7 +68,7 @@ public class RTLightningDecoder extends BaseLightningDecoder {
*/ */
private void doDecode(IBinDataSource msgData, int count) { private void doDecode(IBinDataSource msgData, int count) {
if (msgData.available(TIME_SIZE + (RT_MSG_SIZE * count))) { if (msgData.available(TIME_SIZE + (RT_MSG_SIZE * count))) {
BasePoint base = parseDate(msgData); Calendar baseTime = parseDate(msgData);
// for now just consume some data // for now just consume some data
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
long part = msgData.getU32(); long part = msgData.getU32();
@ -79,11 +81,11 @@ public class RTLightningDecoder extends BaseLightningDecoder {
double lat = getRTLat(part); double lat = getRTLat(part);
int strikeCount = getMult(part); int strikeCount = getMult(part);
LightningStrikePoint strikeData = new LightningStrikePoint( LightningStrikePoint strikeData = new LightningStrikePoint(lat,
base, lat, lon, LtgMsgType.STRIKE_MSG_RT); lon, baseTime, LtgMsgType.STRIKE_MSG_RT);
strikeData.setStrikeStrength(strength); strikeData.setStrikeStrength(strength);
strikeData.setStrikeCount(strikeCount); strikeData.setPulseCount(strikeCount);
// ***** // *****
// NCDC documents indicate that RT data can report both CC/CG // NCDC documents indicate that RT data can report both CC/CG
// but haven't seen any data nor is it in the D2D decoders. Set // but haven't seen any data nor is it in the D2D decoders. Set

View file

@ -0,0 +1,171 @@
/**
* 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.total;
import java.nio.ByteBuffer;
import com.raytheon.uf.common.numeric.UnsignedNumbers;
/**
* ByteBuffer wrapper that keeps track of checksums
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 3, 2014 3226 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class ChecksumByteBuffer {
private static final int SHORT_SIZE = Short.SIZE / Byte.SIZE;
private static final int INT_SIZE = Integer.SIZE / Byte.SIZE;
private static final int LONG_SIZE = Integer.SIZE / Byte.SIZE;
private final ByteBuffer buff;
private long totalSum;
private long packetSum;
/**
* @see ByteBuffer#wrap(byte[])
* @param data
*/
public ChecksumByteBuffer(byte[] data) {
this.buff = ByteBuffer.wrap(data);
}
/**
* get the sum of the next numberOfBytes worth of data
*
* @param numberOfBytes
* @return
*/
private long getSum(int numberOfBytes) {
int start = buff.position();
int end = start + numberOfBytes;
long rval = 0;
for (int i = start; i < end; ++i) {
rval += UnsignedNumbers.ubyteToShort(buff.get(i));
}
return rval;
}
/**
* @see ByteBuffer#get()
* @return
*/
public byte get() {
byte rval = buff.get();
short unsignedRval = UnsignedNumbers.ubyteToShort(rval);
totalSum += unsignedRval;
packetSum += unsignedRval;
return rval;
}
/**
* @see ByteBuffer#getShort()
* @return
*/
public short getShort() {
long sum = getSum(SHORT_SIZE);
totalSum += sum;
packetSum += sum;
return buff.getShort();
}
/**
* @see ByteBuffer#getInt()
* @return
*/
public int getInt() {
long sum = getSum(INT_SIZE);
totalSum += sum;
packetSum += sum;
return buff.getInt();
}
/**
* @see ByteBuffer#getLong()
* @return
*/
public long getLong() {
long sum = getSum(LONG_SIZE);
totalSum += sum;
packetSum += sum;
return buff.getLong();
}
/**
* reset the current packet sum to zero
*/
public void resetPacketSum() {
packetSum = 0;
}
/**
* reset all sums to zero
*/
public void resetAllSums() {
resetPacketSum();
totalSum = 0;
}
/**
* @return the totalSum
*/
public long getTotalSum() {
return totalSum;
}
/**
* @return the packetSum
*/
public long getPacketSum() {
return packetSum;
}
/**
* @see ByteBuffer#limit()
* @return
*/
public int size() {
return buff.limit();
}
/**
* @see ByteBuffer#position()
* @return
*/
public int position() {
return buff.position();
}
}

View file

@ -0,0 +1,348 @@
/**
* 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.total;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import com.raytheon.edex.esb.Headers;
import com.raytheon.edex.exception.DecoderException;
import com.raytheon.edex.plugin.binlightning.BinLightningDecoder;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
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.LightningPulsePoint;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgPulseType;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
import com.raytheon.uf.common.numeric.UnsignedNumbers;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.wmo.WMOHeader;
/**
* Decoder for Earth Networks Total Lightning data
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 30, 2014 3226 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class TotalLightningDecoder {
// flash types
public static final byte CLOUD_TO_GROUND_TYPE = 0x00;
public static final byte CLOUD_TO_CLOUD_TYPE = 0x01;
// pulse types
public static final byte RETURN_STROKE_TYPE = 0x00;
public static final byte NON_RETURN_STROKE_TYPE = 0x01;
public static final byte KEEP_ALIVE_TYPE = 0x09;
// conversions
public static final double LONLAT_SCALE_FACTOR = 0.0000001;
public static final double AMPS_PER_KILO_AMP = 1000.0;
public static final double METERS_PER_KILOMETER = 1000.0;
// constant metadata
public static final String DATA_SOURCE = "ENTLN";
private static final IUFStatusHandler log = UFStatus
.getHandler(TotalLightningDecoder.class);
/**
* Parse total lightning data into BinLightningRecords
*
* @param data
* @param headers
* @return
*/
public PluginDataObject[] decode(byte[] data, Headers headers) {
PluginDataObject[] rval;
WMOHeader wmoHdr = new WMOHeader(data);
String fileName = (String) headers.get(WMOHeader.INGEST_FILE_NAME);
if (wmoHdr.isValid()) {
byte[] pdata = BinLightningDecoder.extractPData(wmoHdr, data);
if (pdata != null) {
try {
rval = decodeInternal(fileName, pdata);
} catch (Exception e) {
error(e, headers, wmoHdr);
rval = new PluginDataObject[0];
}
} else {
warn("Unable to separate data from headers", fileName, wmoHdr);
rval = new PluginDataObject[0];
}
} else {
warn("Invalid WMO header", fileName, wmoHdr);
rval = new PluginDataObject[0];
}
return rval;
}
/**
* Display warning message with file and header names
*
* @param msg
* @param fileName
* @param wmoHdr
*/
private void warn(String msg, String fileName, WMOHeader wmoHdr) {
log.warn(msg + ". File: " + fileName + ", WMO Header: " + wmoHdr);
}
/**
* Display error message with file and header names
*
* @param e
* @param headers
* @param wmoHdr
*/
private void error(Exception e, Headers headers, WMOHeader wmoHdr) {
String fileName = (String) headers.get(WMOHeader.INGEST_FILE_NAME);
log.error(e.getLocalizedMessage() + ". File: " + fileName
+ ", WMO Header: " + wmoHdr, e);
}
/**
* @param fileName
* @param pdata
* data after WMO header is removed
* @return
* @throws DecoderException
*/
private PluginDataObject[] decodeInternal(String fileName, byte[] pdata)
throws DecoderException {
List<LightningStrikePoint> decodeStrikes = decodeStrikes(fileName,
pdata);
BinLightningRecord record = new BinLightningRecord(decodeStrikes);
return new PluginDataObject[] { record };
}
/**
* Extract strike data from raw binary
*
* @param fileName
* @param pdata
* @return
* @throws DecoderException
*/
private List<LightningStrikePoint> decodeStrikes(String fileName,
byte[] pdata) throws DecoderException {
List<LightningStrikePoint> rval = new ArrayList<LightningStrikePoint>();
ChecksumByteBuffer buff = new ChecksumByteBuffer(pdata);
while (buff.position() < buff.size()) {
int totalBytes = UnsignedNumbers.ushortToInt(buff.getShort());
if (totalBytes > (buff.size() - buff.position())) {
log.error("Truncated total lightning packet in file: "
+ fileName);
break;
}
/* start flash packet */
buff.resetPacketSum();
/* discard flash packet size byte */
buff.get();
LtgStrikeType flashType = getStrikeType(buff.get());
LightningStrikePoint strike = new LightningStrikePoint(null,
LtgMsgType.TOTAL_LIGHTNING);
strike.setLightSource(DATA_SOURCE);
strike.setType(flashType);
decodeCommonFields(strike, buff);
int pulseCount = UnsignedNumbers.ubyteToShort(buff.get());
strike.setPulseCount(pulseCount);
checkSum(buff, false);
List<LightningPulsePoint> pulses = new ArrayList<LightningPulsePoint>(
pulseCount);
for (int i = 0; i < pulseCount; ++i) {
/* discard size of pulse packet (always 26) */
buff.get();
LtgPulseType pulseType = getPulseType(buff.get());
LightningPulsePoint pulse = new LightningPulsePoint(null,
pulseType);
decodeCommonFields(pulse, buff);
/* discard pulse count (already set in strike) */
buff.get();
checkSum(buff, false);
pulses.add(pulse);
}
strike.setPulses(pulses);
checkSum(buff, true);
rval.add(strike);
}
return rval;
}
/**
* Extract fields common to both strikes and pulses
*
* @param point
* @param buff
*/
private static void decodeCommonFields(BaseLightningPoint point,
ChecksumByteBuffer buff) {
point.setTime(getTime(buff));
point.setLatitude(getDouble(buff, LONLAT_SCALE_FACTOR));
point.setLongitude(getDouble(buff, LONLAT_SCALE_FACTOR));
point.setStrikeStrength(getKiloAmps(buff.getInt()));
/* discard reserved byte */
buff.get();
point.setElevation(getMeters(buff.getShort()));
point.setSensorCount(UnsignedNumbers.ubyteToShort(buff.get()));
}
/**
* Create calendar from 4 byte UNIX time and 2 byte millisecond addition
*
* @param buff
* @return
*/
private static Calendar getTime(ChecksumByteBuffer buff) {
long unixTime = UnsignedNumbers.uintToLong(buff.getInt());
int additionalMillis = UnsignedNumbers.ushortToInt(buff.getShort());
long totalMillis = (unixTime * TimeUtil.MILLIS_PER_SECOND)
+ additionalMillis;
return TimeUtil.newGmtCalendar(new Date(totalMillis));
}
/**
* Ensure data integrity, resets appropriate sum(s) in buffer after check
*
* @param buff
* @param total
* true if total sum should be checked, otherwise checks packet
* sum
* @throws DecoderException
* if check fails
*/
private static void checkSum(ChecksumByteBuffer buff, boolean total)
throws DecoderException {
long rawsum = total ? buff.getTotalSum() : buff.getPacketSum();
/* convert to overflowed unsigned byte */
rawsum &= 0xFF;
/* checksum algorithm from total lightning spec */
long mungedSum = (256 - rawsum) & 0xFF;
/* get expected after sum so it is not reflected in sum */
long expected = UnsignedNumbers.ubyteToShort(buff.get());
if (mungedSum != expected) {
throw new DecoderException("Checksum failed: expected " + expected
+ " got " + mungedSum);
}
if (total) {
buff.resetAllSums();
} else {
buff.resetPacketSum();
}
}
/**
* Get scaled double from 4 byte integer field
*
* @param buff
* @param scaleFactor
* @return
*/
private static double getDouble(ChecksumByteBuffer buff, double scaleFactor) {
int raw = buff.getInt();
return raw * scaleFactor;
}
/**
* Convert amps to kiloamps
*
* @param amps
* @return
*/
private static double getKiloAmps(int amps) {
return amps / AMPS_PER_KILO_AMP;
}
/**
* Convert kilometers to meters
*
* @param kilometers
* @return
*/
private static double getMeters(short kilometers) {
return kilometers * METERS_PER_KILOMETER;
}
/**
* Map strike byte to internal enum
*
* @param type
* @return
* @throws DecoderException
*/
public static LtgStrikeType getStrikeType(byte type)
throws DecoderException {
switch (type) {
case CLOUD_TO_GROUND_TYPE:
return LtgStrikeType.CLOUD_TO_GROUND;
case CLOUD_TO_CLOUD_TYPE:
return LtgStrikeType.CLOUD_TO_CLOUD;
case KEEP_ALIVE_TYPE:
return LtgStrikeType.KEEP_ALIVE;
}
throw new DecoderException("Unknown flash type: " + type);
}
/**
* Map pulse byte to internal enum
*
* @param type
* @return
* @throws DecoderException
*/
public static LtgPulseType getPulseType(byte type) throws DecoderException {
switch (type) {
case RETURN_STROKE_TYPE:
return LtgPulseType.RETURN_STROKE;
case NON_RETURN_STROKE_TYPE:
return LtgPulseType.NON_RETURN_STROKE;
case KEEP_ALIVE_TYPE:
return LtgPulseType.KEEP_ALIVE;
}
throw new DecoderException("Unknown pulse type: " + type);
}
}

View file

@ -20,5 +20,5 @@
--> -->
<requestPatterns xmlns:ns2="group"> <requestPatterns xmlns:ns2="group">
<regex>^SFUS41 KWBC.*</regex> <regex>^SFUS41 KWBC.*</regex>
<regex>^SFPA41 KWBC.*</regex> <regex>^SFPA4[12] KWBC.*</regex>
</requestPatterns> </requestPatterns>

View file

@ -29,11 +29,7 @@ import com.raytheon.edex.plugin.textlightning.impl.TextLightningParser;
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.LightningStrikePoint; import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.edex.decodertools.time.TimeTools;
/** /**
* Decoder for text lightning data * Decoder for text lightning data
@ -47,6 +43,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
* Mar 25, 2010 jsanchez Initial creation * Mar 25, 2010 jsanchez Initial creation
* 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
* *
* </pre> * </pre>
* *
@ -57,9 +54,6 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
public class TextLightningDecoder extends AbstractDecoder implements public class TextLightningDecoder extends AbstractDecoder implements
IBinaryDecoder { IBinaryDecoder {
private static final IUFStatusHandler logger = UFStatus
.getHandler(TextLightningDecoder.class);
private String traceId = null; private String traceId = null;
/** /**
@ -92,37 +86,19 @@ public class TextLightningDecoder extends AbstractDecoder implements
BinLightningRecord report = null; BinLightningRecord report = null;
if (strikes.size() > 0) { if (strikes.size() > 0) {
report = new BinLightningRecord(strikes.size()); report = new BinLightningRecord(strikes);
for (LightningStrikePoint strike : strikes) {
report.addStrike(strike);
logger.debug(traceId + "-" + strike);
}
} else { } else {
return new PluginDataObject[0]; return new PluginDataObject[0];
} }
Calendar c = TimeTools.getSystemCalendar(); Calendar c = TimeUtil.newGmtCalendar();
if (c == null) {
throw new DecoderException(traceId + "-Error decoding times");
}
report.setInsertTime(c); report.setInsertTime(c);
Calendar cStart = report.getStartTime(); report.setTraceId(traceId);
Calendar cStop = report.getStopTime();
TimeRange range = new TimeRange(cStart.getTimeInMillis(), // TODO anyone have any idea what the source should actually be
cStop.getTimeInMillis()); // named?
report.setSource("text");
DataTime dataTime = new DataTime(cStart, range);
report.setDataTime(dataTime);
if (report != null) {
report.setTraceId(traceId);
// TODO anyone have any idea what the source should actually be
// named?
report.setSource("text");
}
return new PluginDataObject[] { report }; return new PluginDataObject[] { report };
} }

View file

@ -50,6 +50,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
* lgtng intensities -999 to * lgtng intensities -999 to
* 999 * 999
* Feb 12, 2014 2655 njensen Use status handler for logging * Feb 12, 2014 2655 njensen Use status handler for logging
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
* *
* </pre> * </pre>
* *
@ -177,7 +178,7 @@ public class TextLightningParser {
Double.parseDouble(latitude), Double.parseDouble(latitude),
Double.parseDouble(longitude)); Double.parseDouble(longitude));
strike.setStrikeStrength(Double.parseDouble(strength)); strike.setStrikeStrength(Double.parseDouble(strength));
strike.setStrikeCount(Integer.parseInt(count)); strike.setPulseCount(Integer.parseInt(count));
strike.setMonth(Integer.parseInt(month)); strike.setMonth(Integer.parseInt(month));
strike.setDay(Integer.parseInt(day)); strike.setDay(Integer.parseInt(day));
strike.setYear(Integer.parseInt(year)); strike.setYear(Integer.parseInt(year));
@ -186,7 +187,7 @@ public class TextLightningParser {
strike.setSecond(Integer.parseInt(sec)); strike.setSecond(Integer.parseInt(sec));
strike.setMillis(0); strike.setMillis(0);
strike.setMsgType(LtgMsgType.STRIKE_MSG_FL); strike.setMsgType(LtgMsgType.STRIKE_MSG_FL);
strike.setType(LtgStrikeType.STRIKE_CG); strike.setType(LtgStrikeType.CLOUD_TO_GROUND);
strike.setLightSource("UNKN"); strike.setLightSource("UNKN");
reports.add(strike); reports.add(strike);
} else { } else {
@ -214,7 +215,7 @@ public class TextLightningParser {
Double.parseDouble(latitude), lon); Double.parseDouble(latitude), lon);
strike.setStrikeStrength(Double strike.setStrikeStrength(Double
.parseDouble(strength)); .parseDouble(strength));
strike.setStrikeCount(Integer.parseInt(count)); strike.setPulseCount(Integer.parseInt(count));
strike.setMonth(Integer.parseInt(month)); strike.setMonth(Integer.parseInt(month));
strike.setDay(Integer.parseInt(day)); strike.setDay(Integer.parseInt(day));
strike.setYear(Integer.parseInt(year) + 2000); strike.setYear(Integer.parseInt(year) + 2000);
@ -223,7 +224,7 @@ public class TextLightningParser {
strike.setSecond(Integer.parseInt(sec)); strike.setSecond(Integer.parseInt(sec));
strike.setMillis(Integer.parseInt(msec) * 10); strike.setMillis(Integer.parseInt(msec) * 10);
strike.setMsgType(LtgMsgType.STRIKE_MSG_FL); strike.setMsgType(LtgMsgType.STRIKE_MSG_FL);
strike.setType(LtgStrikeType.STRIKE_CG); strike.setType(LtgStrikeType.CLOUD_TO_GROUND);
strike.setLightSource("UNKN"); strike.setLightSource("UNKN");
reports.add(strike); reports.add(strike);
} else { } else {
@ -250,7 +251,7 @@ public class TextLightningParser {
Double.parseDouble(longitude)); Double.parseDouble(longitude));
strike.setStrikeStrength(Double strike.setStrikeStrength(Double
.parseDouble(strength)); .parseDouble(strength));
strike.setStrikeCount(Integer.parseInt(count)); strike.setPulseCount(Integer.parseInt(count));
strike.setMonth(Integer.parseInt(month)); strike.setMonth(Integer.parseInt(month));
strike.setDay(Integer.parseInt(day)); strike.setDay(Integer.parseInt(day));
strike.setYear(Integer.parseInt(year)); strike.setYear(Integer.parseInt(year));
@ -259,7 +260,7 @@ public class TextLightningParser {
strike.setSecond(Integer.parseInt(sec)); strike.setSecond(Integer.parseInt(sec));
strike.setMillis(Integer.parseInt(msec) * 10); strike.setMillis(Integer.parseInt(msec) * 10);
strike.setMsgType(LtgMsgType.STRIKE_MSG_FL); strike.setMsgType(LtgMsgType.STRIKE_MSG_FL);
strike.setType(LtgStrikeType.STRIKE_CG); strike.setType(LtgStrikeType.CLOUD_TO_GROUND);
strike.setLightSource(sls); strike.setLightSource(sls);
reports.add(strike); reports.add(strike);
} else { } else {

View file

@ -19,8 +19,13 @@
**/ **/
package com.raytheon.uf.common.dataplugin.binlightning; package com.raytheon.uf.common.dataplugin.binlightning;
import java.io.FileNotFoundException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.persistence.Access; import javax.persistence.Access;
import javax.persistence.AccessType; import javax.persistence.AccessType;
@ -35,18 +40,17 @@ import org.hibernate.annotations.Index;
import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.dataplugin.annotations.DataURI;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningPulsePoint;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint; import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
import com.raytheon.uf.common.dataplugin.persist.IPersistable; import com.raytheon.uf.common.dataplugin.persist.IPersistable;
import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject; import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject;
import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.IDataStore;
import com.raytheon.uf.common.datastorage.StorageException; import com.raytheon.uf.common.datastorage.StorageException;
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord; import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.datastorage.records.IntegerDataRecord;
import com.raytheon.uf.common.datastorage.records.LongDataRecord;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtil;
/** /**
@ -82,6 +86,8 @@ import com.raytheon.uf.common.time.util.TimeUtil;
* Oct 22, 2013 2361 njensen Removed XML annotations * Oct 22, 2013 2361 njensen Removed XML annotations
* Jan 21, 2014 2667 bclement renamed record's lightSource field to source * Jan 21, 2014 2667 bclement renamed record's lightSource field to source
* 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
* replaced addStrike() with List constructor, added pulses
* *
* </pre> * </pre>
* *
@ -106,43 +112,12 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
public static final String PLUGIN_NAME = "binlightning"; public static final String PLUGIN_NAME = "binlightning";
// Data store data items
@Transient @Transient
private long[] obsTimes = null; private final Map<String, Object> strikeDataArrays = new TreeMap<String, Object>();
@Transient @Transient
private float[] latitudes = null; private final Map<String, Object> pulseDataArrays = new TreeMap<String, Object>();
@Transient
private float[] longitudes = null;
@Transient
private int[] intensities = null;
@Transient
private byte[] msgTypes = null;
@Transient
private byte[] strikeTypes = null;
@Transient
private byte[] strikeCounts = null;
@Transient
private Object[] dataArrays = null;
// Data store data item names
@Transient
private final String[] dataNames = { "obsTime", "latitude", "longitude",
"intensity", "msgType", "strikeType", "strikeCount", };
@Transient
private int insertIndex = 0;
@Transient
private long startTimeMillis = Long.MAX_VALUE;
@Transient
private long stopTimeMillis = Long.MIN_VALUE;
// Persisted value - Earliest strike time in the collection. // Persisted value - Earliest strike time in the collection.
@DataURI(position = 1) @DataURI(position = 1)
@ -177,63 +152,148 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
* *
* @param uri * @param uri
* The dataURI * The dataURI
* @param tableDef
* The table definition associated with this class
*/ */
public BinLightningRecord(String uri) { public BinLightningRecord(String uri) {
super(uri); super(uri);
} }
/** /**
* Construct an empty lightning record. * Construct a lightning record from a list of strikes
*
* @param strikes
*/ */
public BinLightningRecord(int arraysSize) { public BinLightningRecord(final List<LightningStrikePoint> strikes) {
obsTimes = new long[arraysSize]; final int arraysSize = strikes.size();
latitudes = new float[arraysSize]; long[] obsTimes = new long[arraysSize];
longitudes = new float[arraysSize]; float[] latitudes = new float[arraysSize];
float[] longitudes = new float[arraysSize];
int[] intensities = new int[arraysSize];
byte[] msgTypes = new byte[arraysSize];
byte[] strikeTypes = new byte[arraysSize];
byte[] pulseCounts = new byte[arraysSize];
int[] pulseIndexes = new int[arraysSize];
int[] heights = new int[arraysSize];
int[] sensorCounts = new int[arraysSize];
intensities = new int[arraysSize]; strikeDataArrays.put(LightningConstants.TIME_DATASET, obsTimes);
msgTypes = new byte[arraysSize]; strikeDataArrays.put(LightningConstants.LAT_DATASET, latitudes);
strikeTypes = new byte[arraysSize]; strikeDataArrays.put(LightningConstants.LON_DATASET, longitudes);
strikeCounts = new byte[arraysSize]; strikeDataArrays.put(LightningConstants.INTENSITY_DATASET, intensities);
dataArrays = new Object[] { obsTimes, latitudes, longitudes, strikeDataArrays.put(LightningConstants.MSG_TYPE_DATASET, msgTypes);
intensities, msgTypes, strikeTypes, strikeCounts, }; strikeDataArrays.put(LightningConstants.STRIKE_TYPE_DATASET,
insertIndex = 0; strikeTypes);
strikeDataArrays
.put(LightningConstants.PULSE_COUNT_DATSET, pulseCounts);
strikeDataArrays.put(LightningConstants.PULSE_INDEX_DATASET,
pulseIndexes);
strikeDataArrays.put(LightningConstants.HEIGHT_DATASET, heights);
strikeDataArrays.put(LightningConstants.SENSOR_COUNT_DATASET,
sensorCounts);
if (arraysSize > 0) {
LightningStrikePoint sample = strikes.get(0);
setDataSource(sample);
}
long startTimeMillis = Long.MAX_VALUE;
long stopTimeMillis = Long.MIN_VALUE;
int pulseDataCount = 0;
final Iterator<LightningStrikePoint> iter = strikes.iterator();
for (int i = 0; i < arraysSize; ++i) {
LightningStrikePoint strike = iter.next();
Calendar c = strike.getTime();
long obsTimeMillis = c.getTimeInMillis();
startTimeMillis = Math.min(startTimeMillis, obsTimeMillis);
stopTimeMillis = Math.max(stopTimeMillis, obsTimeMillis);
obsTimes[i] = obsTimeMillis;
latitudes[i] = (float) strike.getLatitude();
longitudes[i] = (float) strike.getLongitude();
intensities[i] = (int) Math.round(strike.getStrikeStrength());
msgTypes[i] = (byte) strike.getMsgType().getId();
strikeTypes[i] = (byte) strike.getType().getId();
/* some types have pulse counts but no pulse data */
pulseCounts[i] = (byte) strike.getPulseCount();
heights[i] = (int) Math.round(strike.getElevation());
sensorCounts[i] = strike.getSensorCount();
List<LightningPulsePoint> pulses = strike.getPulses();
if (pulses != null && !pulses.isEmpty()) {
pulseIndexes[i] = pulseDataCount;
pulseDataCount += pulses.size();
if (pulseCounts[i] != pulses.size()) {
pulseCounts[i] = (byte) pulses.size();
}
}
}
if (pulseDataCount > 0) {
/* at least one of the strikes had pulse data */
setPulseData(strikes, pulseDataCount);
}
startTime = TimeUtil.newGmtCalendar(new Date(startTimeMillis));
stopTime = TimeUtil.newGmtCalendar(new Date(stopTimeMillis));
TimeRange range = new TimeRange(startTime, stopTime);
setDataTime(new DataTime(startTime, range));
} }
// /**
// * Construct an empty lightning record.
// *
// * @param message
// * Lightning data report.
// */
// public BinLightningRecord(String message) {
// super(message);
// }
/** /**
* Track the current persistence time for the data set. * @param strikes
* @param pulseDataCount
* total number of pulses for all strikes
*/ */
@SuppressWarnings("unused") private void setPulseData(final List<LightningStrikePoint> strikes,
private void updatePersistenceTime() { final int pulseDataCount) {
if ((startTimeMillis != Long.MAX_VALUE) long[] pulseTimes = new long[pulseDataCount];
&& (stopTimeMillis != Long.MIN_VALUE)) { float[] pulseLats = new float[pulseDataCount];
persistTime = (startTimeMillis + stopTimeMillis) / 2; float[] pulseLons = new float[pulseDataCount];
setPersistenceTime(new Date(persistTime)); int[] pulseIntensities = new int[pulseDataCount];
} else { byte[] pulseTypes = new byte[pulseDataCount];
setPersistenceTime(TimeUtil.newGmtCalendar().getTime()); int[] pulseHeights = new int[pulseDataCount];
persistTime = getInsertTime().getTimeInMillis(); int[] pulseSensorCounts = new int[pulseDataCount];
pulseDataArrays.put(LightningConstants.TIME_DATASET, pulseTimes);
pulseDataArrays.put(LightningConstants.LAT_DATASET, pulseLats);
pulseDataArrays.put(LightningConstants.LON_DATASET, pulseLons);
pulseDataArrays.put(LightningConstants.INTENSITY_DATASET,
pulseIntensities);
pulseDataArrays.put(LightningConstants.PULSE_TYPE_DATASET, pulseTypes);
pulseDataArrays.put(LightningConstants.HEIGHT_DATASET, pulseHeights);
pulseDataArrays.put(LightningConstants.SENSOR_COUNT_DATASET,
pulseSensorCounts);
int index = 0;
for (LightningStrikePoint strike : strikes) {
List<LightningPulsePoint> pulses = strike.getPulses();
if (pulses != null && !pulses.isEmpty()) {
for (LightningPulsePoint pulse : pulses) {
pulseTimes[index] = pulse.getTime().getTimeInMillis();
pulseLats[index] = (float) pulse.getLatitude();
pulseLons[index] = (float) pulse.getLongitude();
pulseIntensities[index] = (int) Math.round(pulse
.getStrikeStrength());
pulseTypes[index] = pulse.getType().getId();
pulseHeights[index] = (int) Math
.round(pulse.getElevation());
pulseSensorCounts[index] = pulse.getSensorCount();
++index;
}
}
} }
} }
/** /**
* Add a strike report to the record collection. * Extract data source from strike
* *
* @param strike * @param strike
* A strike report to add.
*/ */
public void addStrike(LightningStrikePoint strike) { private void setDataSource(LightningStrikePoint strike) {
// jjg add
if (source == null) { if (source == null) {
if (strike.getLightSource() == null) { if (strike.getLightSource() == null) {
source = "NLDN"; source = "NLDN";
@ -249,47 +309,6 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
source = "UNKN"; source = "UNKN";
} }
} }
// end
if (insertIndex < obsTimes.length) {
long t1 = startTimeMillis;
Calendar c = TimeUtil.newGmtCalendar(strike.getYear(),
strike.getMonth(), strike.getDay());
c.set(Calendar.HOUR_OF_DAY, strike.getHour());
c.set(Calendar.MINUTE, strike.getMinute());
c.set(Calendar.SECOND, strike.getSecond());
c.set(Calendar.MILLISECOND, strike.getMillis());
long obsTimeMillis = c.getTimeInMillis();
startTimeMillis = Math.min(startTimeMillis, obsTimeMillis);
stopTimeMillis = Math.max(stopTimeMillis, obsTimeMillis);
obsTimes[insertIndex] = obsTimeMillis;
latitudes[insertIndex] = (float) strike.getLatitude();
longitudes[insertIndex] = (float) strike.getLongitude();
intensities[insertIndex] = Math.round((float) strike
.getStrikeStrength());
msgTypes[insertIndex] = (byte) strike.getMsgType().ordinal();
strikeTypes[insertIndex] = (byte) strike.getType().ordinal();
strikeCounts[insertIndex] = (byte) strike.getStrikeCount();
insertIndex++;
// only update the times if they have changed!
if (t1 != startTimeMillis) {
startTime = TimeUtil.newGmtCalendar(new Date(startTimeMillis));
}
if (t1 != stopTimeMillis) {
stopTime = TimeUtil.newGmtCalendar(new Date(stopTimeMillis));
}
// updatePersistenceTime();
} else {
throw new ArrayIndexOutOfBoundsException(String.format(
"index greater than length [%d]", insertIndex));
}
} }
/** /**
@ -349,25 +368,14 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
setInsertTime(insert_time); setInsertTime(insert_time);
} }
public String[] getDataNames() {
return dataNames;
}
public Object[] getDataArrays() {
return dataArrays;
}
public void setDataArrays(Object[] dataArrays) {
this.dataArrays = dataArrays;
}
/** /**
* gets the obsTimes * gets the obsTimes
* *
* @return * @return
*/ */
public long[] getObsTimes() { public long[] getObsTimes() {
return obsTimes; Object obj = strikeDataArrays.get(LightningConstants.TIME_DATASET);
return obj != null ? (long[]) obj : new long[0];
} }
/** /**
@ -376,7 +384,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
* @return * @return
*/ */
public float[] getLatitudes() { public float[] getLatitudes() {
return latitudes; Object obj = strikeDataArrays.get(LightningConstants.LAT_DATASET);
return obj != null ? (float[]) obj : new float[0];
} }
/** /**
@ -385,7 +394,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
* @return * @return
*/ */
public float[] getLongitudes() { public float[] getLongitudes() {
return longitudes; Object obj = strikeDataArrays.get(LightningConstants.LON_DATASET);
return obj != null ? (float[]) obj : new float[0];
} }
/** /**
@ -394,7 +404,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
* @return * @return
*/ */
public int[] getIntensities() { public int[] getIntensities() {
return intensities; Object obj = strikeDataArrays.get(LightningConstants.INTENSITY_DATASET);
return obj != null ? (int[]) obj : new int[0];
} }
/** /**
@ -403,7 +414,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
* @return * @return
*/ */
public byte[] getMsgTypes() { public byte[] getMsgTypes() {
return msgTypes; Object obj = strikeDataArrays.get(LightningConstants.MSG_TYPE_DATASET);
return obj != null ? (byte[]) obj : new byte[0];
} }
/** /**
@ -412,7 +424,9 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
* @return * @return
*/ */
public byte[] getStrikeTypes() { public byte[] getStrikeTypes() {
return strikeTypes; Object obj = strikeDataArrays
.get(LightningConstants.STRIKE_TYPE_DATASET);
return obj != null ? (byte[]) obj : new byte[0];
} }
/** /**
@ -420,8 +434,10 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
* *
* @return * @return
*/ */
public byte[] getStrikeCounts() { public byte[] getPulseCounts() {
return strikeCounts; Object obj = strikeDataArrays
.get(LightningConstants.PULSE_COUNT_DATSET);
return obj != null ? (byte[]) obj : new byte[0];
} }
/** /**
@ -449,42 +465,55 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
*/ */
public void retrieveFromDataStore(IDataStore dataStore) public void retrieveFromDataStore(IDataStore dataStore)
throws StorageException { throws StorageException {
retrieveFromDataStore(dataStore, false);
}
/**
* Sets the data arrays from the store.
*
* @param dataStore
* @param includePulses
* extract pulse data if true
*/
public void retrieveFromDataStore(IDataStore dataStore,
boolean includePulses) throws StorageException {
try { try {
IDataRecord[] dataRec = dataStore.retrieve(getDataURI()); IDataRecord[] dataRecs = dataStore.retrieve(getDataURI());
dataArrays = new Object[dataRec.length]; for (IDataRecord record : dataRecs) {
for (int i = 0; i < dataRec.length; i++) { strikeDataArrays.put(record.getName(), record.getDataObject());
if (dataRec[i].getName().equals("obsTime")) { }
obsTimes = ((LongDataRecord) dataRec[i]).getLongData(); if (includePulses) {
dataArrays[i] = obsTimes; String pulseGroup = getDataURI() + DataURI.SEPARATOR
} + LightningConstants.PULSE_HDF5_GROUP_SUFFIX;
if (dataRec[i].getName().equals("latitude")) { try {
latitudes = ((FloatDataRecord) dataRec[i]).getFloatData(); IDataRecord[] pulseRecords = dataStore.retrieve(pulseGroup);
dataArrays[i] = latitudes; for (IDataRecord record : pulseRecords) {
} else if (dataRec[i].getName().equals("longitude")) { pulseDataArrays.put(record.getName(),
longitudes = ((FloatDataRecord) dataRec[i]).getFloatData(); record.getDataObject());
dataArrays[i] = longitudes; }
} else if (dataRec[i].getName().equals("intensity")) { } catch (Exception e) {
intensities = ((IntegerDataRecord) dataRec[i]).getIntData(); /* FIXME better way to find out if group doesn't exist */
dataArrays[i] = intensities;
} else if (dataRec[i].getName().equals("msgType")) {
msgTypes = ((ByteDataRecord) dataRec[i]).getByteData();
dataArrays[i] = msgTypes;
} else if (dataRec[i].getName().equals("strikeType")) {
strikeTypes = ((ByteDataRecord) dataRec[i]).getByteData();
dataArrays[i] = strikeTypes;
} else if (dataRec[i].getName().equals("strikeCount")) {
strikeCounts = ((ByteDataRecord) dataRec[i]).getByteData();
dataArrays[i] = strikeCounts;
} }
} }
setDataArrays(dataArrays); } catch (FileNotFoundException e) {
throw new StorageException(e.getLocalizedMessage(), null, e);
} catch (Exception se) {
se.printStackTrace();
} }
} }
/**
* @return the strikeDataArrays
*/
public Map<String, Object> getStrikeDataArrays() {
return strikeDataArrays;
}
/**
* @return the pulseDataArrays
*/
public Map<String, Object> getPulseDataArrays() {
return pulseDataArrays;
}
@Override @Override
@Column @Column
@Access(AccessType.PROPERTY) @Access(AccessType.PROPERTY)

View file

@ -0,0 +1,66 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.binlightning;
/**
* Constants used for lightning data such as dataset names in HDF5
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* May 30, 2014 3226 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class LightningConstants {
public static final String PULSE_HDF5_GROUP_SUFFIX = "pulse";
// HDF5 dataset names
public static final String TIME_DATASET = "obsTime";
public static final String LAT_DATASET = "latitude";
public static final String LON_DATASET = "longitude";
public static final String INTENSITY_DATASET = "intensity";
public static final String MSG_TYPE_DATASET = "msgType";
public static final String STRIKE_TYPE_DATASET = "strikeType";
public static final String PULSE_COUNT_DATSET = "pulseCount";
public static final String PULSE_INDEX_DATASET = "pulseIndex";
public static final String PULSE_TYPE_DATASET = "pulseType";
public static final String HEIGHT_DATASET = "height";
public static final String SENSOR_COUNT_DATASET = "sensorCount";
}

View file

@ -0,0 +1,259 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.binlightning.impl;
import java.util.Calendar;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.vividsolutions.jts.geom.Coordinate;
/**
* Lightning information common to strikes and pulses
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 3, 2014 3226 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class BaseLightningPoint {
private final Coordinate point;
private Calendar time;
// Lightning strike strength and polarity
private double strikeStrength;
private int sensorCount;
/**
*
*/
public BaseLightningPoint() {
this(TimeUtil.newGmtCalendar());
}
/**
* @param time
*/
public BaseLightningPoint(Calendar time) {
this(new Coordinate(), time);
}
/**
* @param point
*/
public BaseLightningPoint(Coordinate point, Calendar time) {
this.point = point;
this.time = time;
}
/**
* @param latitude
* @param longitude
*/
public BaseLightningPoint(double latitude, double longitude, Calendar time) {
this(new Coordinate(longitude, latitude), time);
}
/**
* Set the year part of the date.
*
* @param year
* Year.
*/
public void setYear(int year) {
this.time.set(Calendar.YEAR, year);
}
/**
* Set the day of the month part of the date.
*
* @param day
* Day of month [1..12].
*/
public void setMonth(int month) {
this.time.set(Calendar.MONTH, month - 1);
}
/**
* Set the day of the month part of the date.
*
* @param day
* Day of month [1..12].
*/
public void setDay(int day) {
this.time.set(Calendar.DAY_OF_MONTH, day);
}
/**
* Set the hour part of the time.
*
* @param hour
* Hour of the day [0..23].
*/
public void setHour(int hour) {
this.time.set(Calendar.HOUR, hour);
}
/**
* Set the minute of the hour.
*
* @param minute
* The minute of the hour [0..59]
*/
public void setMinute(int minute) {
this.time.set(Calendar.MINUTE, minute);
}
/**
* Set the second of the minute.
*
* @param second
* The second of the minute [0..59]
*/
public void setSecond(int second) {
this.time.set(Calendar.SECOND, second);
}
/**
* Set the milliseconds part of the time.
*
* @param millis
* Milliseconds [0..999].
*/
public void setMillis(int millis) {
this.time.set(Calendar.MILLISECOND, millis);
}
/**
* @return the time
*/
public Calendar getTime() {
return time;
}
/**
* @param time
* the time to set
*/
public void setTime(Calendar time) {
this.time = time;
}
/**
* Get the strike strength.
*
* @return The strike strength.
*/
public double getStrikeStrength() {
return strikeStrength;
}
/**
* Set the strike strength.
*
* @return The strike strength.
*/
public void setStrikeStrength(double strikeStrength) {
this.strikeStrength = strikeStrength;
}
/**
* @return the sensorCount
*/
public int getSensorCount() {
return sensorCount;
}
/**
* @param sensorCount
* the sensorCount to set
*/
public void setSensorCount(int sensorCount) {
this.sensorCount = sensorCount;
}
/**
* Get the latitude of this point.
*
* @return The latitude.
*/
public double getLatitude() {
return point.y;
}
/**
* Set the latitude for this point.
*
* @param latitude
* The latitude.
*/
public void setLatitude(double latitude) {
this.point.y = latitude;
}
/**
* Get the longitude of this point.
*
* @return The longitude.
*/
public double getLongitude() {
return point.x;
}
/**
* Set the longitude for this point.
*
* @param longitude
* The longitude.
*/
public void setLongitude(double longitude) {
this.point.x = longitude;
}
/**
* Get the elevation of this point. No units are specified.
*
* @return The elevation of this point.
*/
public double getElevation() {
return this.point.z;
}
/**
* Set the elevation of this point. No units are specified.
*
* @param elevation
* The elevation of this point.
*/
public void setElevation(double elevation) {
this.point.z = elevation;
}
}

View file

@ -0,0 +1,67 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.binlightning.impl;
import java.util.Calendar;
/**
* Lightning pulse information
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 3, 2014 3226 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class LightningPulsePoint extends BaseLightningPoint {
private final LtgPulseType type;
public LightningPulsePoint(LtgPulseType type) {
super();
this.type = type;
}
public LightningPulsePoint(Calendar time, LtgPulseType type) {
super(time);
this.type = type;
}
public LightningPulsePoint(double latitude, double longitude,
Calendar time, LtgPulseType type) {
super(latitude, longitude, time);
this.type = type;
}
/**
* @return the type
*/
public LtgPulseType getType() {
return type;
}
}

View file

@ -19,53 +19,59 @@
**/ **/
package com.raytheon.uf.common.dataplugin.binlightning.impl; package com.raytheon.uf.common.dataplugin.binlightning.impl;
import com.raytheon.uf.edex.decodertools.core.BasePoint; import java.util.Calendar;
import java.util.List;
import com.raytheon.uf.common.time.util.TimeUtil;
/** /**
* Record implementation for the Binary Lightning data decoder. * Record implementation for the Binary Lightning data decoder.
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 20070810 379 jkorman Initial Coding from prototype. * 20070810 379 jkorman Initial Coding from prototype.
* 20130227 DCS 152 jgerth Support for WWLLN and multiple sources * 20130227 DCS 152 jgerth Support for WWLLN and multiple sources
* Jun 3, 2014 3226 bclement refactor to support pulse data
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
* @version 1.0 * @version 1.0
*/ */
public class LightningStrikePoint extends BasePoint public class LightningStrikePoint extends BaseLightningPoint
{ {
private LtgStrikeType type; private LtgStrikeType type;
private LtgMsgType msgType; private LtgMsgType msgType;
// Lightning strike strength and polarity // Number of pulses for this record.
private double strikeStrength; private int pulseCount;
// Number of strikes for this record.
private int strikeCount;
// JJG - Lightning data source // JJG - Lightning data source
private String lightSource; private String lightSource;
private List<LightningPulsePoint> pulses;
/** /**
* Construct a LightningStrikePoint using given data. * Construct a LightningStrikePoint using given data.
* @param base The base point which should contain a valid time. *
* @param latitude The latitude of the strike. * @param latitude
* @param longitude The longitude of the strike. * The latitude of the strike.
* @param type The strike message type. * @param longitude
* The longitude of the strike.
* @param time
* @param type
* The strike message type.
*/ */
public LightningStrikePoint(BasePoint base, double latitude, double longitude, LtgMsgType type) public LightningStrikePoint(double latitude, double longitude,
Calendar time, LtgMsgType type)
{ {
super(base); super(latitude, longitude, time);
setLatitude(latitude);
setLongitude(longitude);
setElevation(0); setElevation(0);
this.msgType = type; this.msgType = type;
} }
@ -77,44 +83,37 @@ public class LightningStrikePoint extends BasePoint
*/ */
public LightningStrikePoint(double latitude, double longitude) public LightningStrikePoint(double latitude, double longitude)
{ {
super(latitude,longitude); super(latitude, longitude, TimeUtil.newGmtCalendar());
setElevation(0); setElevation(0);
} }
/** /**
* Get the strike count. * @param time
* @return The strike count. * @param type
*/ */
public int getStrikeCount() public LightningStrikePoint(Calendar time, LtgMsgType type) {
{ super(time);
return strikeCount; this.msgType = type;
} }
/** /**
* Set the strike count. * Get the pulse count.
* @return The strike count. *
* @return The pulse count.
*/ */
public void setStrikeCount(int strikeCount) public int getPulseCount()
{ {
this.strikeCount = strikeCount; return pulseCount;
} }
/** /**
* Get the strike strength. * Set the pulse count.
* @return The strike strength. *
* @return The pulse count.
*/ */
public double getStrikeStrength() public void setPulseCount(int pulseCount)
{ {
return strikeStrength; this.pulseCount = pulseCount;
}
/**
* Set the strike strength.
* @return The strike strength.
*/
public void setStrikeStrength(double strikeStrength)
{
this.strikeStrength = strikeStrength;
} }
/** /**
@ -189,13 +188,22 @@ public class LightningStrikePoint extends BasePoint
{ {
buffer = new StringBuilder(); buffer = new StringBuilder();
} }
buffer.append(String.format("%4d%02d%02d",getYear(),getMonth(),getDay())); Calendar obsTime = getTime();
buffer.append(String.format("%02d%02d%02d",getHour(),getMinute(),getSecond())); int year = obsTime.get(Calendar.YEAR);
int month = obsTime.get(Calendar.MONTH) + 1;
int day = obsTime.get(Calendar.DAY_OF_MONTH);
int hour = obsTime.get(Calendar.HOUR);
int minute = obsTime.get(Calendar.MINUTE);
int second = obsTime.get(Calendar.SECOND);
int millis = obsTime.get(Calendar.MILLISECOND);
buffer.append(String.format("%4d%02d%02d", year, month, day));
buffer.append(String.format("%02d%02d%02d", hour, minute, second));
buffer.append(String.format(" %9.5f %10.5f ",getLatitude(), getLongitude() )); buffer.append(String.format(" %9.5f %10.5f ",getLatitude(), getLongitude() ));
buffer.append(String.format("%2s %2s ",msgType.getType(),type.getType())); buffer.append(String.format("%2s %2s ",msgType.getType(),type.getType()));
buffer.append(String.format("%4.0f %02d %02d", strikeStrength,(getMillis() / 100),strikeCount)); buffer.append(String.format("%4.0f %02d %02d", getStrikeStrength(),
(millis / 100), pulseCount));
return buffer; return buffer;
} }
@ -213,5 +221,20 @@ public class LightningStrikePoint extends BasePoint
{ {
return toString(null).toString(); return toString(null).toString();
} }
/**
* @return the pulses
*/
public List<LightningPulsePoint> getPulses() {
return pulses;
}
/**
* @param pulses
* the pulses to set
*/
public void setPulses(List<LightningPulsePoint> pulses) {
this.pulses = pulses;
}
} }

View file

@ -23,32 +23,51 @@ package com.raytheon.uf.common.dataplugin.binlightning.impl;
* Enums for the lightning message type, Flash or RT Flash. * Enums for the lightning message type, Flash or RT Flash.
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 20070810 379 jkorman Initial Coding from prototype. * 20070810 379 jkorman Initial Coding from prototype.
* Jun 3, 2014 3226 bclement added id, added TOTAL_LIGHTNING
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
* @version 1.0 * @version 1.0
*/ */
public enum LtgMsgType public enum LtgMsgType
{ {
STRIKE_MSG_FL("FL"), STRIKE_MSG_FL((byte) 0, "FL"), STRIKE_MSG_RT((byte) 1, "RT"), TOTAL_LIGHTNING(
STRIKE_MSG_RT("RT"); (byte) 2, "TL");
private final String strikeType; private final String msgType;
private final byte id;
/** /**
* Construct the type. * Construct the type.
* @param type Lightning strike type. *
* @param type
* Lightning message type.
*/ */
private LtgMsgType(String type) private LtgMsgType(byte id, String type)
{ {
strikeType = type; this.msgType = type;
this.id = id;
}
/**
* @param id
* @return null if no type found for id
*/
public static LtgMsgType getById(byte id) {
for (LtgMsgType type : LtgMsgType.values()) {
if (type.id == id) {
return type;
}
}
return null;
} }
/** /**
@ -57,6 +76,13 @@ public enum LtgMsgType
*/ */
public String getType() public String getType()
{ {
return strikeType; return msgType;
}
/**
* @return unique id for type
*/
public byte getId() {
return this.id;
} }
} }

View file

@ -0,0 +1,71 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.dataplugin.binlightning.impl;
/**
* Stroke type enum for lightning pulses. Mainly categorizes between return and
* non-return strokes.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 3, 2014 3226 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public enum LtgPulseType {
RETURN_STROKE((byte) 0), NON_RETURN_STROKE((byte) 1), KEEP_ALIVE((byte) 9);
private final byte id;
/**
* @param id
*/
private LtgPulseType(byte id) {
this.id = id;
}
/**
* @param id
* @return null if no type is found for id
*/
public static LtgPulseType getById(byte id) {
for (LtgPulseType type : LtgPulseType.values()) {
if (type.id == id) {
return type;
}
}
return null;
}
/**
* @return unique id for this type
*/
public byte getId() {
return this.id;
}
}

View file

@ -23,34 +23,52 @@ package com.raytheon.uf.common.dataplugin.binlightning.impl;
* Enums for the lightning strike type, cloud-to-cloud or cloud-to-ground. * Enums for the lightning strike type, cloud-to-cloud or cloud-to-ground.
* *
* <pre> * <pre>
* *
* SOFTWARE HISTORY * SOFTWARE HISTORY
* *
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 20070810 379 jkorman Initial Coding from prototype. * 20070810 379 jkorman Initial Coding from prototype.
* 20130425 DCS 112 Wufeng Zhou Added STRIKE_TF (for Total Flash) in definition for Total Flash * 20130425 DCS 112 Wufeng Zhou Added STRIKE_TF (for Total Flash) in definition for Total Flash
* Jun 3, 2014 3226 bclement added id, changed to more descriptive names, added KEEP_ALIVE
* *
* </pre> * </pre>
* *
* @author jkorman * @author jkorman
* @version 1.0 * @version 1.0
*/ */
public enum LtgStrikeType public enum LtgStrikeType
{ {
STRIKE_CC("CC"), CLOUD_TO_CLOUD((byte)0, "CC"), CLOUD_TO_GROUND((byte)1, "CG"), TOTAL_FLASH((byte)2, "TF"), KEEP_ALIVE((byte)9,
STRIKE_CG("CG"), "");
STRIKE_TF("TF");
private final String strikeType; private final String strikeType;
private final byte id;
/** /**
* Construct the type. * Construct the type.
* @param id unique id for type
* @param type Lightning strike type. * @param type Lightning strike type.
*/ */
private LtgStrikeType(String type) private LtgStrikeType(byte id, String type)
{ {
strikeType = type; this.id = id;
this.strikeType = type;
}
/**
* @param id
* unique id for type
* @return null if no type is found for id
*/
public static LtgStrikeType getById(byte id) {
for (LtgStrikeType type : LtgStrikeType.values()) {
if (type.id == id) {
return type;
}
}
return null;
} }
/** /**
@ -61,4 +79,11 @@ public enum LtgStrikeType
{ {
return strikeType; return strikeType;
} }
/**
* @return id
*/
public int getId() {
return this.id;
}
} }

View file

@ -76,6 +76,8 @@ import com.vividsolutions.jts.io.WKTWriter;
* 12/20/2013 DR 16894 gzhang Fixed getZRvalue2() bias issue. * 12/20/2013 DR 16894 gzhang Fixed getZRvalue2() bias issue.
* 05/12/2014 3133 njensen Extracted getLightningRecord * 05/12/2014 3133 njensen Extracted getLightningRecord
* 05/13/2014 3133 njensen Moved convertStrankValue here from ScanConfig * 05/13/2014 3133 njensen Moved convertStrankValue here from ScanConfig
* Jun 05, 2014 3226 bclement BinLightning refactor
* compare lightning strike type by id instead of ordinal
* </pre> * </pre>
* *
* @author dhladky * @author dhladky
@ -1292,7 +1294,7 @@ public class ScanUtils {
(double) rec.getLatitudes()[i], (double) rec.getLatitudes()[i],
(double) rec.getLongitudes()[i], (double) rec.getLongitudes()[i],
rec.getIntensities()[i], rec.getStrikeTypes()[i], rec.getIntensities()[i], rec.getStrikeTypes()[i],
rec.getMsgTypes()[i], rec.getStrikeCounts()[i]); rec.getMsgTypes()[i], rec.getPulseCounts()[i]);
strikeList.add(strike); strikeList.add(strike);
} }
@ -1311,7 +1313,7 @@ public class ScanUtils {
if (ls.getIntensity() > 0) { if (ls.getIntensity() > 0) {
totalPosStrikes++; totalPosStrikes++;
} }
if (ls.getStrikeType() == LtgStrikeType.STRIKE_CG.ordinal()) { if (ls.getStrikeType() == LtgStrikeType.CLOUD_TO_GROUND.getId()) {
totalCGStrikes++; totalCGStrikes++;
} }
totalStrikes++; totalStrikes++;

View file

@ -19,12 +19,14 @@
**/ **/
package com.raytheon.uf.edex.decodertools.core; package com.raytheon.uf.edex.decodertools.core;
import com.vividsolutions.jts.geom.Coordinate;
/** /**
* BasePoint provides a simple 4D (latitude, longitude, elevation, and time) * BasePoint provides a simple 3D (latitude, longitude, elevation) base class
* base class for observation data. Sub-classes of BasePoint are responsible for * for observation data. Sub-classes of BasePoint are responsible for adding
* adding additional checking or using specific units as required. An example * additional checking or using specific units as required. Most attributes of
* would be adding a accessors for a Calendar to expose the date information. * this class do not have units.
* Most attributes of this class do not have units.
* *
* <pre> * <pre>
* *
@ -35,11 +37,14 @@ package com.raytheon.uf.edex.decodertools.core;
* 27 July 2007 411 jkorman Initial Development * 27 July 2007 411 jkorman Initial Development
* 20070911 379 jkorman Added comments. * 20070911 379 jkorman Added comments.
* 20070912 379 jkorman Code review cleanup. * 20070912 379 jkorman Code review cleanup.
* Jun 05, 2014 3226 bclement deprecated class, removed time
* </pre> * </pre>
* *
* @deprecated use {@link Coordinate} instead
* @author jkorman * @author jkorman
* @version 1 * @version 1
*/ */
@Deprecated
public class BasePoint { public class BasePoint {
private double latitude; private double latitude;
@ -47,20 +52,6 @@ public class BasePoint {
private double elevation; private double elevation;
private int year;
private int month;
private int day;
private int hour;
private int minute;
private int second;
private int millis;
/** /**
* Create an empty basepoint instance. * Create an empty basepoint instance.
*/ */
@ -74,16 +65,9 @@ public class BasePoint {
* A basepoint to copy. * A basepoint to copy.
*/ */
public BasePoint(BasePoint point) { public BasePoint(BasePoint point) {
latitude = point.latitude; this.latitude = point.latitude;
longitude = point.longitude; this.longitude = point.longitude;
elevation = point.elevation; this.elevation = point.elevation;
year = point.year;
month = point.month;
day = point.day;
hour = point.hour;
minute = point.minute;
second = point.second;
millis = point.millis;
} }
/** /**
@ -154,136 +138,4 @@ public class BasePoint {
this.elevation = elevation; this.elevation = elevation;
} }
/**
* Get the year part of the date.
*
* @return The year.
*/
public int getYear() {
return year;
}
/**
* Set the year part of the date.
*
* @param year
* Year.
*/
public void setYear(int year) {
this.year = year;
}
/**
* Get the month part of the date.
*
* @return The month of the year.
*/
public int getMonth() {
return month;
}
/**
* Set the day of the month part of the date.
*
* @param day
* Day of month [1..12].
*/
public void setMonth(int month) {
this.month = month;
}
/**
* Get the day part of the month.
*
* @return The day of the month.
*/
public int getDay() {
return day;
}
/**
* Set the day of the month part of the date.
*
* @param day
* Day of month [1..12].
*/
public void setDay(int day) {
this.day = day;
}
/**
* Get the hours part of the day.
*
* @return The hours part of the day.
*/
public int getHour() {
return hour;
}
/**
* Set the hour part of the time.
*
* @param hour
* Hour of the day [0..23].
*/
public void setHour(int hour) {
this.hour = hour;
}
/**
* Get the minutes part of the hour.
*
* @return The minutes part of the hour.
*/
public int getMinute() {
return minute;
}
/**
* Set the minute of the hour.
*
* @param minute
* The minute of the hour [0..59]
*/
public void setMinute(int minute) {
this.minute = minute;
}
/**
* Get the seconds part of the minute.
*
* @return The seconds part of the minute.
*/
public int getSecond() {
return second;
}
/**
* Set the second of the minute.
*
* @param second
* The second of the minute [0..59]
*/
public void setSecond(int second) {
this.second = second;
}
/**
* Get the milliseconds part of the time.
*
* @return The milliseconds part of the time.
*/
public int getMillis() {
return millis;
}
/**
* Set the milliseconds part of the time.
*
* @param millis
* Milliseconds [0..999].
*/
public void setMillis(int millis) {
this.millis = millis;
}
} }

View file

@ -56,6 +56,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* Jan 10, 2013 1448 bgonzale Added app context check in runOnSchedule(). * Jan 10, 2013 1448 bgonzale Added app context check in runOnSchedule().
* Jan 18, 2013 1469 bkowal Removed the hdf5 data directory. * Jan 18, 2013 1469 bkowal Removed the hdf5 data directory.
* Mar 28, 2014 2952 mpduff Changed to use UFStatus for logging. * Mar 28, 2014 2952 mpduff Changed to use UFStatus for logging.
* Jun 05, 2014 3226 bclement BinLightning refactor
* *
* </pre> * </pre>
* *
@ -138,7 +139,7 @@ public class MpeLightningSrv {
float[] latitudes = ltngRec.getLatitudes(); float[] latitudes = ltngRec.getLatitudes();
float[] longitudes = ltngRec.getLongitudes(); float[] longitudes = ltngRec.getLongitudes();
long[] obstimes = ltngRec.getObsTimes(); long[] obstimes = ltngRec.getObsTimes();
byte[] strikes = ltngRec.getStrikeCounts(); byte[] strikes = ltngRec.getPulseCounts();
// convert latitude and longitude to grid coordinate // convert latitude and longitude to grid coordinate
HRAP hrap = HRAP.getInstance(); HRAP hrap = HRAP.getInstance();

View file

@ -58,6 +58,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* 05/07/2009 2037 dhladky Initial Creation. * 05/07/2009 2037 dhladky Initial Creation.
* Apr 30, 2014 2060 njensen Updates for removal of grid dataURI column * Apr 30, 2014 2060 njensen Updates for removal of grid dataURI column
* Jun 05, 2014 3226 bclement compare lightning strike type by id instead of ordinal
* *
* </pre> * </pre>
* *
@ -292,7 +293,7 @@ public abstract class ScanProduct implements Serializable {
rec.getIntensities()[i], rec.getIntensities()[i],
rec.getStrikeTypes()[i], rec.getStrikeTypes()[i],
rec.getMsgTypes()[i], rec.getMsgTypes()[i],
rec.getStrikeCounts()[i]); rec.getPulseCounts()[i]);
strikeList.add(strike); strikeList.add(strike);
} }
@ -310,8 +311,8 @@ public abstract class ScanProduct implements Serializable {
if (ls.getIntensity() > 0) { if (ls.getIntensity() > 0) {
totalPosStrikes++; totalPosStrikes++;
} }
if (ls.getStrikeType() == LtgStrikeType.STRIKE_CG if (ls.getStrikeType() == LtgStrikeType.CLOUD_TO_GROUND
.ordinal()) { .getId()) {
totalCGStrikes++; totalCGStrikes++;
} }
totalStrikes++; totalStrikes++;

View file

@ -3,8 +3,8 @@ package gov.noaa.nws.ncep.viz.rsc.lightning.rsc;
import gov.noaa.nws.ncep.viz.common.ui.NmapCommon; import gov.noaa.nws.ncep.viz.common.ui.NmapCommon;
import gov.noaa.nws.ncep.viz.resources.AbstractNatlCntrsResource; import gov.noaa.nws.ncep.viz.resources.AbstractNatlCntrsResource;
import gov.noaa.nws.ncep.viz.resources.INatlCntrsResource; import gov.noaa.nws.ncep.viz.resources.INatlCntrsResource;
import gov.noaa.nws.ncep.viz.resources.colorBar.ColorBarResourceData;
import gov.noaa.nws.ncep.viz.resources.colorBar.ColorBarResource; import gov.noaa.nws.ncep.viz.resources.colorBar.ColorBarResource;
import gov.noaa.nws.ncep.viz.resources.colorBar.ColorBarResourceData;
import gov.noaa.nws.ncep.viz.ui.display.ColorBar; import gov.noaa.nws.ncep.viz.ui.display.ColorBar;
import gov.noaa.nws.ncep.viz.ui.display.NCMapDescriptor; import gov.noaa.nws.ncep.viz.ui.display.NCMapDescriptor;
@ -18,6 +18,7 @@ import java.util.List;
import com.raytheon.uf.common.dataplugin.HDF5Util; import com.raytheon.uf.common.dataplugin.HDF5Util;
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.LightningConstants;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.DataStoreFactory;
import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.IDataStore;
@ -42,15 +43,14 @@ import com.raytheon.uf.viz.core.drawables.IWireframeShape;
import com.raytheon.uf.viz.core.drawables.PaintProperties; import com.raytheon.uf.viz.core.drawables.PaintProperties;
import com.raytheon.uf.viz.core.drawables.ResourcePair; import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.map.MapDescriptor;
import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.rsc.ResourceProperties; import com.raytheon.uf.viz.core.rsc.ResourceProperties;
import com.raytheon.uf.viz.core.rsc.ResourceType; import com.raytheon.uf.viz.core.rsc.ResourceType;
/** /**
* LigntningResource - Display Lightning data. * LigntningResource - Display Lightning data. *
* * *
* <pre> * <pre>
* SOFTWARE HISTORY * SOFTWARE HISTORY
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
@ -65,10 +65,11 @@ import com.raytheon.uf.viz.core.rsc.ResourceType;
* 05/23/12 785 Q. Zhou Added getName for legend. * 05/23/12 785 Q. Zhou Added getName for legend.
* 12/19/2012 #960 Greg Hull override propertiesChanged() to update colorBar. * 12/19/2012 #960 Greg Hull override propertiesChanged() to update colorBar.
* 05/07/2013 #993 Greg Hull change key for strikeMap from URI to the HDF5 group * 05/07/2013 #993 Greg Hull change key for strikeMap from URI to the HDF5 group
* * Jun 05, 2014 3226 bclement reference datarecords by LightningConstants
*
* </pre> * </pre>
* *
* @author ghull * @author ghull
* @version 1.0 * @version 1.0
*/ */
public class LightningResource extends AbstractNatlCntrsResource<LightningResourceData, NCMapDescriptor> public class LightningResource extends AbstractNatlCntrsResource<LightningResourceData, NCMapDescriptor>
@ -366,20 +367,17 @@ public class LightningResource extends AbstractNatlCntrsResource<LightningResour
for( int s=0 ; s<hdf5Rec.getSizes()[0] ; s++ ) { for( int s=0 ; s<hdf5Rec.getSizes()[0] ; s++ ) {
LtngStrikeDataObj strikeInfo = strikeList.get(s); LtngStrikeDataObj strikeInfo = strikeList.get(s);
if( hdf5Rec.getName().equals("intensity") ) { String name = hdf5Rec.getName();
if (name.equals(LightningConstants.INTENSITY_DATASET)) {
strikeInfo.intensity = ((IntegerDataRecord) hdf5Rec).getIntData()[s]; strikeInfo.intensity = ((IntegerDataRecord) hdf5Rec).getIntData()[s];
} else if( hdf5Rec.getName().equals("latitude") ) { } else if (name.equals(LightningConstants.LAT_DATASET)) {
strikeInfo.lat = ((FloatDataRecord) hdf5Rec).getFloatData()[s]; strikeInfo.lat = ((FloatDataRecord) hdf5Rec).getFloatData()[s];
} else if( hdf5Rec.getName().equals("longitude") ) { } else if (name.equals(LightningConstants.LON_DATASET)) {
strikeInfo.lon = ((FloatDataRecord) hdf5Rec).getFloatData()[s]; strikeInfo.lon = ((FloatDataRecord) hdf5Rec).getFloatData()[s];
} else if( hdf5Rec.getName().equals("obsTime") ) { } else if (name.equals(LightningConstants.TIME_DATASET)) {
strikeInfo.strikeTime = ((LongDataRecord) hdf5Rec).getLongData()[s]; strikeInfo.strikeTime = ((LongDataRecord) hdf5Rec).getLongData()[s];
// if( strikeInfo.obsTime > latestStrike ) { } else if (name
// latestStrike = strikeInfo.obsTime; .equals(LightningConstants.MSG_TYPE_DATASET)) {
// }
// } else if( hdf5Rec.getName().equals("strikeCount") ) {
// strikeInfo.lon = ((FloatDataRecord) hdf5Rec).getFloatData()[s];
} else if( hdf5Rec.getName().equals("msgType") ) {
// ignore // ignore
} }
} }

View file

@ -16,7 +16,6 @@ import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType; import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.edex.decodertools.core.BasePoint;
/** /**
* BinLigntningDecoderUtil * BinLigntningDecoderUtil
@ -38,6 +37,7 @@ import com.raytheon.uf.edex.decodertools.core.BasePoint;
* moved from com.raytheon.edex.plugin.binlightning to gov.noaa.nws.ost.edex.plugin.binlightning * moved from com.raytheon.edex.plugin.binlightning to gov.noaa.nws.ost.edex.plugin.binlightning
* moved decodeBinLightningData() and decodeBitShiftedBinLightningData() * moved decodeBinLightningData() and decodeBitShiftedBinLightningData()
* to BinLightningDecoder to solve circular dependency * to BinLightningDecoder to solve circular dependency
* Jun 05, 2014 3226 bclement LightningStrikePoint refactor
* </pre> * </pre>
* *
* @author Wufeng Zhou * @author Wufeng Zhou
@ -132,20 +132,16 @@ public class BinLightningDecoderUtil {
// int reserved = buffer.getShort() & 0xffff; // int reserved = buffer.getShort() & 0xffff;
// Create the strike record from the report info and base time information. // Create the strike record from the report info and base time information.
BasePoint base = new BasePoint(lat, lon);
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(epochTime); cal.setTimeInMillis(epochTime);
base.setYear(cal.get(Calendar.YEAR));
base.setMonth(cal.get(Calendar.MONTH) + 1);
base.setDay(cal.get(Calendar.DAY_OF_MONTH));
base.setHour(cal.get(Calendar.HOUR_OF_DAY));
base.setMinute(cal.get(Calendar.MINUTE));
base.setSecond(cal.get(Calendar.SECOND));
base.setMillis(cal.get(Calendar.MILLISECOND));
// new spec does not seem to have lightning message type indicator such as FL (Flash Lightning) or RT (Real Time flash lightning) /*
// The source of lightning data in the vendor specific data bytes (byte 16-17) may related to this (???), * new spec does not seem to have lightning message type indicator
// and it is used here for now. 04/182/013 Wufeng Zhou * such as FL (Flash Lightning) or RT (Real Time flash lightning)
* The source of lightning data in the vendor specific data bytes
* (byte 16-17) may related to this (???),
* and it is used here for now. 04/182/013 Wufeng Zhou
*/
/** 05/02/2013, found DSI-9603 Spec (http://www1.ncdc.noaa.gov/pub/data/documentlibrary/tddoc/td9603.pdf) on NLDN lightning data format, /** 05/02/2013, found DSI-9603 Spec (http://www1.ncdc.noaa.gov/pub/data/documentlibrary/tddoc/td9603.pdf) on NLDN lightning data format,
* on Message Type and Stroke Type: * on Message Type and Stroke Type:
* POS: 37-38 Message Type * POS: 37-38 Message Type
@ -165,19 +161,24 @@ public class BinLightningDecoderUtil {
msgType = LtgMsgType.STRIKE_MSG_RT; msgType = LtgMsgType.STRIKE_MSG_RT;
} }
LightningStrikePoint lsp = new LightningStrikePoint(base, lat, lon, msgType); LightningStrikePoint lsp = new LightningStrikePoint(lat, lon, cal,
LtgStrikeType ltgStrikeType = LtgStrikeType.STRIKE_CG; // default ?? msgType);
LtgStrikeType ltgStrikeType = LtgStrikeType.CLOUD_TO_GROUND; // default ??
if (strokeType == 0x0000) { if (strokeType == 0x0000) {
ltgStrikeType = LtgStrikeType.STRIKE_CG; ltgStrikeType = LtgStrikeType.CLOUD_TO_GROUND;
} else if (strokeType == 0x00ff) { } else if (strokeType == 0x00ff) {
ltgStrikeType = LtgStrikeType.STRIKE_CC; ltgStrikeType = LtgStrikeType.CLOUD_TO_CLOUD;
} else if (strokeType == 0xffff) { } else if (strokeType == 0xffff) {
ltgStrikeType = LtgStrikeType.STRIKE_TF; ltgStrikeType = LtgStrikeType.TOTAL_FLASH;
} }
lsp.setType(ltgStrikeType); lsp.setType(ltgStrikeType);
// as of OB13.3 for World Wide Lightning Location Network (WWLLN) data (decoded by textlightning though, not this bin lightning decoder), /*
// added lightning source field in LightningStrikePoint, as well as column in binlightning database table defaults to NLDN * as of OB13.3 for World Wide Lightning Location Network (WWLLN)
* data (decoded by textlightning though, not this bin lightning
* decoder), added lightning source field in LightningStrikePoint,
* as well as column in binlightning database table defaults to NLDN
*/
if (vendor == ((short)0x0001)) { // CONUS source if (vendor == ((short)0x0001)) { // CONUS source
lsp.setLightSource("NLDN"); lsp.setLightSource("NLDN");
} else if (vendor == ((short)0x0002)) { // long range source, i.e., GLD360. } else if (vendor == ((short)0x0002)) { // long range source, i.e., GLD360.
@ -185,7 +186,7 @@ public class BinLightningDecoderUtil {
lsp.setLightSource("GLD"); lsp.setLightSource("GLD");
} }
lsp.setStrikeCount(strokeMultiplicity); lsp.setPulseCount(strokeMultiplicity);
lsp.setStrikeStrength(strokeKiloAmps); lsp.setStrikeStrength(strokeKiloAmps);
// stroke duration does not seem to be used // stroke duration does not seem to be used