/** This method creates the target product */ private void createTargetProduct() { final String productType = synergyProduct.getProductType(); final String productName = synergyProduct.getName(); final int sceneWidth = synergyProduct.getSceneRasterWidth(); final int sceneHeight = synergyProduct.getSceneRasterHeight(); final int downscaledRasterWidth = (int) (Math.ceil((float) (sceneWidth / scalingFactor) - 0.5)); final int downscaledRasterHeight = (int) (Math.ceil((float) (sceneHeight / scalingFactor) - 0.5)); targetProduct = new Product(productName, productType, downscaledRasterWidth, downscaledRasterHeight); // targetProduct.setPreferredTileSize(128, 128); ProductUtils.copyGeoCoding(synergyProduct, targetProduct); ProductUtils.copyMetadata(synergyProduct, targetProduct); AerosolHelpers.copyDownscaledTiePointGrids(synergyProduct, targetProduct, scalingFactor); AerosolHelpers.copyDownscaledFlagBands(synergyProduct, targetProduct, scalingFactor); // AerosolHelpers.addAerosolFlagBand(targetProduct, downscaledRasterWidth, // downscaledRasterHeight); final BandMathsOp bandArithmeticOp = BandMathsOp.createBooleanExpressionBand(INVALID_EXPRESSION, synergyProduct); invalidBand = bandArithmeticOp.getTargetProduct().getBandAt(0); setTargetBands(); }
/** * This method finds for each regular angstroem parameter a PAIR of models which can be used for a * weighted sum (interpolation). The method represents the breadboard IDL routine * 'find_model_pairs_for_angstroem_interpolation'. * * @param angArray - array of Angstroem coefficients from aerosol model table * @param nAng - number of Ang coeffs * @return AngstroemParameters[] - the model pairs */ public AngstroemParameters[] getAngstroemParameters(float[] angArray, int nAng) { final float[] minMaxVector = AerosolHelpers.getMinMaxVector(angArray, nAng); AngstroemParameters[] angstroemParameters = new AngstroemParameters[minMaxVector.length]; for (int i = 0; i < minMaxVector.length; i++) { int lowerIndex = AerosolHelpers.getNearestLowerValueIndexInFloatArray(minMaxVector[i], angArray); angstroemParameters[i] = new AngstroemParameters(); angstroemParameters[i].setIndexPairs(0, lowerIndex); int higherIndex = AerosolHelpers.getNearestHigherValueIndexInFloatArray(minMaxVector[i], angArray); angstroemParameters[i].setIndexPairs(1, higherIndex); angstroemParameters[i].setValue(minMaxVector[i]); } for (int i = 0; i < minMaxVector.length; i++) { float lowerAng = angArray[angstroemParameters[i].getIndexPairs()[0]]; float higherAng = angArray[angstroemParameters[i].getIndexPairs()[1]]; float distance = lowerAng - higherAng; if (Math.abs(distance) > 0.01) { double wgt0 = 1.0 - (lowerAng - minMaxVector[i]) / distance; angstroemParameters[i].setWeightPairs(0, wgt0); double wgt1 = 1.0 - (minMaxVector[i] - higherAng) / distance; angstroemParameters[i].setWeightPairs(1, wgt1); } else { angstroemParameters[i].setWeightPairs(0, 1.0); angstroemParameters[i].setWeightPairs(1, 0.0); } } return angstroemParameters; }
/** * This method copies all bands which contain a flagcoding from the source product to the target * product. * * @param sourceProduct the source product * @param targetProduct the target product */ public static void copyDownscaledFlagBands( Product sourceProduct, Product targetProduct, float scalingFactor) { Guardian.assertNotNull("source", sourceProduct); Guardian.assertNotNull("target", targetProduct); if (sourceProduct.getFlagCodingGroup().getNodeCount() > 0) { ProductUtils.copyFlagCodings(sourceProduct, targetProduct); ProductUtils.copyMasks(sourceProduct, targetProduct); // loop over bands and check if they have a flags coding attached for (int i = 0; i < sourceProduct.getNumBands(); i++) { Band sourceBand = sourceProduct.getBandAt(i); FlagCoding coding = sourceBand.getFlagCoding(); if (coding != null) { Band targetBand = AerosolHelpers.downscaleBand(sourceBand, scalingFactor); targetBand.setSampleCoding(coding); targetProduct.addBand(targetBand); } } } }
private float[] doSynAOStep1( float aatsrViewElevationNadir, float aatsrViewElevationFward, float aatsrSunElevationNadir, float aatsrSunElevationFward, float aatsrAzimuthDifferenceNadir, float aatsrAzimuthDifferenceFward, float merisViewZenith, float merisSunZenith, float merisAzimuthDifference, float surfacePressure, float ws) { float[] glint = new float[nWvl]; float[] iSun = new float[nWvl]; float[] iView = new float[nWvl]; float[] iAzi = new float[nWvl]; for (int j = 0; j < nWvl; j++) { // todo: clean up cases for finally unused channels switch (wvlIndex[j]) { case 0: case 1: iSun[j] = merisSunZenith; iView[j] = merisViewZenith; iAzi[j] = (float) (180.0 - merisAzimuthDifference); break; case 2: case 3: iSun[j] = (float) (90.0 - aatsrSunElevationNadir); iView[j] = (float) (90.0 - aatsrViewElevationNadir); iAzi[j] = (float) (180.0 - aatsrAzimuthDifferenceNadir); break; case 4: case 5: iSun[j] = (float) (90.0 - aatsrSunElevationFward); iView[j] = (float) (90.0 - aatsrViewElevationFward); iAzi[j] = (float) (180.0 - aatsrAzimuthDifferenceFward); break; default: break; } glint[j] = GlintRetrieval.calcGlintAnalytical( iSun[j], iView[j], iAzi[j], SynergyConstants.refractiveIndex[wvlIndex[j]], ws, SynergyConstants.rhoFoam[wvlIndex[j]]); } vectorTauLutHigh = AerosolHelpers.interpolateArray(vectorTauLut, nTau); for (int i = 0; i < nMod; i++) { for (int j = 0; j < nWvl; j++) { // todo: clean up cases for finally unused channels for (int k = 0; k < nTauLut; k++) { double[] interpol5DLowInput = new double[] {iAzi[j], iView[j], iSun[j], ws, vectorTauLut[k], surfacePressure}; // interpol5DResultLow = 'minilut' in breadboard: // minilut=fltarr(nmod,nwvl,ntau) interpol5DResultLow[i][j][k] = // 'minilut' in breadboard aerosolLookupTables[i][j].getValue(interpol5DLowInput); } // interpol5DResultLow --> interpol5DResultHigh interpol5DResultHigh[i][j] = AerosolHelpers.interpolateArray(interpol5DResultLow[i][j], nTau); for (int k = 0; k < nTau; k++) { interpol5DResultHigh[i][j][k] += glint[j]; } } } return glint; }
public void initialize() throws OperatorException { // System.out.println("starting..."); if (new File(SynergyConstants.SYNERGY_AUXDATA_HOME_DEFAULT).exists()) { auxdataPath = SynergyConstants.SYNERGY_AUXDATA_HOME_DEFAULT + File.separator + "aerosolLUTs" + File.separator + "ocean"; } else { // try this one (in case of calvalus processing) auxdataPath = SynergyConstants.SYNERGY_AUXDATA_CALVALUS_DEFAULT; } noDataVal = (float) SynergyConstants.OUTPUT_AOT_BAND_NODATAVALUE; // get the glint product... Map<String, Product> glintInput = new HashMap<String, Product>(3); glintInput.put("l1bSynergy", synergyProduct); Map<String, Object> glintAveParams = new HashMap<String, Object>(2); glintAveParams.put("aveBlock", aveBlock); glintProduct = GPF.createProduct( OperatorSpi.getOperatorAlias(GlintAveOp.class), glintAveParams, glintInput); scalingFactor = aveBlock; aveBlock /= 2; minNAve = (int) (scalingFactor * scalingFactor - 1); noDataVal = (float) SynergyConstants.OUTPUT_AOT_BAND_NODATAVALUE; createTargetProduct(); // targetProduct = glintProduct; // test // correction of azimuth discontinuity: // set up tiles for MERIS and AATSR which cover the whole scene... final int sceneWidth = synergyProduct.getSceneRasterWidth(); final int sceneHeight = synergyProduct.getSceneRasterHeight(); final Rectangle rect = new Rectangle(0, 0, sceneWidth, sceneHeight); vaMerisTileComplete = getSourceTile(synergyProduct.getTiePointGrid("view_azimuth"), rect); vaAatsrNadirTileComplete = getSourceTile( synergyProduct.getBand( "view_azimuth_nadir" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), rect); aot550Result = new float[sceneWidth][sceneHeight]; angResult = new float[sceneWidth][sceneHeight]; aot550ErrorResult = new float[sceneWidth][sceneHeight]; angErrorResult = new float[sceneWidth][sceneHeight]; glintResult = new float[sceneWidth][sceneHeight]; wsResult = new float[sceneWidth][sceneHeight]; // read aerosol class table try { aerosolClassTable = AerosolAuxData.getInstance().createAerosolClassTable(); } catch (IOException e) { throw new OperatorException("Failed to read aerosol class table:\n" + e.getMessage(), e); } // read aerosol models try { aerosolModelTable = AerosolAuxData.getInstance().createAerosolModelTable(auxdataPath); } catch (IOException e) { throw new OperatorException("Failed to read aerosol class table:\n" + e.getMessage(), e); } // wvl=[ 865, 885,1610, 885,1610, 885] wvl = new float[] {865.0f, 885.0f, 1610.0f, 885.0f, 1610.0f, 885.0f}; wvlWeight = new float[] {1.0f, 1.0f, 3.0f, 1.0f, 3.0f, 3.0f}; wvlIndex = new int[] {0, 3, 5}; // at this point, just use 1 MERIS and 1 AATSR channel... // todo: clarify with RP which we should finally use // find model indices belonging to aerosol classes... final List<Integer> modelIndices = aerosolModelTable.getMaritimeAndDesertIndices(); nMod = modelIndices.size(); nWvl = wvlIndex.length; try { aerosolLookupTables = AerosolAuxData.getInstance() .createAerosolOceanLookupTables( auxdataPath, modelIndices, wvl, wvlIndex); } catch (IOException e) { throw new OperatorException("Failed to create aerosol lookup tables:\n" + e.getMessage(), e); // String msg = SynergyConstants.AUXDATA_ERROR_MESSAGE; // SynergyUtils.logErrorMessage(msg); } nTauLut = aerosolLookupTables[0][0].getDimensions()[4].getSequence().length; interpol5DResultLow = new double[nMod][nWvl][nTauLut]; interpol5DResultHigh = new double[nMod][nWvl][nTau]; interpolAngResult = new float[nWvl][nTau][nAng]; costFunction = new float[nWvl][nTau][nAng]; vectorTauLut = new double[nTauLut]; for (int i = 0; i < nTauLut; i++) { vectorTauLut[i] = i * 2.0 / (nTauLut - 1); } vectorTauLutHigh = new double[nTau]; for (int i = 0; i < nTau; i++) { vectorTauLutHigh[i] = i * 2.0 / (nTau - 1); } final float[] angArray = aerosolModelTable.getAngArray(modelIndices, 0); angstroemParameters = AerosolHelpers.getInstance().getAngstroemParameters(angArray, nAng); // read corresponding small LUTs and make a big LUT... // correct azimuths in these tiles for later usage... GlintPreparation.correctViewAzimuthLinear(vaMerisTileComplete, rect); GlintPreparation.correctViewAzimuthLinear(vaAatsrNadirTileComplete, rect); }