/*
* Copyright (C) 2014 by Array Systems Computing Inc. http://www.array.ca
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.s1tbx.sentinel1.gpf;
import org.esa.snap.core.datamodel.Band;
import org.esa.snap.core.datamodel.MetadataElement;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.datamodel.VirtualBand;
import org.esa.snap.core.gpf.Operator;
import org.esa.snap.core.gpf.OperatorException;
import org.esa.snap.core.gpf.OperatorSpi;
import org.esa.snap.core.gpf.annotations.OperatorMetadata;
import org.esa.snap.core.gpf.annotations.SourceProduct;
import org.esa.snap.core.gpf.annotations.TargetProduct;
import org.esa.snap.core.util.ProductUtils;
import org.esa.snap.engine_utilities.datamodel.AbstractMetadata;
import org.esa.snap.engine_utilities.gpf.InputProductValidator;
import org.esa.snap.engine_utilities.gpf.OperatorUtils;
/**
* Creates a new product with only selected bands
*/
@OperatorMetadata(alias = "GRD-Post",
category = "Radar/Sentinel-1 TOPS",
authors = "Jun Lu, Luis Veci",
version = "1.0",
copyright = "Copyright (C) 2014 by Array Systems Computing Inc.",
description = "Applies GRD post-processing")
public final class GRDPostProcessOp extends Operator {
@SourceProduct(alias = "source")
private Product sourceProduct;
@TargetProduct
private Product targetProduct;
/**
* Initializes this operator and sets the one and only target product.
* <p>The target product can be either defined by a field of type {@link Product} annotated with the
* {@link TargetProduct TargetProduct} annotation or
* by calling {@link #setTargetProduct} method.</p>
* <p>The framework calls this method after it has created this operator.
* Any client code that must be performed before computation of tile data
* should be placed here.</p>
*
* @throws OperatorException If an error occurs during operator initialisation.
* @see #getTargetProduct()
*/
@Override
public void initialize() throws OperatorException {
try {
final InputProductValidator validator = new InputProductValidator(sourceProduct);
validator.checkIfSARProduct();
validator.checkIfSentinel1Product();
validator.checkProductType(new String[]{"SLC"});
if(validator.isComplex()) {
throw new OperatorException("Data should not be complex. Please first apply SLC to GRD processing.");
}
if(validator.isMultiSwath()) {
throw new OperatorException("Data should not be in separate swaths. Please first apply SLC to GRD processing.");
}
String productName = sourceProduct.getName();
productName = productName.replace("SLC_", "GRDH");
targetProduct = new Product(productName, "GRD",
sourceProduct.getSceneRasterWidth(),
sourceProduct.getSceneRasterHeight());
ProductUtils.copyProductNodes(sourceProduct, targetProduct);
for (Band srcBand : sourceProduct.getBands()) {
if (srcBand instanceof VirtualBand) {
ProductUtils.copyVirtualBand(targetProduct, (VirtualBand) srcBand, srcBand.getName());
} else {
ProductUtils.copyBand(srcBand.getName(), sourceProduct, targetProduct, true);
}
}
updateTargetProductMetadata();
} catch (Throwable e) {
OperatorUtils.catchOperatorException(getId(), e);
}
}
/**
* Update the metadata in the target product.
*/
private void updateTargetProductMetadata() {
final MetadataElement absRoot = AbstractMetadata.getAbstractedMetadata(targetProduct);
String productName = absRoot.getAttributeString(AbstractMetadata.PRODUCT);
absRoot.setAttributeString(AbstractMetadata.PRODUCT, productName.replace("SLC_", "GRDH"));
String description = absRoot.getAttributeString(AbstractMetadata.SPH_DESCRIPTOR);
absRoot.setAttributeString(AbstractMetadata.SPH_DESCRIPTOR, description.replace("SLC", "GRD"));
absRoot.setAttributeString(AbstractMetadata.PRODUCT_TYPE, "GRD");
}
/**
* The SPI is used to register this operator in the graph processing framework
* via the SPI configuration file
* {@code META-INF/services/org.esa.snap.core.gpf.OperatorSpi}.
* This class may also serve as a factory for new operator instances.
*
* @see OperatorSpi#createOperator()
* @see OperatorSpi#createOperator(java.util.Map, java.util.Map)
*/
public static class Spi extends OperatorSpi {
public Spi() {
super(GRDPostProcessOp.class);
}
}
}