package mil.nga.giat.geowave.format.landsat8;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.opengis.feature.simple.SimpleFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import mil.nga.giat.geowave.core.cli.api.OperationParams;
import mil.nga.giat.geowave.format.landsat8.WRS2GeometryStore.WRS2Key;
public class AnalyzeRunner
{
private final static Logger LOGGER = LoggerFactory.getLogger(AnalyzeRunner.class);
protected Landsat8BasicCommandLineOptions landsatOptions = new Landsat8BasicCommandLineOptions();
public AnalyzeRunner(
final Landsat8BasicCommandLineOptions landsatOptions ) {
this.landsatOptions = landsatOptions;
}
protected void runInternal(
final OperationParams params )
throws Exception {
try {
try (BandFeatureIterator bands = new BandFeatureIterator(
landsatOptions.isOnlyScenesSinceLastRun(),
landsatOptions.isUseCachedScenes(),
landsatOptions.isNBestPerSpatial(),
landsatOptions.getNBestScenes(),
landsatOptions.getNBestBands(),
landsatOptions.getCqlFilter(),
landsatOptions.getWorkspaceDir())) {
final AnalysisInfo info = new AnalysisInfo();
String prevEntityId = null;
while (bands.hasNext()) {
final SimpleFeature band = bands.next();
final String entityId = (String) band.getAttribute(SceneFeatureIterator.ENTITY_ID_ATTRIBUTE_NAME);
if ((prevEntityId == null) || !prevEntityId.equals(entityId)) {
prevEntityId = entityId;
nextScene(
band,
info);
}
nextBand(
band,
info);
}
lastSceneComplete(info);
}
}
catch (final IOException e) {
LOGGER.error(
"",
e);
}
}
protected void nextScene(
final SimpleFeature firstBandOfScene,
final AnalysisInfo analysisInfo ) {
analysisInfo.nextScene(firstBandOfScene);
}
protected void nextBand(
final SimpleFeature band,
final AnalysisInfo analysisInfo ) {
analysisInfo.addBandInfo(band);
}
protected void lastSceneComplete(
final AnalysisInfo analysisInfo ) {
analysisInfo.printSceneInfo();
analysisInfo.printTotals();
}
protected static class AnalysisInfo
{
private final TreeMap<String, Float> bandIdToMbMap = new TreeMap<String, Float>();
private final TreeMap<String, SimpleFeature> entityBandIdToSimpleFeatureMap = new TreeMap<String, SimpleFeature>();
private int sceneCount = 0;
private final Set<WRS2Key> wrs2Keys = new HashSet<WRS2Key>();
private int minRow = Integer.MAX_VALUE;
private int minPath = Integer.MAX_VALUE;
private int maxRow = Integer.MIN_VALUE;
private int maxPath = Integer.MIN_VALUE;
private double minLat = Double.MAX_VALUE;
private double minLon = Double.MAX_VALUE;
private double maxLat = -Double.MAX_VALUE;
private double maxLon = -Double.MAX_VALUE;
private long startDate = Long.MAX_VALUE;
private long endDate = 0;
private float totalCloudCover = 0f;
private float minCloudCover = Float.MAX_VALUE;
private float maxCloudCover = -Float.MAX_VALUE;
private final Map<String, Integer> processingLevelCounts = new HashMap<String, Integer>();
private void nextScene(
final SimpleFeature currentBand ) {
printSceneInfo();
sceneCount++;
entityBandIdToSimpleFeatureMap.clear();
final int path = (int) currentBand.getAttribute(SceneFeatureIterator.PATH_ATTRIBUTE_NAME);
final int row = (int) currentBand.getAttribute(SceneFeatureIterator.ROW_ATTRIBUTE_NAME);
final float cloudCover = (float) currentBand.getAttribute(SceneFeatureIterator.CLOUD_COVER_ATTRIBUTE_NAME);
final String processingLevel = (String) currentBand
.getAttribute(SceneFeatureIterator.PROCESSING_LEVEL_ATTRIBUTE_NAME);
final Date date = (Date) currentBand.getAttribute(SceneFeatureIterator.ACQUISITION_DATE_ATTRIBUTE_NAME);
minRow = Math.min(
minRow,
row);
maxRow = Math.max(
maxRow,
row);
minPath = Math.min(
minPath,
path);
maxPath = Math.max(
maxPath,
path);
final Envelope env = ((Geometry) currentBand.getDefaultGeometry()).getEnvelopeInternal();
minLat = Math.min(
minLat,
env.getMinY());
maxLat = Math.max(
maxLat,
env.getMaxY());
minLon = Math.min(
minLon,
env.getMinX());
maxLon = Math.max(
maxLon,
env.getMaxX());
minCloudCover = Math.min(
minCloudCover,
cloudCover);
maxCloudCover = Math.max(
maxCloudCover,
cloudCover);
totalCloudCover += cloudCover;
Integer count = processingLevelCounts.get(processingLevel);
if (count == null) {
count = 0;
}
count++;
processingLevelCounts.put(
processingLevel,
count);
startDate = Math.min(
startDate,
date.getTime());
endDate = Math.max(
endDate,
date.getTime());
wrs2Keys.add(new WRS2Key(
path,
row));
}
private void printSceneInfo() {
if (sceneCount > 0) {
final SimpleDateFormat sdf = new SimpleDateFormat(
SceneFeatureIterator.AQUISITION_DATE_FORMAT);
boolean first = true;
for (final Entry<String, SimpleFeature> entry : entityBandIdToSimpleFeatureMap.entrySet()) {
final String bandId = entry.getKey();
final SimpleFeature feature = entry.getValue();
if (first) {
if (feature == null) {
throw new RuntimeException(
"feature is null");
}
// print scene info
System.out.println("\n<-- "
+ feature.getAttribute(SceneFeatureIterator.ENTITY_ID_ATTRIBUTE_NAME) + " -->");
System.out
.println("Acquisition Date: "
+ sdf.format(feature
.getAttribute(SceneFeatureIterator.ACQUISITION_DATE_ATTRIBUTE_NAME)));
System.out.println("Cloud Cover: "
+ feature.getAttribute(SceneFeatureIterator.CLOUD_COVER_ATTRIBUTE_NAME));
System.out.println("Scene Download URL: "
+ feature.getAttribute(SceneFeatureIterator.SCENE_DOWNLOAD_ATTRIBUTE_NAME));
first = false;
}
final float mb = (Float) feature.getAttribute(BandFeatureIterator.SIZE_ATTRIBUTE_NAME);
final String bandDownloadUrl = (String) feature
.getAttribute(BandFeatureIterator.BAND_DOWNLOAD_ATTRIBUTE_NAME);
// print band info
System.out.println("Band " + bandId + ": " + mb + " MB, download at " + bandDownloadUrl);
Float totalMb = bandIdToMbMap.get(bandId);
if (totalMb == null) {
totalMb = 0.0f;
}
totalMb += mb;
bandIdToMbMap.put(
bandId,
totalMb);
}
}
}
private void addBandInfo(
final SimpleFeature band ) {
entityBandIdToSimpleFeatureMap.put(
(String) band.getAttribute(BandFeatureIterator.BAND_ATTRIBUTE_NAME),
band);
}
private void printTotals() {
System.out.println("\n<-- Totals -->");
System.out.println("Total Scenes: " + sceneCount);
if (sceneCount > 0) {
final SimpleDateFormat sdf = new SimpleDateFormat(
SceneFeatureIterator.AQUISITION_DATE_FORMAT);
System.out.println("Date Range: [" + sdf.format(new Date(
startDate)) + ", " + sdf.format(new Date(
endDate)) + "]");
System.out.println("Cloud Cover Range: [" + minCloudCover + ", " + maxCloudCover + "]");
System.out.println("Average Cloud Cover: " + (totalCloudCover / sceneCount));
System.out.println("WRS2 Paths/Rows covered: " + wrs2Keys.size());
System.out.println("Row Range: [" + minRow + ", " + maxRow + "]");
System.out.println("Path Range: [" + minPath + ", " + maxPath + "]");
System.out.println("Latitude Range: [" + minLat + ", " + maxLat + "]");
System.out.println("Longitude Range: [" + minLon + ", " + maxLon + "]");
final StringBuffer strBuf = new StringBuffer(
"Processing Levels: ");
boolean includeSceneCount = false;
boolean first = true;
if (processingLevelCounts.size() > 1) {
includeSceneCount = true;
}
for (final Entry<String, Integer> entry : processingLevelCounts.entrySet()) {
if (!first) {
strBuf.append(", ");
}
else {
first = false;
}
strBuf.append(entry.getKey());
if (includeSceneCount) {
strBuf.append(" (" + entry.getValue() + " scenes)");
}
}
for (final Entry<String, Float> entry : bandIdToMbMap.entrySet()) {
final String bandId = entry.getKey();
final float mb = Math.round(entry.getValue() * 10) / 10f;
final String avg;
if (sceneCount > 1) {
avg = "(avg. " + (Math.round((entry.getValue() * 10) / sceneCount) / 10f) + " MB)";
}
else {
avg = "";
}
System.out.println("Band " + bandId + ": " + mb + " MB " + avg);
}
}
}
}
}