Skip to content

Commit eb32e18

Browse files
authored
Merge pull request #377 from jamesmcclain/feature/timeseries
Time Series
2 parents 7fbd8d8 + 8017e9b commit eb32e18

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

geopyspark-backend/geotrellis/src/main/scala/geopyspark/geotrellis/TemporalTiledRasterLayer.scala

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ import org.apache.spark.rdd._
4343
import org.apache.spark.SparkContext._
4444

4545
import java.util.ArrayList
46+
import java.time.ZonedDateTime
47+
4648
import scala.reflect._
4749
import scala.collection.JavaConverters._
4850

@@ -90,6 +92,78 @@ class TemporalTiledRasterLayer(
9092
TemporalTiledRasterLayer(zoomLevel, multiBand)
9193
}
9294

95+
private def wkbsToMultiPolygons(wkbs: java.util.ArrayList[Array[Byte]]) = {
96+
wkbs
97+
.asScala.map({ wkb => WKB.read(wkb) })
98+
.flatMap({
99+
case p: Polygon => Some(MultiPolygon(p))
100+
case m: MultiPolygon => Some(m)
101+
case _ => None
102+
})
103+
}
104+
105+
private def wkbsToMultiPolygon(wkbs: java.util.ArrayList[Array[Byte]]) =
106+
MultiPolygon(
107+
wkbsToMultiPolygons(wkbs)
108+
.map({ mp => mp.polygons })
109+
.foldLeft(List.empty[Polygon])(_ ++ _)
110+
)
111+
112+
def sumSeries(
113+
wkbs: java.util.ArrayList[Array[Byte]]
114+
): Array[(ZonedDateTime, Double)] = {
115+
val polygon: MultiPolygon = wkbsToMultiPolygon(wkbs)
116+
val metadata = rdd.metadata
117+
ContextRDD(rdd.mapValues({ m => m.bands(0) }), metadata)
118+
.sumSeries(polygon)
119+
.toArray
120+
.sortWith({ (t1, t2) => (t1._1.compareTo(t2._1) <= 0) })
121+
}
122+
123+
def minSeries(
124+
wkbs: java.util.ArrayList[Array[Byte]]
125+
): Array[(ZonedDateTime, Double)] = {
126+
val polygon: MultiPolygon = wkbsToMultiPolygon(wkbs)
127+
val metadata = rdd.metadata
128+
ContextRDD(rdd.mapValues({ m => m.bands(0) }), metadata)
129+
.minSeries(polygon)
130+
.toArray
131+
.sortWith({ (t1, t2) => (t1._1.compareTo(t2._1) <= 0) })
132+
}
133+
134+
def maxSeries(
135+
wkbs: java.util.ArrayList[Array[Byte]]
136+
): Array[(ZonedDateTime, Double)] = {
137+
val polygon: MultiPolygon = wkbsToMultiPolygon(wkbs)
138+
val metadata = rdd.metadata
139+
ContextRDD(rdd.mapValues({ m => m.bands(0) }), metadata)
140+
.maxSeries(polygon)
141+
.toArray
142+
.sortWith({ (t1, t2) => (t1._1.compareTo(t2._1) <= 0) })
143+
}
144+
145+
def meanSeries(
146+
wkbs: java.util.ArrayList[Array[Byte]]
147+
): Array[(ZonedDateTime, Double)] = {
148+
val polygon: MultiPolygon = wkbsToMultiPolygon(wkbs)
149+
val metadata = rdd.metadata
150+
ContextRDD(rdd.mapValues({ m => m.bands(0) }), metadata)
151+
.meanSeries(polygon)
152+
.toArray
153+
.sortWith({ (t1, t2) => (t1._1.compareTo(t2._1) <= 0) })
154+
}
155+
156+
def histogramSeries(
157+
wkbs: java.util.ArrayList[Array[Byte]]
158+
): Array[(ZonedDateTime, Histogram[Double])] = {
159+
val polygon: MultiPolygon = wkbsToMultiPolygon(wkbs)
160+
val metadata = rdd.metadata
161+
ContextRDD(rdd.mapValues({ m => m.bands(0) }), metadata)
162+
.histogramSeries(polygon)
163+
.toArray
164+
.sortWith({ (t1, t2) => (t1._1.compareTo(t2._1) <= 0) })
165+
}
166+
93167
def reproject(targetCRS: String, resampleMethod: ResampleMethod): TemporalTiledRasterLayer = {
94168
val crs = TileLayer.getCRS(targetCRS).get
95169
val (zoom, reprojected) = rdd.reproject(crs, rdd.metadata.layout, resampleMethod)

geopyspark/geotrellis/layer.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,36 @@ def save_stitched(self, path, crop_bounds=None, crop_dimensions=None):
11331133
else:
11341134
self.srdd.save_stitched(path)
11351135

1136+
def star_series(self, geometries, fn):
1137+
if not self.layer_type == LayerType.SPACETIME:
1138+
raise ValueError("Only Spatio-Temporal layers can use this function.")
1139+
1140+
if not isinstance(geometries, list):
1141+
geometries = [geometries]
1142+
wkbs = [shapely.wkb.dumps(g) for g in geometries]
1143+
1144+
return [(t._1(), t._2()) for t in list(fn(wkbs))]
1145+
1146+
def histogram_series(self, geometries):
1147+
fn = self.srdd.histogramSeries
1148+
return self.star_series(geometries, fn)
1149+
1150+
def mean_series(self, geometries):
1151+
fn = self.srdd.meanSeries
1152+
return self.star_series(geometries, fn)
1153+
1154+
def max_series(self, geometries):
1155+
fn = self.srdd.maxSeries
1156+
return self.star_series(geometries, fn)
1157+
1158+
def min_series(self, geometries):
1159+
fn = self.srdd.minSeries
1160+
return self.star_series(geometries, fn)
1161+
1162+
def sum_series(self, geometries):
1163+
fn = self.srdd.sumSeries
1164+
return self.star_series(geometries, fn)
1165+
11361166
def mask(self, geometries):
11371167
"""Masks the ``TiledRasterLayer`` so that only values that intersect the geometries will
11381168
be available.

0 commit comments

Comments
 (0)