/**
* This file is hereby placed into the Public Domain. This means anyone is
* free to do whatever they wish with this file.
*/
package mil.nga.giat.process.elasticsearch;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.IntStream;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.davidmoten.geo.GeoHash;
import com.github.davidmoten.geo.LatLong;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.vividsolutions.jts.geom.Envelope;
public class GeoHashGridTest {
private static final String BUCKET_NAME = "bucket1";
private static final int DOC_COUNT = 11;
private static final int VALUE = 25;
private static final String METRIC_KEY = "metric_key";
private static final String VALUE_KEY = "value_key";
private static final String AGG_KEY = "nested_agg";
private static final int[] AGG_RESULTS = {1, 2, 3, 4, 5};
private static final Map<String,Object> SIMPLE_BUCKET = TestUtil.createDocCountBucket(BUCKET_NAME, DOC_COUNT);
private static final Map<String,Object> METRIC_BUCKET = TestUtil.createMetricBucket(DOC_COUNT, METRIC_KEY, VALUE_KEY, VALUE);
private static final Map<String,Object> AGG_BUCKET = TestUtil.createAggBucket(AGG_KEY, AGG_RESULTS);
private SimpleFeatureCollection features;
private GeoHashGrid geohashGrid;
private ObjectMapper mapper;
@Before
public void setup() {
this.geohashGrid = new BasicGeoHashGrid();
this.mapper = new ObjectMapper();
}
@Test
public void testGeoHashGridLowLonRange() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key",GeoHash.encodeHash(new LatLong(-89.9,-179.9),1),"doc_count",10)))
));
ReferencedEnvelope envelope = new ReferencedEnvelope(-360,180,-90,90,DefaultGeographicCRS.WGS84);
geohashGrid.initalize(envelope, features);
assertEquals(GeoHash.widthDegrees(1), geohashGrid.getCellWidth(), 1e-10);
assertEquals(GeoHash.heightDegrees(1), geohashGrid.getCellHeight(), 1e-10);
assertEquals(new Envelope(-360+GeoHash.widthDegrees(1)/2.,180-GeoHash.widthDegrees(1)/2.,-90+GeoHash.heightDegrees(1)/2.,90-GeoHash.heightDegrees(1)/2.), geohashGrid.getEnvelope());
int ny = (int) Math.round(180/geohashGrid.getCellHeight());
int nx = (int) Math.round(540/GeoHash.widthDegrees(1));
assertEquals(ny, geohashGrid.getGrid().length);
assertEquals(nx, geohashGrid.getGrid()[0].length);
}
@Test
public void testGeoHashGridHighLonRange() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key",GeoHash.encodeHash(new LatLong(-89.9,-179.9),1),"doc_count",10)))
));
ReferencedEnvelope envelope = new ReferencedEnvelope(360,540,-90,90,DefaultGeographicCRS.WGS84);
geohashGrid.initalize(envelope, features);
assertEquals(GeoHash.widthDegrees(1), geohashGrid.getCellWidth(), 1e-10);
assertEquals(GeoHash.heightDegrees(1), geohashGrid.getCellHeight(), 1e-10);
assertEquals(new Envelope(360+GeoHash.widthDegrees(1)/2.,540-GeoHash.widthDegrees(1)/2.,-90+GeoHash.heightDegrees(1)/2.,90-GeoHash.heightDegrees(1)/2.), geohashGrid.getEnvelope());
int ny = (int) Math.round(180/geohashGrid.getCellHeight());
int nx = (int) Math.round(180/GeoHash.widthDegrees(1));
assertEquals(ny, geohashGrid.getGrid().length);
assertEquals(nx, geohashGrid.getGrid()[0].length);
}
@Test
public void testGeoHashGrid() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key",GeoHash.encodeHash(new LatLong(-89.9,-179.9),1),"doc_count",10)))
));
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,DefaultGeographicCRS.WGS84);
geohashGrid.initalize(envelope, features);
assertEquals(GeoHash.widthDegrees(1), geohashGrid.getCellWidth(), 1e-10);
assertEquals(GeoHash.heightDegrees(1), geohashGrid.getCellHeight(), 1e-10);
assertEquals(new Envelope(-180+GeoHash.widthDegrees(1)/2.,180-GeoHash.widthDegrees(1)/2.,-90+GeoHash.heightDegrees(1)/2.,90-GeoHash.heightDegrees(1)/2.), geohashGrid.getEnvelope());
int ny = (int) Math.round(180/geohashGrid.getCellHeight());
int nx = (int) Math.round(360/GeoHash.widthDegrees(1));
float[][] expected = new float[ny][nx];
expected[ny-1][0] = 10;
assertEquals(ny, geohashGrid.getGrid().length);
assertEquals(nx, geohashGrid.getGrid()[0].length);
IntStream.range(0, ny).forEach(i->assertTrue(Arrays.equals(expected[i], geohashGrid.getGrid()[i])));
}
@Test
public void testGeoHashGrid_scaled() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key",GeoHash.encodeHash(new LatLong(-89.9,-179.9),1),"doc_count",20))),
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key",GeoHash.encodeHash(new LatLong(89.9,179.9),1),"doc_count",30)))
));
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,DefaultGeographicCRS.WGS84);
geohashGrid.setScale(new RasterScale(5f, 10f));
geohashGrid.initalize(envelope, features);
assertEquals(GeoHash.widthDegrees(1), geohashGrid.getCellWidth(), 1e-10);
assertEquals(GeoHash.heightDegrees(1), geohashGrid.getCellHeight(), 1e-10);
assertEquals(new Envelope(-180+GeoHash.widthDegrees(1)/2.,180-GeoHash.widthDegrees(1)/2.,-90+GeoHash.heightDegrees(1)/2.,90-GeoHash.heightDegrees(1)/2.), geohashGrid.getEnvelope());
int ny = (int) Math.round(180/geohashGrid.getCellHeight());
int nx = (int) Math.round(360/GeoHash.widthDegrees(1));
assertEquals(ny, geohashGrid.getGrid().length);
assertEquals(nx, geohashGrid.getGrid()[0].length);
float[][] expected = new float[ny][nx];
expected[0][7] = 10;
expected[ny-1][0] = 5;
IntStream.range(0, ny).forEach(i->assertTrue(Arrays.equals(geohashGrid.getGrid()[i], expected[i])));
}
@Test
public void testGeoHashGridWithProjectedEnvelope() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key",GeoHash.encodeHash(new LatLong(-89.9,-179.9),1),"doc_count",10)))
));
ReferencedEnvelope envelope = new ReferencedEnvelope(-19926188.85,19926188.85,-30240971.96,30240971.96, CRS.decode("EPSG:3857"));
geohashGrid.initalize(envelope, features);
assertEquals(new ReferencedEnvelope(-180,180,-90,90,DefaultGeographicCRS.WGS84), geohashGrid.getBoundingBox());
}
@Test
public void testGeoHashGridWithNoFeatures() throws Exception {
features = new DefaultFeatureCollection();
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,CRS.decode("EPSG:4326"));
geohashGrid.initalize(envelope, features);
IntStream.range(0, geohashGrid.getGrid().length).forEach(i->assertTrue(Arrays.equals(new float[geohashGrid.getGrid()[i].length], geohashGrid.getGrid()[i])));
}
@Test
public void testGeoHashGrid_emptyCellValue() throws Exception {
float emptyCellValue = -1.0f;
features = new DefaultFeatureCollection();
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,CRS.decode("EPSG:4326"));
geohashGrid.setEmptyCellValue(emptyCellValue);
geohashGrid.initalize(envelope, features);
IntStream.range(0, geohashGrid.getGrid().length).forEach(row-> {
IntStream.range(0, geohashGrid.getGrid()[row].length).forEach(column-> {
assertEquals(emptyCellValue, geohashGrid.getGrid()[row][column], 0.0);
});
});
}
@Test
public void testGeoHashGrid_nullEmptyCellValue() throws Exception {
features = new DefaultFeatureCollection();
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,CRS.decode("EPSG:4326"));
geohashGrid.setEmptyCellValue(null);
geohashGrid.initalize(envelope, features);
IntStream.range(0, geohashGrid.getGrid().length).forEach(row-> {
IntStream.range(0, geohashGrid.getGrid()[row].length).forEach(column-> {
assertEquals(0.0, geohashGrid.getGrid()[row][column], 0.0);
});
});
}
@Test
public void testGeoHashGridWithNoAggregations() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("aString", UUID.randomUUID().toString())
));
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,CRS.decode("EPSG:4326"));
geohashGrid.initalize(envelope, features);
IntStream.range(0, geohashGrid.getGrid().length).forEach(i->assertTrue(Arrays.equals(new float[geohashGrid.getGrid()[i].length], geohashGrid.getGrid()[i])));
}
@Test(expected=IllegalArgumentException.class)
public void testGeoHashGridWithNoDocCount() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key",GeoHash.encodeHash(new LatLong(-89.9,-179.9),1))))
));
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,CRS.decode("EPSG:4326"));
geohashGrid.initalize(envelope, features);
IntStream.range(0, geohashGrid.getGrid().length).forEach(i->assertTrue(Arrays.equals(new float[geohashGrid.getGrid()[i].length], geohashGrid.getGrid()[i])));
}
@Test
public void testGeoHashGridWithInvalidGeohash() throws Exception {
features = TestUtil.createAggregationFeatures(ImmutableList.of(
ImmutableMap.of("_aggregation", mapper.writeValueAsBytes(ImmutableMap.of("key","invalid","doc_count",10)))
));
ReferencedEnvelope envelope = new ReferencedEnvelope(-180,180,-90,90,CRS.decode("EPSG:4326"));
geohashGrid.initalize(envelope, features);
IntStream.range(0, geohashGrid.getGrid().length).forEach(i->assertTrue(Arrays.equals(new float[geohashGrid.getGrid()[i].length], geohashGrid.getGrid()[i])));
}
@Test
public void testPluckBucketName() {
String plucked = this.geohashGrid.pluckBucketName(SIMPLE_BUCKET);
assertEquals(BUCKET_NAME, plucked);
}
@Test
public void testPluckBucketName_doubleKey() {
Map<String,Object> bucket = new HashMap<>();
bucket.put(GeoHashGrid.BUCKET_NAME_KEY, 2.0);
bucket.put("doc_count", DOC_COUNT);
String plucked = this.geohashGrid.pluckBucketName(bucket);
assertEquals("2.0", plucked);
}
@Test(expected=IllegalArgumentException.class)
public void testPluckBucketName_invalidKey() {
Map<String,Object> bucket = new HashMap<>();
bucket.put("invalid", "invalid");
this.geohashGrid.pluckBucketName(bucket);
}
@Test
public void testPluckDocCount() {
Number plucked = this.geohashGrid.pluckDocCount(SIMPLE_BUCKET);
assertEquals(DOC_COUNT, plucked);
}
@Test
public void testPluckMetricValue() {
Number plucked = this.geohashGrid.pluckMetricValue(METRIC_BUCKET, METRIC_KEY, VALUE_KEY);
assertEquals(VALUE, plucked);
}
@Test
public void testPluckMetricValue_docCount() {
Number plucked = this.geohashGrid.pluckMetricValue(METRIC_BUCKET, null, null);
assertEquals(DOC_COUNT, plucked);
plucked = this.geohashGrid.pluckMetricValue(METRIC_BUCKET, "", null);
assertEquals(DOC_COUNT, plucked);
}
@Test(expected=IllegalArgumentException.class)
public void testPluckMetricValue_canNotFindMetricKey() {
this.geohashGrid.pluckMetricValue(METRIC_BUCKET, "noGonnaFindMe", VALUE_KEY);
}
@Test(expected=IllegalArgumentException.class)
public void testPluckMetricValue_canNotFindValueKey() {
this.geohashGrid.pluckMetricValue(METRIC_BUCKET, METRIC_KEY, "noGonnaFindMe");
}
@Test
public void testPluckAggBuckets() {
List<Map<String,Object>> buckets = this.geohashGrid.pluckAggBuckets(AGG_BUCKET, AGG_KEY);
assertEquals(AGG_RESULTS.length, buckets.size());
}
@Test(expected=IllegalArgumentException.class)
public void testPluckAggBuckets_canNotFindAggKey() {
this.geohashGrid.pluckAggBuckets(AGG_BUCKET, "noGonnaFindMe");
}
}