From e7fa60722610f2795936b78cfe55cb888d6a3888 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Mon, 28 Sep 2015 09:00:29 -0500 Subject: [PATCH] Omaha #4605 Lightning time matching adjustments. Former-commit-id: 6d4763fec2896bbb59c3be8abe1d855356a0a4cd --- .../META-INF/MANIFEST.MF | 2 +- .../bundles/GridLightningCGPlot.xml | 1 + .../bundles/GridLightningCloudFlashPlot.xml | 1 + .../bundles/GridLightningPulsePlot.xml | 1 + .../bundles/GridLightningTotalFlashPlot.xml | 1 + .../bundles/TotalLightningPlot5Min.xml | 133 ++++++------ .../gridTotalLightningBundleItems.xml | 12 +- .../viz/lightning/GridLightningResource.java | 70 ++++-- .../viz/lightning/LightningResource.java | 28 +-- .../viz/lightning/LightningResourceData.java | 110 +++++++++- .../viz/lightning/RepeatingBinOffset.java | 200 ++++++++++++++++++ .../cache/LightningFrameMetadata.java | 15 +- .../cache/LightningFrameRetriever.java | 17 +- 13 files changed, 456 insertions(+), 135 deletions(-) create mode 100644 cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/RepeatingBinOffset.java diff --git a/cave/com.raytheon.viz.lightning/META-INF/MANIFEST.MF b/cave/com.raytheon.viz.lightning/META-INF/MANIFEST.MF index d499f5c726..305e1e9d88 100644 --- a/cave/com.raytheon.viz.lightning/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.viz.lightning/META-INF/MANIFEST.MF @@ -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, diff --git a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCGPlot.xml b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCGPlot.xml index 354f5adfd0..c9a686d4bd 100644 --- a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCGPlot.xml +++ b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCGPlot.xml @@ -34,6 +34,7 @@ handlingPulses="false" handlingCloudFlashes="false" kmResolution="${resolution}"> + ${binRepeatCount;1} diff --git a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCloudFlashPlot.xml b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCloudFlashPlot.xml index 841ee52cf3..7e6c1979d3 100644 --- a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCloudFlashPlot.xml +++ b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningCloudFlashPlot.xml @@ -34,6 +34,7 @@ handlingPulses="false" handlingCloudFlashes="true" kmResolution="${resolution}"> + ${binRepeatCount;1} diff --git a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningPulsePlot.xml b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningPulsePlot.xml index f654a66f76..6e3f12719d 100644 --- a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningPulsePlot.xml +++ b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningPulsePlot.xml @@ -34,6 +34,7 @@ handlingPulses="true" handlingCloudFlashes="false" kmResolution="${resolution}"> + ${binRepeatCount;1} diff --git a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningTotalFlashPlot.xml b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningTotalFlashPlot.xml index 087af9d274..73899970e5 100644 --- a/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningTotalFlashPlot.xml +++ b/cave/com.raytheon.viz.lightning/localization/bundles/GridLightningTotalFlashPlot.xml @@ -34,6 +34,7 @@ handlingPulses="false" handlingCloudFlashes="true" kmResolution="${resolution}"> + ${binRepeatCount;1} diff --git a/cave/com.raytheon.viz.lightning/localization/bundles/TotalLightningPlot5Min.xml b/cave/com.raytheon.viz.lightning/localization/bundles/TotalLightningPlot5Min.xml index 4d020d948b..e39934d055 100644 --- a/cave/com.raytheon.viz.lightning/localization/bundles/TotalLightningPlot5Min.xml +++ b/cave/com.raytheon.viz.lightning/localization/bundles/TotalLightningPlot5Min.xml @@ -19,72 +19,69 @@ further_licensing_information. --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + 5 + + + + + + + + + + + + + + + + + 5 + + + + + + + + + + + + + + + + + 5 + + + + + + + + + + + + + diff --git a/cave/com.raytheon.viz.lightning/localization/menus/lightning/gridTotalLightningBundleItems.xml b/cave/com.raytheon.viz.lightning/localization/menus/lightning/gridTotalLightningBundleItems.xml index cd8c6322a8..5a3abee374 100644 --- a/cave/com.raytheon.viz.lightning/localization/menus/lightning/gridTotalLightningBundleItems.xml +++ b/cave/com.raytheon.viz.lightning/localization/menus/lightning/gridTotalLightningBundleItems.xml @@ -56,19 +56,23 @@ - + + - + + - + + - + + * @@ -99,7 +100,15 @@ public class GridLightningResource extends private static final String TIME_PARAM_LABEL = "min"; - private final Map> cacheObjectMap = new ConcurrentHashMap<>(); + protected final Map> 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> recordMap = new ConcurrentHashMap>(); /** * @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 data = new SparseShortArray(nx, ny); - LightningFrame frame = getFrame(time, pdos); + LightningFrame frame = getFrame(time); List> iterators = new ArrayList<>(4); if (resourceData.isHandlingPositiveStrikes()) { @@ -307,7 +317,7 @@ public class GridLightningResource extends * @param pdos * @return */ - private LightningFrame getFrame(DataTime time, List pdos) { + private LightningFrame getFrame(DataTime time) { LightningFrameRetriever retriever = LightningFrameRetriever .getInstance(); CacheObject 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 ensurePdoType(List pdos) { - List rval = new ArrayList<>(pdos.size()); - for (PluginDataObject pdo : pdos) { - if (pdo instanceof BinLightningRecord) { - rval.add((BinLightningRecord) pdo); - } + List 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 pdos = this.recordMap.get(time); + if (pdos == null) { + pdos = new ArrayList(); + 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 getPluginDataObjects(DataTime time) { + return new ArrayList(recordMap.get(time)); + } + } diff --git a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResource.java b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResource.java index 38d2df40c7..7fc3009e5e 100644 --- a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResource.java +++ b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResource.java @@ -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 * * * @@ -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> recordMap = new HashMap>(); 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 times = resourceData.getRepeatingBinOffset() + .getNormalizedTimes(validPeriod); + for (DataTime time : times) { List records = recordMap.get(time); if (records == null) { records = new ArrayList(); 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); diff --git a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResourceData.java b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResourceData.java index 37dc8b633a..a5fc7704c8 100644 --- a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResourceData.java +++ b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/LightningResourceData.java @@ -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 + * * * * @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 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 loadSet) throws VizException { + if (binOffset == null || binRepeatCount <= 1) { + return super.requestPluginDataObjects(loadSet); + } else { + Set 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; } diff --git a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/RepeatingBinOffset.java b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/RepeatingBinOffset.java new file mode 100644 index 0000000000..7130ac8c0f --- /dev/null +++ b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/RepeatingBinOffset.java @@ -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; + +/** + *

+ * 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. + *

+ * + *

Repeating Bin Offset(1 minute repeated 5 times)

+ * + *
+ * 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:                                            |-------+-------+-------+-------+-------|
+ * 
+ * + *

+ * For comparison here is a chart showing a normal BinOffset of 5 minutes and 1 + * minutes. + *

+ * + *

5 Minute Bin Offset(No Repeating)

+ * + *
+ * Bin times:  |-12:00---------------------------12:04-|-12:05---------------------------12:09-|
+ * Frame 1:    |---------------------------------------|
+ * Frame 2:                                            |---------------------------------------|
+ * 
+ * + *

1 Minute Bin Offset(No Repeating)

+ * + *
+ * 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:                                                                           |-------|
+ * 
+ * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer  Description
+ * ------------- -------- --------- --------------------------
+ * Sep 25, 2015  4605     bsteffen  Initial Creation
+ * 
+ * 
+ * + * @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 getNormalizedTimes(DataTime time) { + return repeatNormalizedTime(binOffset.getNormalizedTime(time), false); + } + + /** + * Determine all the normalized frame times that contain data within the + * specified range. + */ + public List 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 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 getBinsToRequest(DataTime time) { + return repeatNormalizedTime(time, true); + } + + /** + * Return a list of repeatCount times that are spaces according to the binOffset interval. + */ + private List repeatNormalizedTime(DataTime time, boolean backwards) { + List 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; + } + +} diff --git a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameMetadata.java b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameMetadata.java index 53f94f1245..f06c072f75 100644 --- a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameMetadata.java +++ b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameMetadata.java @@ -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 * * * @@ -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 processed = new ArrayList(); 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; } diff --git a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameRetriever.java b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameRetriever.java index 55753bc444..1262b31db7 100644 --- a/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameRetriever.java +++ b/cave/com.raytheon.viz.lightning/src/com/raytheon/viz/lightning/cache/LightningFrameRetriever.java @@ -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 * * * @@ -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 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++; } }