@Override public void computeTile(Band targetBand, Tile targetTile, ProgressMonitor pm) throws OperatorException { if (targetBand.isFlagBand()) { // no computations return; } final Rectangle rectangle = targetTile.getRectangle(); final int bigWidth = (int) (scalingFactor * rectangle.getWidth()); final int bigHeight = (int) (scalingFactor * rectangle.getHeight()); final int bigX = (int) (scalingFactor * rectangle.getX()); final int bigY = (int) (scalingFactor * rectangle.getY()); final Rectangle big = new Rectangle(bigX, bigY, bigWidth, bigHeight); pm.beginTask("Processing frame...", rectangle.height); try { // todo: clean up the tiles which are not finally needed (depends on how many channels are // used) final Tile szMerisTile = getSourceTile(synergyProduct.getTiePointGrid("sun_zenith"), big); final Tile vzMerisTile = getSourceTile(synergyProduct.getTiePointGrid("view_zenith"), big); final Tile saMerisTile = getSourceTile(synergyProduct.getTiePointGrid("sun_azimuth"), big); final Tile pressureTile = getSourceTile(synergyProduct.getTiePointGrid("atm_press"), big); final Tile seAatsrNadirTile = getSourceTile( synergyProduct.getBand( "sun_elev_nadir" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), big); final Tile veAatsrNadirTile = getSourceTile( synergyProduct.getBand( "view_elev_nadir" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), big); final Tile saAatsrNadirTile = getSourceTile( synergyProduct.getBand( "sun_azimuth_nadir" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), big); final Tile seAatsrFwardTile = getSourceTile( synergyProduct.getBand( "sun_elev_fward" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), big); final Tile veAatsrFwardTile = getSourceTile( synergyProduct.getBand( "view_elev_fward" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), big); final Tile saAatsrFwardTile = getSourceTile( synergyProduct.getBand( "sun_azimuth_fward" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), big); final Tile vaAatsrFwardTile = getSourceTile( synergyProduct.getBand( "view_azimuth_fward" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""), big); final Tile merisRad13Tile = getSourceTile( synergyProduct.getBand( "radiance_13" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_MERIS + ""), big); final Tile merisRad14Tile = getSourceTile( synergyProduct.getBand( "radiance_14" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_MERIS + ""), big); final Band reflecNadir16Band = synergyProduct.getBand( "reflec_nadir_1600" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""); final Tile aatsrReflNadir1600Tile = getSourceTile(reflecNadir16Band, big); final Band reflecNadir87Band = synergyProduct.getBand( "reflec_nadir_0870" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""); final Tile aatsrReflNadir0870Tile = getSourceTile(reflecNadir87Band, big); final Band reflecFward16Band = synergyProduct.getBand( "reflec_fward_1600" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""); final Tile aatsrReflFward1600Tile = getSourceTile(reflecFward16Band, big); final Band reflecFward87Band = synergyProduct.getBand( "reflec_fward_0870" + "_" + SynergyConstants.INPUT_BANDS_SUFFIX_AATSR + ""); final Tile aatsrReflFward0870Tile = getSourceTile(reflecFward87Band, big); final Tile wsTile = getSourceTile(glintProduct.getBand(GlintAveOp.RESULT_WINDSPEED_NAME), rectangle); // Flags tiles final Tile isInvalid = getSourceTile(invalidBand, rectangle); for (int iY = rectangle.y; iY < rectangle.y + rectangle.height; iY++) { for (int iX = rectangle.x; iX < rectangle.x + rectangle.width; iX++) { final int iTarX = (int) (scalingFactor * iX + aveBlock); final int iTarY = (int) (scalingFactor * iY + aveBlock); checkForCancellation(); final float aatsrViewElevationNadir = getAvePixel(veAatsrNadirTile, iTarX, iTarY); final float aatsrSunElevationNadir = getAvePixel(seAatsrNadirTile, iTarX, iTarY); final float aatsrViewElevationFward = getAvePixel(veAatsrFwardTile, iTarX, iTarY); final float aatsrSunElevationFward = getAvePixel(seAatsrFwardTile, iTarX, iTarY); // just use one windspeed (the 'closer to ECMWF' one from Glint retrieval) final float ws = wsTile.getSampleFloat(iX, iY); if (isInvalid.getSampleBoolean(iX, iY) || ws == SynergyConstants.OUTPUT_WS_BAND_NODATAVALUE) { targetTile.setSample(iX, iY, noDataVal); } else if (targetBand.getName().equals(SynergyConstants.OUTPUT_AOT_BAND_NAME) && (aot550Result[iX][iY] > 0.0 || aot550Result[iX][iY] == SynergyConstants.OUTPUT_AOT_BAND_NODATAVALUE)) { targetTile.setSample(iX, iY, aot550Result[iX][iY]); } else if (targetBand.getName().equals(SynergyConstants.OUTPUT_ANG_BAND_NAME) && (angResult[iX][iY] > 0.0 || angResult[iX][iY] == SynergyConstants.OUTPUT_ANG_BAND_NODATAVALUE)) { targetTile.setSample(iX, iY, angResult[iX][iY]); } else if (targetBand.getName().equals(SynergyConstants.OUTPUT_AOTERR_BAND_NAME) && (aot550ErrorResult[iX][iY] > 0.0 || aot550ErrorResult[iX][iY] == SynergyConstants.OUTPUT_AOTERR_BAND_NODATAVALUE)) { targetTile.setSample(iX, iY, aot550ErrorResult[iX][iY]); } else if (targetBand.getName().equals(SynergyConstants.OUTPUT_ANGERR_BAND_NAME) && (angErrorResult[iX][iY] > 0.0 || angErrorResult[iX][iY] == SynergyConstants.OUTPUT_ANGERR_BAND_NODATAVALUE)) { targetTile.setSample(iX, iY, aot550ErrorResult[iX][iY]); } else if (targetBand.getName().equals(SynergyConstants.OUTPUT_GLINT_BAND_NAME) && (glintResult[iX][iY] > 0.0 || glintResult[iX][iY] == SynergyConstants.OUTPUT_GLINT_BAND_NODATAVALUE)) { targetTile.setSample(iX, iY, glintResult[iX][iY]); } else if (targetBand.getName().equals(SynergyConstants.OUTPUT_WS_BAND_NAME) && (wsResult[iX][iY] > 0.0 || wsResult[iX][iY] == SynergyConstants.OUTPUT_WS_BAND_NODATAVALUE)) { targetTile.setSample(iX, iY, wsResult[iX][iY]); } else { final float merisViewAzimuth = getAvePixel(vaMerisTileComplete, iTarX, iTarY); final float merisSunAzimuth = getAvePixel(saMerisTile, iTarX, iTarY); final float merisAzimuthDifference = GlintPreparation.removeAzimuthDifferenceAmbiguity( merisViewAzimuth, merisSunAzimuth); final float merisViewZenith = getAvePixel(vzMerisTile, iTarX, iTarY); final float merisSunZenith = getAvePixel(szMerisTile, iTarX, iTarY); final float merisRad13 = getAvePixel(merisRad13Tile, iTarX, iTarY) / SynergyConstants.MERIS_13_SOLAR_FLUX; final float merisRad14 = getAvePixel(merisRad14Tile, iTarX, iTarY) / SynergyConstants.MERIS_14_SOLAR_FLUX; final double aatsrSeNadir = getAvePixel(seAatsrNadirTile, iTarX, iTarY); final double aatsrSeFward = getAvePixel(seAatsrFwardTile, iTarX, iTarY); // for RP test data (unit '%'), we need to divide AATSR reflectances by 100. // however, the correct AATSR units should be 'dl', as for the Synergy products created // in the Synergy module float aatsrUnitCorrFactor = 1.0f; if (reflecNadir87Band.getUnit().equals("%")) { // check for one band should be enough aatsrUnitCorrFactor = 100.0f; } final float aatsrReflNadir87 = (float) (getAvePixel(aatsrReflNadir0870Tile, iTarX, iTarY) / (Math.PI * Math.cos(MathUtils.DTOR * (90.0 - aatsrSeNadir)) * aatsrUnitCorrFactor)); final float aatsrReflNadir16 = (float) (getAvePixel(aatsrReflNadir1600Tile, iTarX, iTarY) / (Math.PI * Math.cos(MathUtils.DTOR * (90.0 - aatsrSeNadir)) * aatsrUnitCorrFactor)); final float aatsrReflFward87 = (float) (getAvePixel(aatsrReflFward0870Tile, iTarX, iTarY) / (Math.PI * Math.cos(MathUtils.DTOR * (90.0 - aatsrSeFward)) * aatsrUnitCorrFactor)); final float aatsrReflFward16 = (float) (getAvePixel(aatsrReflFward1600Tile, iTarX, iTarY) / (Math.PI * Math.cos(MathUtils.DTOR * (90.0 - aatsrSeFward)) * aatsrUnitCorrFactor)); final float aatsrViewAzimuthNadir = getAvePixel(vaAatsrNadirTileComplete, iTarX, iTarY); final float aatsrSunAzimuthNadir = getAvePixel(saAatsrNadirTile, iTarX, iTarY); final float aatsrViewAzimuthFward = vaAatsrFwardTile.getSampleFloat(iTarX, iTarY); final float aatsrSunAzimuthFward = saAatsrFwardTile.getSampleFloat(iTarX, iTarY); final float aatsrAzimuthDifferenceNadir = GlintPreparation.removeAzimuthDifferenceAmbiguity( aatsrViewAzimuthNadir, aatsrSunAzimuthNadir); final float aatsrAzimuthDifferenceFward = aatsrViewAzimuthFward - aatsrSunAzimuthFward; // negative pressures were stored in LUT to ensure ascending sequence final float surfacePressure = -1.0f * getAvePixel(pressureTile, iTarX, iTarY); // breadboard begin STEP 1 final float[] glintArray = doSynAOStep1( aatsrViewElevationNadir, aatsrViewElevationFward, aatsrSunElevationNadir, aatsrSunElevationFward, aatsrAzimuthDifferenceNadir, aatsrAzimuthDifferenceFward, merisViewZenith, merisSunZenith, merisAzimuthDifference, surfacePressure, ws); glintResult[iX][iY] = glintArray[0]; wsResult[iX][iY] = ws; // breadboard end STEP 1 // breadboard begin STEP 2 doSynAOStep2(); // breadboard end STEP 2 // breadboard begin STEP 3 doSynAOStep3( iY, iX, merisRad13, merisRad14, aatsrReflNadir16, aatsrReflNadir87, aatsrReflFward16, aatsrReflFward87); // breadboard end STEP 3 if (targetBand.getName().equals(SynergyConstants.OUTPUT_AOT_BAND_NAME)) { targetTile.setSample(iX, iY, aot550Result[iX][iY]); } if (targetBand.getName().equals(SynergyConstants.OUTPUT_ANG_BAND_NAME)) { targetTile.setSample(iX, iY, angResult[iX][iY]); } if (targetBand.getName().equals(SynergyConstants.OUTPUT_AOTERR_BAND_NAME)) { targetTile.setSample(iX, iY, aot550ErrorResult[iX][iY]); } if (targetBand.getName().equals(SynergyConstants.OUTPUT_ANGERR_BAND_NAME)) { targetTile.setSample(iX, iY, angErrorResult[iX][iY]); } if (targetBand.getName().equals(SynergyConstants.OUTPUT_GLINT_BAND_NAME)) { targetTile.setSample(iX, iY, glintResult[iX][iY]); } if (targetBand.getName().equals(SynergyConstants.OUTPUT_WS_BAND_NAME)) { targetTile.setSample(iX, iY, wsResult[iX][iY]); } } pm.worked(1); } } } catch (Exception e) { throw new OperatorException( "Failed to process ocean aerosol algorithm:\n" + e.getMessage(), e); } finally { pm.done(); } }
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); }