1 /***********************************************************************
2  * Copyright (c) 2013-2024 Commonwealth Computer Research, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Apache License, Version 2.0
5  * which accompanies this distribution and is available at
6  * http://www.opensource.org/licenses/apache2.0.php.
7  ***********************************************************************/
8 
9 package org.locationtech.geomesa.utils.stats
10 
11 import com.typesafe.scalalogging.LazyLogging
12 import org.geotools.api.feature.simple.{SimpleFeature, SimpleFeatureType}
13 import org.geotools.geometry.jts.JTSFactoryFinder
14 import org.locationtech.geomesa.curve.TimePeriod.TimePeriod
15 import org.locationtech.geomesa.curve.{BinnedTime, TimePeriod, Z3SFC}
16 import org.locationtech.geomesa.utils.stats.BinnedArray.LongBinning
17 import org.locationtech.geomesa.utils.stats.MinMax.MinMaxGeometry
18 import org.locationtech.jts.geom.{Coordinate, Geometry, Point}
19 
20 import java.util.Date
21 
22 /**
23   * The histogram's state is stored in an indexed array, where the index is the bin number
24   * and the values are the counts.
25   *
26   * Tracks geometry and date attributes as a single value.
27   *
28   * @param sft simple feature type
29   * @param geom geometry attribute in the sft
30   * @param dtg date attribute in the sft
31   * @param period time period to use for z index
32   * @param length number of bins the histogram has, per period
33  */
34 class Z3Histogram(
35     val sft: SimpleFeatureType,
36     val geom: String,
37     val dtg: String,
38     val period: TimePeriod,
39     val length: Int
40   ) extends Stat with LazyLogging {
41 
42   import Z3Histogram._
43 
44   override type S = Z3Histogram
45 
46   private val g = sft.indexOf(geom)
47   private val d = sft.indexOf(dtg)
48 
49   private val sfc = Z3SFC(period)
50   private val timeToBin = BinnedTime.timeToBinnedTime(period)
51   private val binToDate = BinnedTime.binnedTimeToDate(period)
52   private val minZ = sfc.index(minGeom.getX, minGeom.getY, sfc.time.min.toLong)
53   private val maxZ = sfc.index(maxGeom.getX, maxGeom.getY, sfc.time.max.toLong)
54 
55   private lazy val jsonFormat = period match {
56     case TimePeriod.Day   => s"$period-%05d"
57     case TimePeriod.Week  => s"$period-%04d"
58     case TimePeriod.Month => s"$period-%03d"
59     case TimePeriod.Year  => s"$period-%02d"
60   }
61 
62   private [stats] val binMap = scala.collection.mutable.Map.empty[Short, BinnedArray[java.lang.Long]]
63   private [stats] def newBins = new BinnedArray(new LongBinning(length, (minZ, maxZ)))
64 
65   def timeBins: Seq[Short] = binMap.keys.toSeq.sorted
66   def count(timeBin: Short, i: Int): Long = binMap.get(timeBin).map(_.counts(i)).getOrElse(0L)
67 
68   def directIndex(timeBin: Short, value: Long): Int = binMap.get(timeBin).map(_.indexOf(value)).getOrElse(-1)
69 
70   def indexOf(value: (Geometry, Date)): (Short, Int) = {
71     val (timeBin, z) = toKey(value._1, value._2, lenient = false)
72     (timeBin, directIndex(timeBin, z))
73   }
74 
75   def medianValue(timeBin: Short, i: Int): (Geometry, Date) = fromKey(timeBin, binMap(timeBin).medianValue(i))
76 
77   private def toKey(geom: Geometry, dtg: Date, lenient: Boolean): (Short, Long) = {
78     import org.locationtech.geomesa.utils.geotools.Conversions.RichGeometry
79     val BinnedTime(bin, offset) = timeToBin(dtg.getTime)
80     val centroid = geom.safeCentroid()
81     val z = sfc.index(centroid.getX, centroid.getY, offset, lenient)
82     (bin, z)
83   }
84 
85   private def fromKey(timeBin: Short, z: Long): (Geometry, Date) = {
86     val (x, y, t) = sfc.invert(z)
87     val dtg = Date.from(binToDate(BinnedTime(timeBin, t)).toInstant)
88     val geom = Z3Histogram.gf.createPoint(new Coordinate(x, y))
89     (geom, dtg)
90   }
91 
92   /**
93     * Split the stat into a separate stat per time bin of z data. Allows for separate handling of the reduced
94     * data set.
95     *
96     * @return
97     */
98   def splitByTime: Seq[(Short, Z3Histogram)] = {
99     binMap.toSeq.map { case (w, bins) =>
100       val hist = new Z3Histogram(sft, geom, dtg, period, length)
101       hist.binMap.put(w, bins)
102       (w, hist)
103     }
104   }
105 
106   override def observe(sf: SimpleFeature): Unit = {
107     val geom = sf.getAttribute(g).asInstanceOf[Geometry]
108     val dtg  = sf.getAttribute(d).asInstanceOf[Date]
109     if (geom != null && dtg != null) {
110       try {
111         val (timeBin, z3) = toKey(geom, dtg, lenient = false)
112         binMap.getOrElseUpdate(timeBin, newBins).add(z3, 1L)
113       } catch {
114         case e: Exception => logger.warn(s"Error observing geom '$geom' and date '$dtg': ${e.toString}")
115       }
116     }
117   }
118 
119   override def unobserve(sf: SimpleFeature): Unit = {
120     val geom = sf.getAttribute(g).asInstanceOf[Geometry]
121     val dtg  = sf.getAttribute(d).asInstanceOf[Date]
122     if (geom != null && dtg != null) {
123       try {
124         val (timeBin, z3) = toKey(geom, dtg, lenient = true)
125         binMap.get(timeBin).foreach(_.add(z3, -1L))
126       } catch {
127         case e: Exception => logger.warn(s"Error un-observing geom '$geom' and date '$dtg': ${e.toString}")
128       }
129     }
130   }
131 
132   /**
133     * Creates a new histogram by combining another histogram with this one
134     */
135   override def +(other: Z3Histogram): Z3Histogram = {
136     val plus = new Z3Histogram(sft, geom, dtg, period, length)
137     plus += this
138     plus += other
139     plus
140   }
141 
142   /**
143     * Copies another histogram into this one
144     */
145   override def +=(other: Z3Histogram): Unit = {
146     if (length != other.length) {
147       throw new NotImplementedError("Can only add z3 histograms with the same length")
148     }
149     other.binMap.foreach { case (w, bins) =>
150       binMap.get(w) match {
151         case None => binMap.put(w, bins) // note: sharing a reference now
152         case Some(b) =>
153           var i = 0
154           while (i < b.length) {
155             b.counts(i) += bins.counts(i)
156             i += 1
157           }
158       }
159     }
160   }
161 
162   override def toJsonObject: Any =
163     binMap.toSeq.sortBy(_._1)
164       .map { case (p, bins) => (String.format(jsonFormat, Short.box(p)), bins) }
165       .map { case (label, bins) => Map(label-> Map("bins" -> bins.counts)) }
166 
167   override def isEmpty: Boolean = binMap.values.forall(_.counts.forall(_ == 0))
168 
169   override def clear(): Unit = binMap.values.foreach(_.clear())
170 
171   override def isEquivalent(other: Stat): Boolean = other match {
172     case that: Z3Histogram =>
173       g == that.g && d == that.d && period == that.period &&
174           length == that.length && binMap.keySet == that.binMap.keySet &&
175           binMap.forall { case (w, bins) => java.util.Arrays.equals(bins.counts, that.binMap(w).counts) }
176     case _ => false
177   }
178 }
179 
180 object Z3Histogram {
181 
182   private val gf = JTSFactoryFinder.getGeometryFactory
183 
184   val minGeom: Point = MinMaxGeometry.min.asInstanceOf[Point]
185   val maxGeom: Point = MinMaxGeometry.max.asInstanceOf[Point]
186 }
Line Stmt Id Pos Tree Symbol Tests Code
46 13750 1732 - 1736 Select org.locationtech.geomesa.utils.stats.Z3Histogram.geom Z3Histogram.this.geom
46 13751 1720 - 1737 Apply org.geotools.api.feature.simple.SimpleFeatureType.indexOf Z3Histogram.this.sft.indexOf(Z3Histogram.this.geom)
47 13752 1768 - 1771 Select org.locationtech.geomesa.utils.stats.Z3Histogram.dtg Z3Histogram.this.dtg
47 13753 1756 - 1772 Apply org.geotools.api.feature.simple.SimpleFeatureType.indexOf Z3Histogram.this.sft.indexOf(Z3Histogram.this.dtg)
49 13754 1800 - 1806 Select org.locationtech.geomesa.utils.stats.Z3Histogram.period Z3Histogram.this.period
49 13755 1794 - 1807 Apply org.locationtech.geomesa.curve.Z3SFC.apply org.locationtech.geomesa.curve.Z3SFC.apply(Z3Histogram.this.period)
50 13756 1862 - 1868 Select org.locationtech.geomesa.utils.stats.Z3Histogram.period Z3Histogram.this.period
50 13757 1834 - 1869 Apply org.locationtech.geomesa.curve.BinnedTime.timeToBinnedTime org.locationtech.geomesa.curve.BinnedTime.timeToBinnedTime(Z3Histogram.this.period)
51 13758 1924 - 1930 Select org.locationtech.geomesa.utils.stats.Z3Histogram.period Z3Histogram.this.period
51 13759 1896 - 1931 Apply org.locationtech.geomesa.curve.BinnedTime.binnedTimeToDate org.locationtech.geomesa.curve.BinnedTime.binnedTimeToDate(Z3Histogram.this.period)
52 13760 1963 - 1975 Apply org.locationtech.jts.geom.Point.getX Z3Histogram.minGeom.getX()
52 13761 1977 - 1989 Apply org.locationtech.jts.geom.Point.getY Z3Histogram.minGeom.getY()
52 13762 1991 - 2010 Select scala.Double.toLong Z3Histogram.this.sfc.time.min.toLong
52 13763 1953 - 2011 Apply org.locationtech.geomesa.curve.Z3SFC.index Z3Histogram.this.sfc.index(Z3Histogram.minGeom.getX(), Z3Histogram.minGeom.getY(), Z3Histogram.this.sfc.time.min.toLong, Z3Histogram.this.sfc.index$default$4)
53 13764 2043 - 2055 Apply org.locationtech.jts.geom.Point.getX Z3Histogram.maxGeom.getX()
53 13765 2057 - 2069 Apply org.locationtech.jts.geom.Point.getY Z3Histogram.maxGeom.getY()
53 13766 2071 - 2090 Select scala.Double.toLong Z3Histogram.this.sfc.time.max.toLong
53 13767 2033 - 2091 Apply org.locationtech.geomesa.curve.Z3SFC.index Z3Histogram.this.sfc.index(Z3Histogram.maxGeom.getX(), Z3Histogram.maxGeom.getY(), Z3Histogram.this.sfc.time.max.toLong, Z3Histogram.this.sfc.index$default$4)
62 13768 2356 - 2426 TypeApply scala.collection.mutable.Map.empty scala.collection.mutable.Map.empty[Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long]]
63 13769 2491 - 2497 Select org.locationtech.geomesa.utils.stats.Z3Histogram.length Z3Histogram.this.length
63 13770 2500 - 2504 Select org.locationtech.geomesa.utils.stats.Z3Histogram.minZ Z3Histogram.this.minZ
63 13771 2500 - 2504 ApplyImplicitView scala.Predef.long2Long scala.Predef.long2Long(Z3Histogram.this.minZ)
63 13772 2506 - 2510 Select org.locationtech.geomesa.utils.stats.Z3Histogram.maxZ Z3Histogram.this.maxZ
63 13773 2506 - 2510 ApplyImplicitView scala.Predef.long2Long scala.Predef.long2Long(Z3Histogram.this.maxZ)
63 13774 2499 - 2511 Apply scala.Tuple2.apply scala.Tuple2.apply[Long, Long](scala.Predef.long2Long(Z3Histogram.this.minZ), scala.Predef.long2Long(Z3Histogram.this.maxZ))
63 13775 2475 - 2512 Apply org.locationtech.geomesa.utils.stats.BinnedArray.LongBinning.<init> new org.locationtech.geomesa.utils.stats.BinnedArray.LongBinning(Z3Histogram.this.length, scala.Tuple2.apply[Long, Long](scala.Predef.long2Long(Z3Histogram.this.minZ), scala.Predef.long2Long(Z3Histogram.this.maxZ)))
63 13776 2459 - 2513 Apply org.locationtech.geomesa.utils.stats.BinnedArray.<init> new org.locationtech.geomesa.utils.stats.BinnedArray[Long](new org.locationtech.geomesa.utils.stats.BinnedArray.LongBinning(Z3Histogram.this.length, scala.Tuple2.apply[Long, Long](scala.Predef.long2Long(Z3Histogram.this.minZ), scala.Predef.long2Long(Z3Histogram.this.maxZ))))
65 13777 2562 - 2562 Select scala.math.Ordering.Short math.this.Ordering.Short
65 13778 2544 - 2568 ApplyToImplicitArgs scala.collection.SeqLike.sorted Z3Histogram.this.binMap.keys.toSeq.sorted[Short](math.this.Ordering.Short)
66 13779 2613 - 2663 Apply scala.Option.getOrElse Z3Histogram.this.binMap.get(timeBin).map[Long](((x$1: org.locationtech.geomesa.utils.stats.BinnedArray[Long]) => x$1.counts.apply(i))).getOrElse[Long](0L)
68 13780 2719 - 2774 Apply scala.Option.getOrElse Z3Histogram.this.binMap.get(timeBin).map[Int](((x$2: org.locationtech.geomesa.utils.stats.BinnedArray[Long]) => x$2.indexOf(scala.Predef.long2Long(value)))).getOrElse[Int](-1)
71 13781 2842 - 2842 Select scala.Tuple2._1 x$3._1
71 13782 2851 - 2851 Select scala.Tuple2._2 x$3._2
72 13783 2913 - 2936 Apply org.locationtech.geomesa.utils.stats.Z3Histogram.directIndex Z3Histogram.this.directIndex(timeBin, z)
72 13784 2903 - 2937 Apply scala.Tuple2.apply scala.Tuple2.apply[Short, Int](timeBin, Z3Histogram.this.directIndex(timeBin, z))
75 13785 3022 - 3052 Apply org.locationtech.geomesa.utils.stats.BinnedArray.medianValue Z3Histogram.this.binMap.apply(timeBin).medianValue(i)
75 13786 3022 - 3052 ApplyImplicitView scala.Predef.Long2long scala.Predef.Long2long(Z3Histogram.this.binMap.apply(timeBin).medianValue(i))
75 13787 3005 - 3053 Apply org.locationtech.geomesa.utils.stats.Z3Histogram.fromKey Z3Histogram.this.fromKey(timeBin, scala.Predef.Long2long(Z3Histogram.this.binMap.apply(timeBin).medianValue(i)))
79 13788 3234 - 3234 Select scala.Tuple2._1 x$4._1
79 13789 3239 - 3239 Select scala.Tuple2._2 x$4._2
80 13790 3291 - 3310 Apply org.locationtech.geomesa.utils.geotools.Conversions.RichGeometry.safeCentroid org.locationtech.geomesa.utils.geotools.Conversions.RichGeometry(geom).safeCentroid()
81 13791 3333 - 3346 Apply org.locationtech.jts.geom.Point.getX centroid.getX()
81 13792 3348 - 3361 Apply org.locationtech.jts.geom.Point.getY centroid.getY()
81 13793 3323 - 3379 Apply org.locationtech.geomesa.curve.Z3SFC.index Z3Histogram.this.sfc.index(centroid.getX(), centroid.getY(), offset, lenient)
82 13794 3384 - 3392 Apply scala.Tuple2.apply scala.Tuple2.apply[Short, Long](bin, z)
86 13795 3476 - 3476 Select scala.Tuple3._1 x$5._1
86 13796 3479 - 3479 Select scala.Tuple3._2 x$5._2
86 13797 3482 - 3482 Select scala.Tuple3._3 x$5._3
87 13798 3525 - 3568 Apply java.time.chrono.ChronoZonedDateTime.toInstant Z3Histogram.this.binToDate.apply(org.locationtech.geomesa.curve.BinnedTime.apply(timeBin, t)).toInstant()
87 13799 3515 - 3569 Apply java.util.Date.from java.util.Date.from(Z3Histogram.this.binToDate.apply(org.locationtech.geomesa.curve.BinnedTime.apply(timeBin, t)).toInstant())
88 13800 3612 - 3632 Apply org.locationtech.jts.geom.Coordinate.<init> new org.locationtech.jts.geom.Coordinate(x, y)
88 13801 3585 - 3633 Apply org.locationtech.jts.geom.GeometryFactory.createPoint Z3Histogram.gf.createPoint(new org.locationtech.jts.geom.Coordinate(x, y))
89 13802 3638 - 3649 Apply scala.Tuple2.apply scala.Tuple2.apply[org.locationtech.jts.geom.Point, java.util.Date](geom, dtg)
99 13811 3901 - 4015 Block <nosymbol> { val hist: org.locationtech.geomesa.utils.stats.Z3Histogram = new Z3Histogram(Z3Histogram.this.sft, Z3Histogram.this.geom, Z3Histogram.this.dtg, Z3Histogram.this.period, Z3Histogram.this.length); hist.binMap.put(w, bins); scala.Tuple2.apply[Short, org.locationtech.geomesa.utils.stats.Z3Histogram](w, hist) }
99 13812 3884 - 3884 TypeApply scala.collection.Seq.canBuildFrom collection.this.Seq.canBuildFrom[(Short, org.locationtech.geomesa.utils.stats.Z3Histogram)]
99 13813 3867 - 4021 ApplyToImplicitArgs scala.collection.TraversableLike.map Z3Histogram.this.binMap.toSeq.map[(Short, org.locationtech.geomesa.utils.stats.Z3Histogram), Seq[(Short, org.locationtech.geomesa.utils.stats.Z3Histogram)]](((x0$1: (Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x0$1 match { case (_1: Short, _2: org.locationtech.geomesa.utils.stats.BinnedArray[Long])(Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])((w @ _), (bins @ _)) => { val hist: org.locationtech.geomesa.utils.stats.Z3Histogram = new Z3Histogram(Z3Histogram.this.sft, Z3Histogram.this.geom, Z3Histogram.this.dtg, Z3Histogram.this.period, Z3Histogram.this.length); hist.binMap.put(w, bins); scala.Tuple2.apply[Short, org.locationtech.geomesa.utils.stats.Z3Histogram](w, hist) } }))(collection.this.Seq.canBuildFrom[(Short, org.locationtech.geomesa.utils.stats.Z3Histogram)])
100 13803 3937 - 3940 Select org.locationtech.geomesa.utils.stats.Z3Histogram.sft Z3Histogram.this.sft
100 13804 3942 - 3946 Select org.locationtech.geomesa.utils.stats.Z3Histogram.geom Z3Histogram.this.geom
100 13805 3948 - 3951 Select org.locationtech.geomesa.utils.stats.Z3Histogram.dtg Z3Histogram.this.dtg
100 13806 3953 - 3959 Select org.locationtech.geomesa.utils.stats.Z3Histogram.period Z3Histogram.this.period
100 13807 3961 - 3967 Select org.locationtech.geomesa.utils.stats.Z3Histogram.length Z3Histogram.this.length
100 13808 3921 - 3968 Apply org.locationtech.geomesa.utils.stats.Z3Histogram.<init> new Z3Histogram(Z3Histogram.this.sft, Z3Histogram.this.geom, Z3Histogram.this.dtg, Z3Histogram.this.period, Z3Histogram.this.length)
101 13809 3975 - 3999 Apply scala.collection.mutable.MapLike.put hist.binMap.put(w, bins)
102 13810 4006 - 4015 Apply scala.Tuple2.apply scala.Tuple2.apply[Short, org.locationtech.geomesa.utils.stats.Z3Histogram](w, hist)
107 13814 4110 - 4111 Select org.locationtech.geomesa.utils.stats.Z3Histogram.g Z3Histogram.this.g
107 13815 4094 - 4135 TypeApply scala.Any.asInstanceOf sf.getAttribute(Z3Histogram.this.g).asInstanceOf[org.locationtech.jts.geom.Geometry]
108 13816 4167 - 4168 Select org.locationtech.geomesa.utils.stats.Z3Histogram.d Z3Histogram.this.d
108 13817 4151 - 4188 TypeApply scala.Any.asInstanceOf sf.getAttribute(Z3Histogram.this.d).asInstanceOf[java.util.Date]
109 13818 4205 - 4209 Literal <nosymbol> null
109 13819 4213 - 4224 Apply java.lang.Object.!= dtg.!=(null)
109 13820 4197 - 4224 Apply scala.Boolean.&& geom.!=(null).&&(dtg.!=(null))
109 13830 4193 - 4193 Literal <nosymbol> ()
109 13831 4193 - 4193 Block <nosymbol> ()
110 13827 4248 - 4362 Block <nosymbol> { <synthetic> <artifact> private[this] val x$6: (Short, Long) = (Z3Histogram.this.toKey(geom, dtg, false): (Short, Long) @unchecked) match { case (_1: Short, _2: Long)(Short, Long)((timeBin @ _), (z3 @ _)) => scala.Tuple2.apply[Short, Long](timeBin, z3) }; val timeBin: Short = x$6._1; val z3: Long = x$6._2; Z3Histogram.this.binMap.getOrElseUpdate(timeBin, Z3Histogram.this.newBins).add(scala.Predef.long2Long(z3), 1L) }
110 13829 4234 - 4491 Try <nosymbol> try { <synthetic> <artifact> private[this] val x$6: (Short, Long) = (Z3Histogram.this.toKey(geom, dtg, false): (Short, Long) @unchecked) match { case (_1: Short, _2: Long)(Short, Long)((timeBin @ _), (z3 @ _)) => scala.Tuple2.apply[Short, Long](timeBin, z3) }; val timeBin: Short = x$6._1; val z3: Long = x$6._2; Z3Histogram.this.binMap.getOrElseUpdate(timeBin, Z3Histogram.this.newBins).add(scala.Predef.long2Long(z3), 1L) } catch { case (e @ (_: Exception)) => (if (Z3Histogram.this.logger.underlying.isWarnEnabled()) Z3Histogram.this.logger.underlying.warn("Error observing geom \'{}\' and date \'{}\': {}", (geom: AnyRef), (dtg: AnyRef), (e.toString(): AnyRef)) else (): Unit) }
111 13821 4253 - 4253 Select scala.Tuple2._1 x$6._1
111 13822 4262 - 4262 Select scala.Tuple2._2 x$6._2
112 13823 4342 - 4349 Select org.locationtech.geomesa.utils.stats.Z3Histogram.newBins Z3Histogram.this.newBins
112 13824 4355 - 4357 ApplyImplicitView scala.Predef.long2Long scala.Predef.long2Long(z3)
112 13825 4359 - 4361 Literal <nosymbol> 1L
112 13826 4310 - 4362 Apply org.locationtech.geomesa.utils.stats.BinnedArray.add Z3Histogram.this.binMap.getOrElseUpdate(timeBin, Z3Histogram.this.newBins).add(scala.Predef.long2Long(z3), 1L)
114 13828 4408 - 4483 Typed <nosymbol> (if (Z3Histogram.this.logger.underlying.isWarnEnabled()) Z3Histogram.this.logger.underlying.warn("Error observing geom \'{}\' and date \'{}\': {}", (geom: AnyRef), (dtg: AnyRef), (e.toString(): AnyRef)) else (): Unit)
120 13832 4588 - 4589 Select org.locationtech.geomesa.utils.stats.Z3Histogram.g Z3Histogram.this.g
120 13833 4572 - 4613 TypeApply scala.Any.asInstanceOf sf.getAttribute(Z3Histogram.this.g).asInstanceOf[org.locationtech.jts.geom.Geometry]
121 13834 4645 - 4646 Select org.locationtech.geomesa.utils.stats.Z3Histogram.d Z3Histogram.this.d
121 13835 4629 - 4666 TypeApply scala.Any.asInstanceOf sf.getAttribute(Z3Histogram.this.d).asInstanceOf[java.util.Date]
122 13836 4683 - 4687 Literal <nosymbol> null
122 13837 4691 - 4702 Apply java.lang.Object.!= dtg.!=(null)
122 13838 4675 - 4702 Apply scala.Boolean.&& geom.!=(null).&&(dtg.!=(null))
122 13848 4671 - 4671 Literal <nosymbol> ()
122 13849 4671 - 4671 Block <nosymbol> ()
123 13845 4726 - 4830 Block <nosymbol> { <synthetic> <artifact> private[this] val x$7: (Short, Long) = (Z3Histogram.this.toKey(geom, dtg, true): (Short, Long) @unchecked) match { case (_1: Short, _2: Long)(Short, Long)((timeBin @ _), (z3 @ _)) => scala.Tuple2.apply[Short, Long](timeBin, z3) }; val timeBin: Short = x$7._1; val z3: Long = x$7._2; Z3Histogram.this.binMap.get(timeBin).foreach[Unit](((x$8: org.locationtech.geomesa.utils.stats.BinnedArray[Long]) => x$8.add(scala.Predef.long2Long(z3), -1L))) }
123 13847 4712 - 4962 Try <nosymbol> try { <synthetic> <artifact> private[this] val x$7: (Short, Long) = (Z3Histogram.this.toKey(geom, dtg, true): (Short, Long) @unchecked) match { case (_1: Short, _2: Long)(Short, Long)((timeBin @ _), (z3 @ _)) => scala.Tuple2.apply[Short, Long](timeBin, z3) }; val timeBin: Short = x$7._1; val z3: Long = x$7._2; Z3Histogram.this.binMap.get(timeBin).foreach[Unit](((x$8: org.locationtech.geomesa.utils.stats.BinnedArray[Long]) => x$8.add(scala.Predef.long2Long(z3), -1L))) } catch { case (e @ (_: Exception)) => (if (Z3Histogram.this.logger.underlying.isWarnEnabled()) Z3Histogram.this.logger.underlying.warn("Error un-observing geom \'{}\' and date \'{}\': {}", (geom: AnyRef), (dtg: AnyRef), (e.toString(): AnyRef)) else (): Unit) }
124 13839 4731 - 4731 Select scala.Tuple2._1 x$7._1
124 13840 4740 - 4740 Select scala.Tuple2._2 x$7._2
125 13841 4821 - 4823 ApplyImplicitView scala.Predef.long2Long scala.Predef.long2Long(z3)
125 13842 4825 - 4828 Literal <nosymbol> -1L
125 13843 4815 - 4829 Apply org.locationtech.geomesa.utils.stats.BinnedArray.add x$8.add(scala.Predef.long2Long(z3), -1L)
125 13844 4787 - 4830 Apply scala.Option.foreach Z3Histogram.this.binMap.get(timeBin).foreach[Unit](((x$8: org.locationtech.geomesa.utils.stats.BinnedArray[Long]) => x$8.add(scala.Predef.long2Long(z3), -1L)))
127 13846 4876 - 4954 Typed <nosymbol> (if (Z3Histogram.this.logger.underlying.isWarnEnabled()) Z3Histogram.this.logger.underlying.warn("Error un-observing geom \'{}\' and date \'{}\': {}", (geom: AnyRef), (dtg: AnyRef), (e.toString(): AnyRef)) else (): Unit)
136 13850 5147 - 5150 Select org.locationtech.geomesa.utils.stats.Z3Histogram.sft Z3Histogram.this.sft
136 13851 5152 - 5156 Select org.locationtech.geomesa.utils.stats.Z3Histogram.geom Z3Histogram.this.geom
136 13852 5158 - 5161 Select org.locationtech.geomesa.utils.stats.Z3Histogram.dtg Z3Histogram.this.dtg
136 13853 5163 - 5169 Select org.locationtech.geomesa.utils.stats.Z3Histogram.period Z3Histogram.this.period
136 13854 5171 - 5177 Select org.locationtech.geomesa.utils.stats.Z3Histogram.length Z3Histogram.this.length
136 13855 5131 - 5178 Apply org.locationtech.geomesa.utils.stats.Z3Histogram.<init> new Z3Histogram(Z3Histogram.this.sft, Z3Histogram.this.geom, Z3Histogram.this.dtg, Z3Histogram.this.period, Z3Histogram.this.length)
137 13856 5183 - 5195 Apply org.locationtech.geomesa.utils.stats.Z3Histogram.+= plus.+=(this)
138 13857 5200 - 5213 Apply org.locationtech.geomesa.utils.stats.Z3Histogram.+= plus.+=(other)
146 13858 5352 - 5364 Select org.locationtech.geomesa.utils.stats.Z3Histogram.length other.length
146 13859 5342 - 5364 Apply scala.Int.!= Z3Histogram.this.length.!=(other.length)
146 13862 5338 - 5338 Literal <nosymbol> ()
146 13863 5338 - 5338 Block <nosymbol> ()
147 13860 5374 - 5454 Throw <nosymbol> throw new scala.NotImplementedError("Can only add z3 histograms with the same length")
147 13861 5374 - 5454 Block <nosymbol> throw new scala.NotImplementedError("Can only add z3 histograms with the same length")
149 13880 5465 - 5771 Apply scala.collection.IterableLike.foreach other.binMap.foreach[Any](((x0$1: (Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x0$1 match { case (_1: Short, _2: org.locationtech.geomesa.utils.stats.BinnedArray[Long])(Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])((w @ _), (bins @ _)) => Z3Histogram.this.binMap.get(w) match { case scala.None => Z3Histogram.this.binMap.put(w, bins) case (value: org.locationtech.geomesa.utils.stats.BinnedArray[Long])Some[org.locationtech.geomesa.utils.stats.BinnedArray[Long]]((b @ _)) => { var i: Int = 0; while$1(){ if (i.<(b.length)) { { { <synthetic> val ev$1: Int = i; b.counts.update(ev$1, b.counts.apply(ev$1).+(bins.counts.apply(i))) }; i = i.+(1) }; while$1() } else () } } } }))
150 13864 5512 - 5525 Apply scala.collection.MapLike.get Z3Histogram.this.binMap.get(w)
150 13879 5512 - 5765 Match <nosymbol> Z3Histogram.this.binMap.get(w) match { case scala.None => Z3Histogram.this.binMap.put(w, bins) case (value: org.locationtech.geomesa.utils.stats.BinnedArray[Long])Some[org.locationtech.geomesa.utils.stats.BinnedArray[Long]]((b @ _)) => { var i: Int = 0; while$1(){ if (i.<(b.length)) { { { <synthetic> val ev$1: Int = i; b.counts.update(ev$1, b.counts.apply(ev$1).+(bins.counts.apply(i))) }; i = i.+(1) }; while$1() } else () } } }
151 13865 5555 - 5574 Apply scala.collection.mutable.MapLike.put Z3Histogram.this.binMap.put(w, bins)
151 13866 5555 - 5574 Block scala.collection.mutable.MapLike.put Z3Histogram.this.binMap.put(w, bins)
152 13878 5629 - 5757 Block <nosymbol> { var i: Int = 0; while$1(){ if (i.<(b.length)) { { { <synthetic> val ev$1: Int = i; b.counts.update(ev$1, b.counts.apply(ev$1).+(bins.counts.apply(i))) }; i = i.+(1) }; while$1() } else () } }
153 13867 5650 - 5651 Literal <nosymbol> 0
154 13868 5673 - 5681 Select org.locationtech.geomesa.utils.stats.BinnedArray.length b.length
154 13869 5669 - 5681 Apply scala.Int.< i.<(b.length)
154 13874 5683 - 5683 Apply org.locationtech.geomesa.utils.stats.Z3Histogram.while$1 while$1()
154 13875 5683 - 5757 Block <nosymbol> { { { <synthetic> val ev$1: Int = i; b.counts.update(ev$1, b.counts.apply(ev$1).+(bins.counts.apply(i))) }; i = i.+(1) }; while$1() }
154 13876 5662 - 5662 Literal <nosymbol> ()
154 13877 5662 - 5662 Block <nosymbol> ()
155 13870 5712 - 5726 Apply scala.Array.apply bins.counts.apply(i)
155 13871 5697 - 5726 Apply scala.Long.+ b.counts.apply(ev$1).+(bins.counts.apply(i))
155 13872 5697 - 5726 Apply scala.Array.update b.counts.update(ev$1, b.counts.apply(ev$1).+(bins.counts.apply(i)))
156 13873 5739 - 5745 Apply scala.Int.+ i.+(1)
163 13881 5836 - 5840 Select scala.Tuple2._1 x$9._1
163 13882 5835 - 5835 Select scala.math.Ordering.Short math.this.Ordering.Short
164 13883 5900 - 5912 Apply scala.Short.box scala.Short.box(p)
164 13884 5874 - 5913 Apply java.lang.String.format java.lang.String.format(Z3Histogram.this.jsonFormat, scala.Short.box(p))
164 13885 5873 - 5920 Apply scala.Tuple2.apply scala.Tuple2.apply[String, org.locationtech.geomesa.utils.stats.BinnedArray[Long]](java.lang.String.format(Z3Histogram.this.jsonFormat, scala.Short.box(p)), bins)
164 13886 5873 - 5920 Block scala.Tuple2.apply scala.Tuple2.apply[String, org.locationtech.geomesa.utils.stats.BinnedArray[Long]](java.lang.String.format(Z3Histogram.this.jsonFormat, scala.Short.box(p)), bins)
164 13887 5853 - 5853 TypeApply scala.collection.Seq.canBuildFrom collection.this.Seq.canBuildFrom[(String, org.locationtech.geomesa.utils.stats.BinnedArray[Long])]
165 13888 5974 - 5980 Literal <nosymbol> "bins"
165 13889 5984 - 5995 Select org.locationtech.geomesa.utils.stats.BinnedArray.counts bins.counts
165 13890 5974 - 5995 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[String]("bins").->[Array[Long]](bins.counts)
165 13891 5970 - 5996 Apply scala.collection.generic.GenMapFactory.apply scala.Predef.Map.apply[String, Array[Long]](scala.Predef.ArrowAssoc[String]("bins").->[Array[Long]](bins.counts))
165 13892 5962 - 5996 Apply scala.Predef.ArrowAssoc.-> scala.Predef.ArrowAssoc[String](label).->[scala.collection.immutable.Map[String,Array[Long]]](scala.Predef.Map.apply[String, Array[Long]](scala.Predef.ArrowAssoc[String]("bins").->[Array[Long]](bins.counts)))
165 13893 5958 - 5997 Apply scala.collection.generic.GenMapFactory.apply scala.Predef.Map.apply[String, scala.collection.immutable.Map[String,Array[Long]]](scala.Predef.ArrowAssoc[String](label).->[scala.collection.immutable.Map[String,Array[Long]]](scala.Predef.Map.apply[String, Array[Long]](scala.Predef.ArrowAssoc[String]("bins").->[Array[Long]](bins.counts))))
165 13894 5958 - 5997 Block scala.collection.generic.GenMapFactory.apply scala.Predef.Map.apply[String, scala.collection.immutable.Map[String,Array[Long]]](scala.Predef.ArrowAssoc[String](label).->[scala.collection.immutable.Map[String,Array[Long]]](scala.Predef.Map.apply[String, Array[Long]](scala.Predef.ArrowAssoc[String]("bins").->[Array[Long]](bins.counts))))
165 13895 5934 - 5934 TypeApply scala.collection.Seq.canBuildFrom collection.this.Seq.canBuildFrom[scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Array[Long]]]]
165 13896 5816 - 5999 ApplyToImplicitArgs scala.collection.TraversableLike.map Z3Histogram.this.binMap.toSeq.sortBy[Short](((x$9: (Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x$9._1))(math.this.Ordering.Short).map[(String, org.locationtech.geomesa.utils.stats.BinnedArray[Long]), Seq[(String, org.locationtech.geomesa.utils.stats.BinnedArray[Long])]](((x0$1: (Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x0$1 match { case (_1: Short, _2: org.locationtech.geomesa.utils.stats.BinnedArray[Long])(Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])((p @ _), (bins @ _)) => scala.Tuple2.apply[String, org.locationtech.geomesa.utils.stats.BinnedArray[Long]](java.lang.String.format(Z3Histogram.this.jsonFormat, scala.Short.box(p)), bins) }))(collection.this.Seq.canBuildFrom[(String, org.locationtech.geomesa.utils.stats.BinnedArray[Long])]).map[scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Array[Long]]], Any](((x0$2: (String, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x0$2 match { case (_1: String, _2: org.locationtech.geomesa.utils.stats.BinnedArray[Long])(String, org.locationtech.geomesa.utils.stats.BinnedArray[Long])((label @ _), (bins @ _)) => scala.Predef.Map.apply[String, scala.collection.immutable.Map[String,Array[Long]]](scala.Predef.ArrowAssoc[String](label).->[scala.collection.immutable.Map[String,Array[Long]]](scala.Predef.Map.apply[String, Array[Long]](scala.Predef.ArrowAssoc[String]("bins").->[Array[Long]](bins.counts)))) }))(collection.this.Seq.canBuildFrom[scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Array[Long]]]])
167 13897 6056 - 6064 Select org.locationtech.geomesa.utils.stats.BinnedArray.counts x$10.counts
167 13898 6072 - 6078 Apply scala.Long.== x$11.==(0)
167 13899 6056 - 6079 Apply scala.collection.IndexedSeqOptimized.forall scala.Predef.longArrayOps(x$10.counts).forall(((x$11: Long) => x$11.==(0)))
167 13900 6035 - 6080 Apply scala.collection.IterableLike.forall Z3Histogram.this.binMap.values.forall(((x$10: org.locationtech.geomesa.utils.stats.BinnedArray[Long]) => scala.Predef.longArrayOps(x$10.counts).forall(((x$11: Long) => x$11.==(0)))))
169 13901 6135 - 6144 Apply org.locationtech.geomesa.utils.stats.BinnedArray.clear x$12.clear()
169 13902 6113 - 6145 Apply scala.collection.IterableLike.foreach Z3Histogram.this.binMap.values.foreach[Unit](((x$12: org.locationtech.geomesa.utils.stats.BinnedArray[Long]) => x$12.clear()))
173 13903 6254 - 6260 Select org.locationtech.geomesa.utils.stats.Z3Histogram.g that.g
173 13904 6269 - 6275 Select org.locationtech.geomesa.utils.stats.Z3Histogram.d that.d
173 13905 6264 - 6275 Apply scala.Int.== Z3Histogram.this.d.==(that.d)
173 13906 6289 - 6300 Select org.locationtech.geomesa.utils.stats.Z3Histogram.period that.period
173 13907 6279 - 6300 Apply java.lang.Object.== Z3Histogram.this.period.==(that.period)
174 13908 6324 - 6335 Select org.locationtech.geomesa.utils.stats.Z3Histogram.length that.length
174 13909 6314 - 6335 Apply scala.Int.== Z3Histogram.this.length.==(that.length)
174 13910 6356 - 6374 Select scala.collection.MapLike.keySet that.binMap.keySet
174 13911 6339 - 6374 Apply java.lang.Object.== Z3Histogram.this.binMap.keySet.==(that.binMap.keySet)
174 13917 6249 - 6483 Apply scala.Boolean.&& Z3Histogram.this.g.==(that.g).&&(Z3Histogram.this.d.==(that.d)).&&(Z3Histogram.this.period.==(that.period)).&&(Z3Histogram.this.length.==(that.length)).&&(Z3Histogram.this.binMap.keySet.==(that.binMap.keySet)).&&(Z3Histogram.this.binMap.forall(((x0$1: (Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x0$1 match { case (_1: Short, _2: org.locationtech.geomesa.utils.stats.BinnedArray[Long])(Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])((w @ _), (bins @ _)) => java.util.Arrays.equals(bins.counts, that.binMap.apply(w).counts) })))
174 13918 6249 - 6483 Block scala.Boolean.&& Z3Histogram.this.g.==(that.g).&&(Z3Histogram.this.d.==(that.d)).&&(Z3Histogram.this.period.==(that.period)).&&(Z3Histogram.this.length.==(that.length)).&&(Z3Histogram.this.binMap.keySet.==(that.binMap.keySet)).&&(Z3Histogram.this.binMap.forall(((x0$1: (Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x0$1 match { case (_1: Short, _2: org.locationtech.geomesa.utils.stats.BinnedArray[Long])(Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])((w @ _), (bins @ _)) => java.util.Arrays.equals(bins.counts, that.binMap.apply(w).counts) })))
175 13912 6446 - 6457 Select org.locationtech.geomesa.utils.stats.BinnedArray.counts bins.counts
175 13913 6459 - 6480 Select org.locationtech.geomesa.utils.stats.BinnedArray.counts that.binMap.apply(w).counts
175 13914 6422 - 6481 Apply java.util.Arrays.equals java.util.Arrays.equals(bins.counts, that.binMap.apply(w).counts)
175 13915 6422 - 6481 Block java.util.Arrays.equals java.util.Arrays.equals(bins.counts, that.binMap.apply(w).counts)
175 13916 6388 - 6483 Apply scala.collection.IterableLike.forall Z3Histogram.this.binMap.forall(((x0$1: (Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])) => x0$1 match { case (_1: Short, _2: org.locationtech.geomesa.utils.stats.BinnedArray[Long])(Short, org.locationtech.geomesa.utils.stats.BinnedArray[Long])((w @ _), (bins @ _)) => java.util.Arrays.equals(bins.counts, that.binMap.apply(w).counts) }))
176 13919 6498 - 6503 Literal <nosymbol> false
176 13920 6498 - 6503 Block <nosymbol> false
182 13921 6552 - 6587 Apply org.geotools.geometry.jts.JTSFactoryFinder.getGeometryFactory org.geotools.geometry.jts.JTSFactoryFinder.getGeometryFactory()
184 13922 6612 - 6650 TypeApply scala.Any.asInstanceOf org.locationtech.geomesa.utils.stats.MinMax.MinMaxGeometry.min.asInstanceOf[org.locationtech.jts.geom.Point]
185 13923 6674 - 6712 TypeApply scala.Any.asInstanceOf org.locationtech.geomesa.utils.stats.MinMax.MinMaxGeometry.max.asInstanceOf[org.locationtech.jts.geom.Point]