Omaha #4605 Lightning time matching adjustments.

Former-commit-id: 6d4763fec2896bbb59c3be8abe1d855356a0a4cd
This commit is contained in:
Ben Steffensmeier 2015-09-28 09:00:29 -05:00
parent d4de7fe1af
commit e7fa607226
13 changed files with 456 additions and 135 deletions

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Lightning Plug-in
Bundle-SymbolicName: com.raytheon.viz.lightning;singleton:=true
Bundle-Version: 1.14.1.qualifier
Bundle-Version: 1.15.0.qualifier
Bundle-Vendor: Raytheon
Require-Bundle: com.raytheon.uf.common.dataplugin.binlightning;bundle-version="1.0.0",
com.raytheon.viz.core,

View file

@ -34,6 +34,7 @@
handlingPulses="false" handlingCloudFlashes="false"
kmResolution="${resolution}">
<binOffset posOffset="0" negOffset="${negOffset}" virtualOffset="0"/>
<binRepeatCount>${binRepeatCount;1}</binRepeatCount>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />

View file

@ -34,6 +34,7 @@
handlingPulses="false" handlingCloudFlashes="true"
kmResolution="${resolution}">
<binOffset posOffset="0" negOffset="${negOffset}" virtualOffset="0"/>
<binRepeatCount>${binRepeatCount;1}</binRepeatCount>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />

View file

@ -34,6 +34,7 @@
handlingPulses="true" handlingCloudFlashes="false"
kmResolution="${resolution}">
<binOffset posOffset="0" negOffset="${negOffset}" virtualOffset="0"/>
<binRepeatCount>${binRepeatCount;1}</binRepeatCount>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />

View file

@ -34,6 +34,7 @@
handlingPulses="false" handlingCloudFlashes="true"
kmResolution="${resolution}">
<binOffset posOffset="0" negOffset="${negOffset}" virtualOffset="0"/>
<binRepeatCount>${binRepeatCount;1}</binRepeatCount>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />

View file

@ -19,72 +19,69 @@
further_licensing_information.
-->
<bundle>
<displayList>
<displays xsi:type="d2DMapRenderableDisplay" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<descriptor xsi:type="mapDescriptor">
<resource>
<loadProperties loadWithoutData="true">
</loadProperties>
<properties isSystemResource="false"
isBlinking="false" isMapLayer="false" isHoverOn="false"
isVisible="false" />
<resourceData xsi:type="lightningResourceData"
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
handlingPulses="true">
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />
</mapping>
<mapping key="source">
<constraint constraintValue="${source}" constraintType="EQUALS" />
</mapping>
</metadataMap>
</resourceData>
</resource>
<resource>
<loadProperties loadWithoutData="true">
</loadProperties>
<properties isSystemResource="false"
isBlinking="false" isMapLayer="false" isHoverOn="false"
isVisible="true" />
<resourceData xsi:type="lightningResourceData"
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
handlingPositiveStrikes="false" handlingNegativeStrikes="false"
handlingCloudFlashes="true">
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />
</mapping>
<mapping key="source">
<constraint constraintValue="${source}" constraintType="EQUALS" />
</mapping>
</metadataMap>
</resourceData>
</resource>
<resource>
<loadProperties loadWithoutData="true">
</loadProperties>
<properties isSystemResource="false"
isBlinking="false" isMapLayer="false" isHoverOn="false"
isVisible="true" />
<resourceData xsi:type="lightningResourceData"
isUpdatingOnMetadataOnly="false" isRequeryNecessaryOnTimeMatch="true"
handlingPositiveStrikes="true" handlingNegativeStrikes="true">
<binOffset posOffset="0" negOffset="300" virtualOffset="0"/>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />
</mapping>
<mapping key="source">
<constraint constraintValue="${source}" constraintType="EQUALS" />
</mapping>
</metadataMap>
</resourceData>
</resource>
</descriptor>
</displays>
</displayList>
<displayList>
<displays xsi:type="d2DMapRenderableDisplay" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<descriptor xsi:type="mapDescriptor">
<resource>
<loadProperties loadWithoutData="true">
</loadProperties>
<properties isSystemResource="false" isBlinking="false" isMapLayer="false" isHoverOn="false"
isVisible="false" />
<resourceData xsi:type="lightningResourceData" isUpdatingOnMetadataOnly="false"
isRequeryNecessaryOnTimeMatch="true" handlingPositiveStrikes="false" handlingNegativeStrikes="false"
handlingPulses="true">
<binOffset posOffset="0" negOffset="60" virtualOffset="0" />
<binRepeatCount>5</binRepeatCount>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />
</mapping>
<mapping key="source">
<constraint constraintValue="${source}" constraintType="EQUALS" />
</mapping>
</metadataMap>
</resourceData>
</resource>
<resource>
<loadProperties loadWithoutData="true">
</loadProperties>
<properties isSystemResource="false" isBlinking="false" isMapLayer="false" isHoverOn="false"
isVisible="true" />
<resourceData xsi:type="lightningResourceData" isUpdatingOnMetadataOnly="false"
isRequeryNecessaryOnTimeMatch="true" handlingPositiveStrikes="false" handlingNegativeStrikes="false"
handlingCloudFlashes="true">
<binOffset posOffset="0" negOffset="60" virtualOffset="0" />
<binRepeatCount>5</binRepeatCount>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />
</mapping>
<mapping key="source">
<constraint constraintValue="${source}" constraintType="EQUALS" />
</mapping>
</metadataMap>
</resourceData>
</resource>
<resource>
<loadProperties loadWithoutData="true">
</loadProperties>
<properties isSystemResource="false" isBlinking="false" isMapLayer="false" isHoverOn="false"
isVisible="true" />
<resourceData xsi:type="lightningResourceData" isUpdatingOnMetadataOnly="false"
isRequeryNecessaryOnTimeMatch="true" handlingPositiveStrikes="true" handlingNegativeStrikes="true">
<binOffset posOffset="0" negOffset="60" virtualOffset="0" />
<binRepeatCount>5</binRepeatCount>
<metadataMap>
<mapping key="pluginName">
<constraint constraintValue="binlightning" constraintType="EQUALS" />
</mapping>
<mapping key="source">
<constraint constraintValue="${source}" constraintType="EQUALS" />
</mapping>
</metadataMap>
</resourceData>
</resource>
</descriptor>
</displays>
</displayList>
</bundle>

View file

@ -56,19 +56,23 @@
<contribute xsi:type="bundleItem" file="bundles/GridLightningCGPlot.xml"
menuText="5min cloud to ground density" id="1HrGridLightningCGPlot">
<substitute key="negOffset" value="300"/>
<substitute key="negOffset" value="60"/>
<substitute key="binRepeatCount" value="5"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/GridLightningCloudFlashPlot.xml"
menuText="5min cloud flash density" id="1HrGridLightningCloudFlashPlot">
<substitute key="negOffset" value="300"/>
<substitute key="negOffset" value="60"/>
<substitute key="binRepeatCount" value="5"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/GridLightningTotalFlashPlot.xml"
menuText="5min total flash density" id="1HrGridLightningFlashPlot">
<substitute key="negOffset" value="300"/>
<substitute key="negOffset" value="60"/>
<substitute key="binRepeatCount" value="5"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/GridLightningPulsePlot.xml"
menuText="5min pulse density" id="1HrGridLightningPulsePlot">
<substitute key="negOffset" value="300"/>
<substitute key="negOffset" value="60"/>
<substitute key="binRepeatCount" value="5"/>
</contribute>
<contribute xsi:type="bundleItem" file="bundles/GridLightningCGPlot.xml"

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.lightning;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -55,7 +56,6 @@ import com.raytheon.uf.common.style.image.DataScale;
import com.raytheon.uf.common.style.image.ImagePreferences;
import com.raytheon.uf.common.style.level.Level.LevelType;
import com.raytheon.uf.common.style.level.SingleLevel;
import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.cache.CacheObject;
import com.raytheon.uf.viz.core.exception.VizException;
@ -82,6 +82,7 @@ import com.raytheon.viz.lightning.cache.LightningFrameRetriever;
* Jul 29, 2014 3463 bclement uses sparse data source
* Mar 05, 2015 4233 bsteffen include source in cache key.
* Jul 02, 2015 4606 bclement added getDisplayParameterName()
* Sep 25, 2015 4605 bsteffen repeat binning
*
* </pre>
*
@ -99,7 +100,15 @@ public class GridLightningResource extends
private static final String TIME_PARAM_LABEL = "min";
private final Map<DataTime, CacheObject<LightningFrameMetadata, LightningFrame>> cacheObjectMap = new ConcurrentHashMap<>();
protected final Map<DataTime, CacheObject<LightningFrameMetadata, LightningFrame>> cacheObjectMap = new ConcurrentHashMap<>();
/**
* This serves the same purpose as {@link AbstractGridResource#pdoMap} but
* this only contains lightning records and also takes into account
* {@link RepeatingBinOffset}. Since pdoMap is not publicly accessible it is
* necessary to have this.
*/
private Map<DataTime, List<BinLightningRecord>> recordMap = new ConcurrentHashMap<DataTime, List<BinLightningRecord>>();
/**
* @param resourceData
@ -122,7 +131,7 @@ public class GridLightningResource extends
GridLightningResourceData resourceData = getResourceData();
DisplayType type = resourceData.getDisplayType();
BinOffset offset = resourceData.getBinOffset();
RepeatingBinOffset offset = resourceData.getRepeatingBinOffset();
String param = getDisplayParameterName(type, offset);
/* cave gets angry if there is ever more than one parameter here */
rval.setParameterName(Arrays.asList(param));
@ -135,7 +144,7 @@ public class GridLightningResource extends
}
private static String getDisplayParameterName(DisplayType type,
BinOffset offset) {
RepeatingBinOffset offset) {
String rval;
if (!type.equals(DisplayType.UNDEFINED)) {
StringBuilder sb = new StringBuilder();
@ -228,6 +237,7 @@ public class GridLightningResource extends
*/
@Override
public void remove(DataTime dataTime) {
recordMap.remove(dataTime);
cacheObjectMap.remove(dataTime);
super.remove(dataTime);
}
@ -260,7 +270,7 @@ public class GridLightningResource extends
* strikes
*/
SparseArray<short[]> data = new SparseShortArray(nx, ny);
LightningFrame frame = getFrame(time, pdos);
LightningFrame frame = getFrame(time);
List<Iterator<double[]>> iterators = new ArrayList<>(4);
if (resourceData.isHandlingPositiveStrikes()) {
@ -307,7 +317,7 @@ public class GridLightningResource extends
* @param pdos
* @return
*/
private LightningFrame getFrame(DataTime time, List<PluginDataObject> pdos) {
private LightningFrame getFrame(DataTime time) {
LightningFrameRetriever retriever = LightningFrameRetriever
.getInstance();
CacheObject<LightningFrameMetadata, LightningFrame> co;
@ -320,27 +330,17 @@ public class GridLightningResource extends
*/
LightningFrameMetadata key = new LightningFrameMetadata(
resourceData.getSource(), time,
resourceData.getBinOffset());
resourceData.getRepeatingBinOffset());
co = CacheObject.newCacheObject(key, retriever);
cacheObjectMap.put(time, co);
}
}
return retriever.updateAndGet(ensurePdoType(pdos), co);
}
/**
* @param pdos
* @return list of all BinLightningRecords in pdos
*/
private List<BinLightningRecord> ensurePdoType(List<PluginDataObject> pdos) {
List<BinLightningRecord> rval = new ArrayList<>(pdos.size());
for (PluginDataObject pdo : pdos) {
if (pdo instanceof BinLightningRecord) {
rval.add((BinLightningRecord) pdo);
}
List<BinLightningRecord> pdos = recordMap.get(time);
if (pdos == null) {
pdos = Collections.emptyList();
}
return rval;
return retriever.updateAndGet(pdos, co);
}
/**
@ -425,4 +425,32 @@ public class GridLightningResource extends
super.project(crs);
}
@Override
protected void addDataObject(PluginDataObject pdo) {
/*
* This method is overridden because the method in super does not take
* into account the repeating bin offset.
*/
BinLightningRecord record = (BinLightningRecord) pdo;
for (DataTime time : resourceData.getRepeatingBinOffset()
.getNormalizedTimes(pdo.getDataTime().getValidPeriod())) {
List<BinLightningRecord> pdos = this.recordMap.get(time);
if (pdos == null) {
pdos = new ArrayList<BinLightningRecord>();
this.recordMap.put(time, pdos);
}
if (!pdos.contains(pdo)) {
pdos.add(record);
/* Must remove to clear all previously requested data. */
super.remove(time);
dataTimes.add(time);
}
}
}
@Override
protected List<PluginDataObject> getPluginDataObjects(DataTime time) {
return new ArrayList<PluginDataObject>(recordMap.get(time));
}
}

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.lightning;
import java.awt.Font;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -93,6 +94,7 @@ import com.raytheon.viz.lightning.cache.LightningFrameRetriever;
* Jul 01, 2015 4592 bclement cloud flashes are now points instead of circles
* Jul 01, 2015 4597 bclement reworked resource name using DisplayType
* Sep 10, 2015 4856 njensen synchronize in remove(DataTime)
* Sep 25, 2015 4605 bsteffen repeat binning
*
* </pre>
*
@ -178,7 +180,7 @@ public class LightningResource extends
*/
public static String formatResourceName(LightningResourceData resourceData) {
String rval = "";
int absTimeInterval = Math.abs(resourceData.getBinOffset()
int absTimeInterval = Math.abs(resourceData.getRepeatingBinOffset()
.getInterval());
// If a virtual offset is provided, it is aged lightning, so use
@ -428,33 +430,21 @@ public class LightningResource extends
final Map<DataTime, List<BinLightningRecord>> recordMap = new HashMap<DataTime, List<BinLightningRecord>>();
for (BinLightningRecord obj : objs) {
long duration = obj.getDataTime().getValidPeriod().getDuration();
if (duration > MAX_RECORD_BIN_MILLIS) {
TimeRange validPeriod = obj.getDataTime().getValidPeriod();
if (validPeriod.getDuration() > MAX_RECORD_BIN_MILLIS) {
statusHandler.error("Record bin time larger than maximum "
+ "supported period. Skipping record: " + obj);
continue;
}
DataTime time = new DataTime(obj.getStartTime());
DataTime end = new DataTime(obj.getStopTime());
time = this.getResourceData().getBinOffset()
.getNormalizedTime(time);
end = this.getResourceData().getBinOffset().getNormalizedTime(end);
// check for frames in the middle
// get interval ( in seconds ) between frames
int interval = this.getResourceData().getBinOffset().getInterval();
while (end.greaterThan(time) || end.equals(time)) {
Collection<DataTime> times = resourceData.getRepeatingBinOffset()
.getNormalizedTimes(validPeriod);
for (DataTime time : times) {
List<BinLightningRecord> records = recordMap.get(time);
if (records == null) {
records = new ArrayList<BinLightningRecord>();
recordMap.put(time, records);
}
records.add(obj);
// increment to the next time
long newTime = time.getRefTime().getTime() + (interval * 1000);
TimeRange range = new TimeRange(newTime, newTime);
time = new DataTime(newTime, range);
}
}
@ -516,7 +506,7 @@ public class LightningResource extends
*/
LightningFrameMetadata key = new LightningFrameMetadata(
resourceData.getSource(), dt,
resourceData.getBinOffset());
resourceData.getRepeatingBinOffset());
co = CacheObject.newCacheObject(key, retriever);
cacheObjectMap.put(dt, co);
dataTimes.add(dt);

View file

@ -20,11 +20,16 @@
package com.raytheon.viz.lightning;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
@ -32,8 +37,13 @@ import com.raytheon.uf.common.dataplugin.binlightning.LightningConstants;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.SimulatedTime;
import com.raytheon.uf.viz.core.alerts.AlertMessage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
/**
@ -50,6 +60,9 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
* Jul 07, 2014 3333 bclement removed plotLightSource field
* Mar 05, 2015 4233 bsteffen include source in cache key.
* Jul 01, 2015 4597 bclement added DisplayType
* Jul 02, 2015 4605 bclement don't show current bin as available
* Sep 25, 2015 4605 bsteffen repeat binning
*
* </pre>
*
* @author chammack
@ -89,6 +102,24 @@ public class LightningResourceData extends AbstractRequestableResourceData {
@XmlAttribute
private int countPosition = 0;
/**
* This field controls whether the frame for the current time is displayed.
*
* When it is true then all data is displayed including the current frame,
* since the current frame may not be fully populated this frame may be more
* sparse than others.
*
* When this is false then the frame for the current time is not displayed.
*/
@XmlAttribute
private boolean liveDisplay = false;
/**
* @See {@link RepeatingBinOffset}
*/
@XmlElement
private int binRepeatCount = 1;
@Override
protected AbstractVizResource<?, ?> constructResource(
LoadProperties loadProperties, PluginDataObject[] objects) {
@ -110,6 +141,53 @@ public class LightningResourceData extends AbstractRequestableResourceData {
return rsc;
}
@Override
public DataTime[] getAvailableTimes() throws VizException {
DataTime[] rval;
DataTime[] allTimes = super.getAvailableTimes();
if (liveDisplay || allTimes == null || allTimes.length < 1) {
rval = allTimes;
} else {
SimulatedTime systemTime = SimulatedTime.getSystemTime();
DataTime currentBin = binOffset.getNormalizedTime(new DataTime(
systemTime.getTime()));
List<DataTime> pastTimes = new ArrayList<>(Arrays.asList(allTimes));
/* remove current bin which may not be fully populated yet */
pastTimes.remove(currentBin);
rval = pastTimes.toArray(new DataTime[0]);
}
return rval;
}
@Override
protected void update(AlertMessage... messages) {
for (AlertMessage message : messages) {
Object timeObj = message.decodedAlert.get("dataTime");
fireChangeListeners(ChangeType.DATA_REMOVE, timeObj);
}
invalidateAvailableTimesCache();
}
@Override
protected PluginDataObject[] requestPluginDataObjects(
Collection<DataTime> loadSet) throws VizException {
if (binOffset == null || binRepeatCount <= 1) {
return super.requestPluginDataObjects(loadSet);
} else {
Set<DataTime> newLoadSet = new HashSet<>();
RepeatingBinOffset binRepeater = getRepeatingBinOffset();
for (DataTime loadTime : loadSet) {
newLoadSet.addAll(binRepeater.getBinsToRequest(loadTime));
}
return super.requestPluginDataObjects(newLoadSet);
}
}
public RepeatingBinOffset getRepeatingBinOffset() {
return new RepeatingBinOffset(binOffset, binRepeatCount);
}
@Override
public boolean isUpdatingOnMetadataOnly() {
if (this.isUpdatingOnMetadataOnly == false)
@ -247,28 +325,36 @@ public class LightningResourceData extends AbstractRequestableResourceData {
return rval;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public boolean isLiveDisplay() {
return liveDisplay;
}
public void setLiveDisplay(boolean liveDisplay) {
this.liveDisplay = liveDisplay;
}
public int getBinRepeatCount() {
return binRepeatCount;
}
public void setBinRepeatCount(int binRepeatCount) {
this.binRepeatCount = binRepeatCount;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + binRepeatCount;
result = prime * result + countPosition;
result = prime * result + (handlingCloudFlashes ? 1231 : 1237);
result = prime * result + (handlingNegativeStrikes ? 1231 : 1237);
result = prime * result + (handlingPositiveStrikes ? 1231 : 1237);
result = prime * result + (handlingPulses ? 1231 : 1237);
result = prime * result + (liveDisplay ? 1231 : 1237);
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
@ -278,6 +364,8 @@ public class LightningResourceData extends AbstractRequestableResourceData {
if (getClass() != obj.getClass())
return false;
LightningResourceData other = (LightningResourceData) obj;
if (binRepeatCount != other.binRepeatCount)
return false;
if (countPosition != other.countPosition)
return false;
if (handlingCloudFlashes != other.handlingCloudFlashes)
@ -288,6 +376,8 @@ public class LightningResourceData extends AbstractRequestableResourceData {
return false;
if (handlingPulses != other.handlingPulses)
return false;
if (liveDisplay != other.liveDisplay)
return false;
return true;
}

View file

@ -0,0 +1,200 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.viz.lightning;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.common.time.TimeRange;
/**
* <p>
* When using a bin offset, display each bin in multiple frames. For example a
* bin offset can be used to group data into 1 minute intervals and if the
* repeat count is 5 then each bin will be displayed in 5 frames and each frame
* would last 5 minutes. For example the first diagram below shows how 10 one
* minute bins get grouped into 6 five minute frames. Also, the 12:04 and 12:05
* are repeated in 5 different frames, if the time line was extended infinitely
* then all other bins would be repeated.
* </p>
*
* <h1>Repeating Bin Offset(1 minute repeated 5 times)</h1>
*
* <pre>
* Bin times: |-12:00-|-12:01-|-12:02-|-12:03-|-12:04-|-12:05-|-12:06-|-12:07-|-12:08-|-12:09-|
* Frame 1: |-------+-------+-------+-------+-------|
* Frame 2: |-------+-------+-------+-------+-------|
* Frame 3: |-------+-------+-------+-------+-------|
* Frame 4: |-------+-------+-------+-------+-------|
* Frame 5: |-------+-------+-------+-------+-------|
* Frame 6: |-------+-------+-------+-------+-------|
* </pre>
*
* <p>
* For comparison here is a chart showing a normal BinOffset of 5 minutes and 1
* minutes.
* </p>
*
* <h1>5 Minute Bin Offset(No Repeating)</h1>
*
* <pre>
* Bin times: |-12:00---------------------------12:04-|-12:05---------------------------12:09-|
* Frame 1: |---------------------------------------|
* Frame 2: |---------------------------------------|
* </pre>
*
* <h1>1 Minute Bin Offset(No Repeating)</h1>
*
* <pre>
* Bin times: |-12:00-|-12:01-|-12:02-|-12:03-|-12:04-|-12:05-|-12:06-|-12:07-|-12:08-|-12:09-|
* Frame 1: |-------|
* Frame 2: |-------|
* Frame 3: |-------|
* Frame 4: |-------|
* Frame 5: |-------|
* Frame 6: |-------|
* Frame 7: |-------|
* Frame 8: |-------|
* Frame 9: |-------|
* Frame 10: |-------|
* </pre>
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Sep 25, 2015 4605 bsteffen Initial Creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class RepeatingBinOffset {
private final BinOffset binOffset;
private final int repeatCount;
public RepeatingBinOffset(BinOffset binOffset, int repeatCount) {
this.binOffset = binOffset;
this.repeatCount = repeatCount;
}
/**
* For a given data time this will return the times of all the normalized
* frames which should contain this data.
*/
public List<DataTime> getNormalizedTimes(DataTime time) {
return repeatNormalizedTime(binOffset.getNormalizedTime(time), false);
}
/**
* Determine all the normalized frame times that contain data within the
* specified range.
*/
public List<DataTime> getNormalizedTimes(TimeRange range) {
/*
* Start off defining the result as all the times that should include
* the end time.
*/
DataTime normalEnd = binOffset.getNormalizedTime(new DataTime(range
.getEnd()));
List<DataTime> result = repeatNormalizedTime(normalEnd, false);
/* Add all the bins that exist from the start time to the end time. */
DataTime normalStart = binOffset.getNormalizedTime(new DataTime(range
.getStart()));
long intervalMs = binOffset.getInterval() * 1000L;
while (!normalEnd.equals(normalStart)) {
result.add(normalStart);
long newTimeMs = normalStart.getRefTime().getTime() + intervalMs;
normalStart = new DataTime(new Date(newTimeMs));
}
return result;
}
/**
* When requesting data for a specific time, this can be used to get the
* time of all the bins contained in a single frame of data. This is useful
* for requesting data through code that understands a {@link BinOffset} but
* does not understand this class.
*/
public List<DataTime> getBinsToRequest(DataTime time) {
return repeatNormalizedTime(time, true);
}
/**
* Return a list of repeatCount times that are spaces according to the binOffset interval.
*/
private List<DataTime> repeatNormalizedTime(DataTime time, boolean backwards) {
List<DataTime> result = new ArrayList<>(repeatCount);
result.add(time);
long intervalMs = binOffset.getInterval() * 1000L;
if (backwards) {
intervalMs *= -1;
}
for (int i = 1; i < repeatCount; i += 1) {
long newTimeMs = time.getRefTime().getTime() + intervalMs;
time = new DataTime(new Date(newTimeMs));
result.add(time);
}
return result;
}
public int getInterval() {
return binOffset.getInterval() * repeatCount;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((binOffset == null) ? 0 : binOffset.hashCode());
result = prime * result + repeatCount;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RepeatingBinOffset other = (RepeatingBinOffset) obj;
if (binOffset == null) {
if (other.binOffset != null)
return false;
} else if (!binOffset.equals(other.binOffset))
return false;
if (repeatCount != other.repeatCount)
return false;
return true;
}
}

View file

@ -23,8 +23,8 @@ import java.util.ArrayList;
import java.util.List;
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
import com.raytheon.uf.common.time.BinOffset;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.viz.lightning.RepeatingBinOffset;
/**
* Time and record data used to create a LightningFrame
@ -35,8 +35,9 @@ import com.raytheon.uf.common.time.DataTime;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jul 9, 2014 3333 bclement moved from LightningResource
* Jul 9, 2014 3333 bclement moved from LightningResource
* Mar 05, 2015 4233 bsteffen include source in cache key.
* Sep 25, 2015 4605 bsteffen repeat binning
*
* </pre>
*
@ -47,7 +48,7 @@ public class LightningFrameMetadata {
private final String source;
private final BinOffset offset;
private final RepeatingBinOffset offset;
private final DataTime frameTime;
@ -56,16 +57,20 @@ public class LightningFrameMetadata {
private final List<BinLightningRecord> processed = new ArrayList<BinLightningRecord>();
public LightningFrameMetadata(String source, DataTime frameTime,
BinOffset offset) {
RepeatingBinOffset offset) {
this.source = source;
this.frameTime = frameTime;
this.offset = offset;
}
public boolean contains(DataTime time) {
return offset.getNormalizedTimes(time).contains(frameTime);
}
/**
* @return the offset
*/
public BinOffset getOffset() {
public RepeatingBinOffset getOffset() {
return offset;
}

View file

@ -62,6 +62,7 @@ import com.raytheon.uf.viz.core.cache.CacheObject.IObjectRetrieverAndDisposer;
* Jul 09, 2014 3333 bclement moved from LightningResource
* Jul 22, 2014 3214 bclement fixed typos in populatePulseData() and updateAndGet()
* Sep 11, 2014 3608 bclement index records by group and dataset name for better error handling
* Sep 25, 2015 4605 bsteffen repeat binning
*
* </pre>
*
@ -273,7 +274,13 @@ public class LightningFrameRetriever implements
for (int i = 0; i < numRecords; i++) {
DataTime dt = new DataTime(new Date(timeData[i]));
dt = frame.getOffset().getNormalizedTime(dt);
if (!frame.contains(dt)) {
/*
* only add the strike to the list if the data time
* of the strike matches the data time of the frame
*/
continue;
}
List<double[]> list;
LtgStrikeType type = LtgStrikeType.getById(typeData[i]);
switch (type) {
@ -292,12 +299,8 @@ public class LightningFrameRetriever implements
double[] latLon = new double[] { longitudeData[i],
latitudeData[i] };
// only add the strike to the list if the data time
// of the strike matches the data time of the frame
if (dt.equals(bundle.getFrameTime())) {
list.add(latLon);
strikeCount++;
}
list.add(latLon);
strikeCount++;
}
}