Skip to content

Commit

Permalink
Sentinel2 client module to ingest Sentinel-2 imagery from Theia and A…
Browse files Browse the repository at this point in the history
…WS providers (#1326)

* Delete Theia client module

It will be replaced by a new more generic Sentinel2 client module

* Sentinel2 client module to ingest Sentinel-2 imagery from Theia and AWS providers

* Fix Travis tests running in Linux OS
  • Loading branch information
ahuarte47 authored and rfecher committed May 29, 2018
1 parent 2789e12 commit 4b897c4
Show file tree
Hide file tree
Showing 48 changed files with 2,543 additions and 1,282 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -27,6 +27,7 @@ cache:
directories:
- $HOME/.m2
- test/landsat8
- test/sentinel2
- test/target/temp/gdal
install:
- .utility/pull-dev-resources.sh
Expand Down
2 changes: 1 addition & 1 deletion deploy/pom.xml
Expand Up @@ -124,7 +124,7 @@
</dependency>
<dependency>
<groupId>mil.nga.giat</groupId>
<artifactId>geowave-cli-theia</artifactId>
<artifactId>geowave-cli-sentinel2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
Expand Down
343 changes: 343 additions & 0 deletions extensions/cli/sentinel2/README.md

Large diffs are not rendered by default.

Expand Up @@ -13,9 +13,9 @@
<tools.scope>compile</tools.scope>
</properties>

<artifactId>geowave-cli-theia</artifactId>
<name>GeoWave Theia Operations</name>
<description>GeoWave support for public Theia data</description>
<artifactId>geowave-cli-sentinel2</artifactId>
<name>GeoWave Sentinel2 Operations</name>
<description>GeoWave support for public Sentinel2 data</description>
<dependencies>
<dependency>
<groupId>it.geosolutions.imageio-ext</groupId>
Expand Down
Expand Up @@ -8,7 +8,7 @@
* Version 2.0 which accompanies this distribution and is available at
* http://www.apache.org/licenses/LICENSE-2.0.txt
******************************************************************************/
package mil.nga.giat.geowave.format.theia;
package mil.nga.giat.geowave.format.sentinel2;

import java.io.IOException;
import java.text.SimpleDateFormat;
Expand All @@ -26,36 +26,37 @@
import com.vividsolutions.jts.geom.Geometry;

import mil.nga.giat.geowave.core.cli.api.OperationParams;
import mil.nga.giat.geowave.format.theia.AnalyzeRunner;
import mil.nga.giat.geowave.format.theia.BandFeatureIterator;
import mil.nga.giat.geowave.format.theia.TheiaBasicCommandLineOptions;
import mil.nga.giat.geowave.format.theia.SceneFeatureIterator;
import mil.nga.giat.geowave.format.sentinel2.AnalyzeRunner;
import mil.nga.giat.geowave.format.sentinel2.BandFeatureIterator;
import mil.nga.giat.geowave.format.sentinel2.SceneFeatureIterator;
import mil.nga.giat.geowave.format.sentinel2.Sentinel2BasicCommandLineOptions;

public class AnalyzeRunner
{
private final static Logger LOGGER = LoggerFactory.getLogger(AnalyzeRunner.class);

protected TheiaBasicCommandLineOptions theiaOptions = new TheiaBasicCommandLineOptions();
protected Sentinel2BasicCommandLineOptions sentinel2Options = new Sentinel2BasicCommandLineOptions();

public AnalyzeRunner(
final TheiaBasicCommandLineOptions theiaOptions ) {
this.theiaOptions = theiaOptions;
final Sentinel2BasicCommandLineOptions options ) {
this.sentinel2Options = options;
}

protected void runInternal(
final OperationParams params )
throws Exception {
try {
try (BandFeatureIterator bands = new BandFeatureIterator(
theiaOptions.collection(),
theiaOptions.platform(),
theiaOptions.location(),
theiaOptions.startDate(),
theiaOptions.endDate(),
theiaOptions.orbitNumber(),
theiaOptions.relativeOrbitNumber(),
theiaOptions.getCqlFilter(),
theiaOptions.getWorkspaceDir())) {
sentinel2Options.providerName(),
sentinel2Options.collection(),
sentinel2Options.platform(),
sentinel2Options.location(),
sentinel2Options.startDate(),
sentinel2Options.endDate(),
sentinel2Options.orbitNumber(),
sentinel2Options.relativeOrbitNumber(),
sentinel2Options.getCqlFilter(),
sentinel2Options.getWorkspaceDir())) {
final AnalysisInfo info = new AnalysisInfo();
String prevEntityId = null;

Expand Down Expand Up @@ -192,6 +193,8 @@ private void printSceneInfo() {
// print scene info
System.out.println("\n<-- "
+ feature.getAttribute(SceneFeatureIterator.PRODUCT_ID_ATTRIBUTE_NAME) + " -->");
System.out.println("Provider Name: "
+ feature.getAttribute(SceneFeatureIterator.PROVIDER_NAME_ATTRIBUTE_NAME));
System.out
.println("Acquisition Date: "
+ sdf.format(feature
Expand Down
Expand Up @@ -8,7 +8,7 @@
* Version 2.0 which accompanies this distribution and is available at
* http://www.apache.org/licenses/LICENSE-2.0.txt
******************************************************************************/
package mil.nga.giat.geowave.format.theia;
package mil.nga.giat.geowave.format.sentinel2;

import java.io.IOException;
import java.net.MalformedURLException;
Expand All @@ -33,39 +33,37 @@
import org.opengis.referencing.NoSuchAuthorityCodeException;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;

import mil.nga.giat.geowave.format.theia.BandFeatureIterator;
import mil.nga.giat.geowave.format.theia.SceneFeatureIterator;
import mil.nga.giat.geowave.format.sentinel2.BandFeatureIterator;
import mil.nga.giat.geowave.format.sentinel2.SceneFeatureIterator;

public class BandFeatureIterator implements
SimpleFeatureIterator
{
private static final String BANDS_TYPE_NAME = "theia-band";

// List of predefined attributes
public static final String BAND_ATTRIBUTE_NAME = "band";

private Iterator<SimpleFeature> iterator;
private final SceneFeatureIterator sceneIterator;

/**
* Returns the SimpleFeatureTypeBuilder which provides the schema of the
* Bands of the Theia repository.
* Default SimpleFeatureTypeBuilder which provides the Bands schema of a
* Sentinel2 provider.
*
* @return
* @throws NoSuchAuthorityCodeException
* @throws FactoryException
*/
public static SimpleFeatureTypeBuilder defaultBandFeatureTypeBuilder()
public static SimpleFeatureTypeBuilder defaultBandFeatureTypeBuilder(
String typeName )
throws NoSuchAuthorityCodeException,
FactoryException {
SimpleFeatureTypeBuilder sceneBuilder = SceneFeatureIterator.defaultSceneFeatureTypeBuilder();
SimpleFeatureTypeBuilder sceneBuilder = SceneFeatureIterator.defaultSceneFeatureTypeBuilder(typeName);

SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
typeBuilder.init(sceneBuilder.buildFeatureType());
typeBuilder.setName(BANDS_TYPE_NAME);
typeBuilder.setName(typeName);
typeBuilder.setDefaultGeometry(SceneFeatureIterator.SHAPE_ATTRIBUTE_NAME);
typeBuilder.minOccurs(
1).maxOccurs(
Expand All @@ -78,6 +76,7 @@ public static SimpleFeatureTypeBuilder defaultBandFeatureTypeBuilder()
}

public BandFeatureIterator(
final String providerName,
final String collection,
final String platform,
final String location,
Expand All @@ -94,6 +93,7 @@ public BandFeatureIterator(
GeneralSecurityException {
this(
new SceneFeatureIterator(
providerName,
collection,
platform,
location,
Expand All @@ -119,7 +119,7 @@ private void init(
final Filter cqlFilter )
throws NoSuchAuthorityCodeException,
FactoryException {
final SimpleFeatureTypeBuilder typeBuilder = BandFeatureIterator.defaultBandFeatureTypeBuilder();
final SimpleFeatureTypeBuilder typeBuilder = sceneIterator.getProvider().bandFeatureTypeBuilder();
final SimpleFeatureType bandType = typeBuilder.buildFeatureType();

Iterator<SimpleFeature> featureIterator = new FeatureIteratorIterator<SimpleFeature>(
Expand All @@ -141,7 +141,7 @@ private void init(
BAND_ATTRIBUTE_NAME)) {
featureIterator = Iterators.filter(
featureIterator,
new CqlFilterPredicate(
new SceneFeatureIterator.CqlFilterPredicate(
cqlFilter));
}
}
Expand Down Expand Up @@ -206,21 +206,4 @@ public Iterator<SimpleFeature> apply(
return bands.iterator();
}
}

private static class CqlFilterPredicate implements
Predicate<SimpleFeature>
{
private final Filter cqlFilter;

public CqlFilterPredicate(
final Filter cqlFilter ) {
this.cqlFilter = cqlFilter;
}

@Override
public boolean apply(
final SimpleFeature input ) {
return cqlFilter.evaluate(input);
}
}
}
@@ -0,0 +1,123 @@
/*******************************************************************************
* Copyright (c) 2013-2018 Contributors to the Eclipse Foundation
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License,
* Version 2.0 which accompanies this distribution and is available at
* http://www.apache.org/licenses/LICENSE-2.0.txt
******************************************************************************/
package mil.nga.giat.geowave.format.sentinel2;

import java.io.File;
import java.io.IOException;

import org.apache.hadoop.fs.FileUtil;
import org.opengis.feature.simple.SimpleFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DownloadRunner extends
AnalyzeRunner
{
private final static Logger LOGGER = LoggerFactory.getLogger(DownloadRunner.class);

private static final String DOWNLOAD_DIRECTORY = "scenes";

protected Sentinel2DownloadCommandLineOptions downloadOptions;

public DownloadRunner(
final Sentinel2BasicCommandLineOptions analyzeOptions,
final Sentinel2DownloadCommandLineOptions downloadOptions ) {
super(
analyzeOptions);
this.downloadOptions = downloadOptions;
}

@Override
protected void nextScene(
final SimpleFeature firstBandOfScene,
final AnalysisInfo analysisInfo ) {
super.nextScene(
firstBandOfScene,
analysisInfo);

final String providerName = sentinel2Options.providerName();
final String workspaceDir = sentinel2Options.getWorkspaceDir();
final boolean overwriteIfExists = downloadOptions.isOverwriteIfExists();
final String userIdent = downloadOptions.getUserIdent();
final String password = downloadOptions.getPassword();

Sentinel2ImageryProvider provider = Sentinel2ImageryProvider.getProvider(providerName);
if (provider == null) {
throw new RuntimeException(
"Unable to find '" + providerName + "' Sentinel2 provider");
}

// First steps to download, check state of scene directory
final File sceneDir = getSceneDirectory(
firstBandOfScene,
workspaceDir);
if (overwriteIfExists) {
if (sceneDir.exists() && !FileUtil.fullyDelete(sceneDir)) {
LOGGER.warn("Unable to delete dir '" + sceneDir.getAbsolutePath() + "'");
}
}
else if (sceneDir.exists()) {
return;
}
if (!sceneDir.getParentFile().exists() && !sceneDir.getParentFile().mkdirs()) {
LOGGER.warn("Unable to create directory '" + sceneDir.getParentFile().getAbsolutePath() + "'");
}

// Download files of scene
try {
provider.downloadScene(
firstBandOfScene,
workspaceDir,
userIdent,
password);
}
catch (IOException e) {
LOGGER.error("Unable to download scene '"
+ firstBandOfScene.getAttribute(SceneFeatureIterator.PRODUCT_ID_ATTRIBUTE_NAME) + "'");
}
}

/**
* Returns the path of the downloaded scene directory in the specified
* workspace directory
*
* @param scene
* @param workspaceDirectory
* @return
*/
public static File getSceneDirectory(
final SimpleFeature scene,
final String workspaceDirectory ) {
final String scenesDir = workspaceDirectory + File.separator + DOWNLOAD_DIRECTORY;
final String productId = (String) scene.getAttribute(SceneFeatureIterator.PRODUCT_ID_ATTRIBUTE_NAME);

return new File(
scenesDir + File.separator + productId);
}

/**
* Remove all downloaded files of the scene in the specified workspace
* directory
*
* @param scene
* @param workspaceDirectory
*/
protected static void cleanDownloadedFiles(
final SimpleFeature scene,
final String workspaceDirectory ) {
final File sceneDir = getSceneDirectory(
scene,
workspaceDirectory);
if (sceneDir.isDirectory()) {
FileUtil.fullyDelete(sceneDir);
}
}
}

0 comments on commit 4b897c4

Please sign in to comment.