/** * Converts an array of radiance values to an array of reflectance values for given solar spectral flux and sun * zenith angle. * <p/> * If the <code>recycle</code> parameter is of the same size as the radiance array, this array will be filled with * the results and returned. The returned result may contain reflectances <0 or >1. * <p/> * The method performs no plausability check on the conversion. * * @param rad the radiances in mW /(m^2 * sr * nm) * @param sza the sun zenith angle in decimal degrees * @param e0 the solar spectral flux * @param recycle optional array which will be filled with the results, can be null. * @return the array of corresponding reflectance */ public static float[] radianceToReflectance(float[] rad, float[] sza, float e0, float[] recycle) { Guardian.assertNotNull("rad", rad); Guardian.assertNotNull("sza", sza); float[] fRet = createOrRecycleArray(recycle, Math.min(rad.length, sza.length)); for (int i = 0; i < rad.length; i++) { fRet[i] = radianceToReflectance(rad[i], sza[i], e0); } return fRet; }
/** * Transforms horizontal visibility(km) to aerosol optical depth according to Koschmieder's formula. * * @param visibility horizontal visibility in km * * @throws java.lang.IllegalArgumentException * if the given parameter is 0.f */ public static float koschmieder(float visibility) { return computeKoschmieder(visibility); }
/** * Tests the functionality of radianceToReflectance(): */ public void testRadianceToReflectance() { float rad = 80.f; float sza = 30.f; // check for correct values assertEquals(0.1692265f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[0]), EPS); assertEquals(0.1757149f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[5]), EPS); assertEquals(0.23116349f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[10]), EPS); assertEquals(0.3287255f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[14]), EPS); testVectorVersion(); }
private void processMerisWithADS(Band spectralBand, SourceData sourceData, Tile targetTile, Rectangle targetRectangle, SmacAlgorithm algorithm) throws IOException { if (!setBandCoefficients(spectralBand.getName(), algorithm)) { logger.severe(String.format("Sensor coefficient file for spectral band '%s' not found!", spectralBand.getName())); return; } float[] toa = RsMathUtils.radianceToReflectance(sourceData.toa, sourceData.sza, spectralBand.getSolarFlux(), null); float[] press = RsMathUtils.simpleBarometric(sourceData.press, sourceData.elev, null); float[] uo3 = dobsonToCmAtm(sourceData.uo3); float[] uh2o = relativeHumidityTogcm2(sourceData.uh2o); Mask mask = sourceProduct.getMaskGroup().get(SMAC_MASK); int i = 0; for (int absY = targetRectangle.y; absY < targetRectangle.y + targetRectangle.height; absY++) { checkForCancellation(); for (int absX = targetRectangle.x; absX < targetRectangle.x + targetRectangle.width; absX++) { sourceData.process[i] = mask.getSampleInt(absX, absY) != 0; i++; } } float[] toa_corr = new float[toa.length]; toa_corr = algorithm.run(sourceData.sza, sourceData.saa, sourceData.vza, sourceData.vaa, sourceData.taup550, uh2o, uo3, press, sourceData.process, invalidPixel, toa, toa_corr); targetTile.setSamples(toa_corr); }
/** * Gets the geodetically corrected latitude and longitude value for a given pixel co-ordinate. * <p/> * Implements the geodetic correction algorithm from the MERIS Geometry Handbook, VT-P194-DOC-001-E, iss 1, rev 4, * page 39, equations 6a and 6b. * * @param pixelPos the pixel position to be corrected * @param factor A factor. Must be greater than zero. * @param geoPos an existing geo position or null * * @return the geo position */ private GeoPos performDirectLocationModel(PixelPos pixelPos, double factor, GeoPos geoPos) { geoPos = geoCoding.getGeoPos(pixelPos, geoPos); final float h = getElevation(geoPos, pixelPos); final AngularDirection vg = pointing.getViewDir(pixelPos, null); RsMathUtils.applyGeodeticCorrection(geoPos, factor * h, vg.zenith, vg.azimuth); return geoPos; }
float[] sza; if (isForwardBand) { vza = RsMathUtils.elevationToZenith(sourceData.vzaFwd, null); sza = RsMathUtils.elevationToZenith(sourceData.szaFwd, null); mask = sourceProduct.getMaskGroup().get(SMAC_MASK_FORWARD); } else { vza = RsMathUtils.elevationToZenith(sourceData.vza, null); sza = RsMathUtils.elevationToZenith(sourceData.sza, null); mask = sourceProduct.getMaskGroup().get(SMAC_MASK);
fRet = RsMathUtils.simpleBarometric(1013.f, 5500.f); assertEquals(515.4429931640625f, fRet, EPS); fRet = RsMathUtils.simpleBarometric(1013.f, 0.f); assertEquals(1013.f, fRet, EPS); fRet = RsMathUtils.simpleBarometric(1013.f, 8000.f); assertEquals(379.14377f, fRet, EPS); fRetArray = RsMathUtils.simpleBarometric(pressure, halfHeight, null); assertEquals(515.4429931640625f, fRetArray[3], EPS); fRetArray = RsMathUtils.simpleBarometric(pressure, seaHeight, null); assertEquals(1013.f, fRetArray[1], EPS); fRetArray = RsMathUtils.simpleBarometric(pressure, eHeight, null); assertEquals(379.14377f, fRetArray[4], EPS); fRetArray = RsMathUtils.simpleBarometric(pressure, wrongHeight, null); fail("exception expected"); } catch (ArrayIndexOutOfBoundsException e) { fRetArray = RsMathUtils.simpleBarometric(pressure, eHeight, recycle); assertSame(fRetArray, recycle); fRetArray = RsMathUtils.simpleBarometric(pressure, eHeight, recycleShort); assertTrue(fRetArray != recycle);
/** * Converts a vector of zenith angles to a vector of elevation angles. If recycle is not <code>null</code> and has * the same size as the zenith angle vector, recycle will be filled and returned to minimize the memory * finmgerprint. * * @param zenith the zenith angle vector in decimal degrees * @param recycle optional array which will be filled with the results. can be null. */ public static float[] zenithToElevation(float[] zenith, float[] recycle) { Guardian.assertNotNull("zenith", zenith); // check if we can use the recycle argument to save memory // ------------------------------------------------------- float[] fRet = createOrRecycleArray(recycle, zenith.length); // loop over vector // ---------------- for (int n = 0; n < zenith.length; n++) { fRet[n] = 90.0F - zenith[n]; } return fRet; }
public void testKoschmider_exception() { try { RsMathUtils.koschmieder(0.f); fail("IllegalArgumentException expected"); } catch (IllegalArgumentException e) { } }
/** * Tests the functionality of radianceToReflectance() vector version */ public void testVectorVersion() { float[] rad = {80.f, 80.f, 80.f, 80.f}; float[] sza = {30.f, 30.f, 30.f, 30.f}; // check for correct results assertEquals(0.1692265f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[0], null)[0], EPS); assertEquals(0.1757149f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[5], null)[0], EPS); assertEquals(0.23116349f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[10], null)[0], EPS); assertEquals(0.3287255f, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[14], null)[0], EPS); // check that if we set a recycle array that it is actually used float[] recycle = new float[4]; assertEquals(recycle, RsMathUtils.radianceToReflectance(rad, sza, BeamConstants.MERIS_SOLAR_FLUXES[0], recycle)); }
expLon = 0; expLat = 0; RsMathUtils.applyGeodeticCorrection(gp, h, 0, 0); assertEquals(expLon, gp.lon, EPS); assertEquals(expLat, gp.lat, EPS); expLon = 0; expLat = 0 + 0.02f; RsMathUtils.applyGeodeticCorrection(gp, h, 45, 0); assertEquals(expLon, gp.lon, EPS); assertEquals(expLat, gp.lat, EPS); expLon = 0 + 0.02f; expLat = 0; RsMathUtils.applyGeodeticCorrection(gp, h, 45, 90); assertEquals(expLon, gp.lon, EPS); assertEquals(expLat, gp.lat, EPS); expLon = 0; expLat = 0 - 0.02f; RsMathUtils.applyGeodeticCorrection(gp, h, 45, 180); assertEquals(expLon, gp.lon, EPS); assertEquals(expLat, gp.lat, EPS); expLon = 0 - 0.02f; expLat = 0; RsMathUtils.applyGeodeticCorrection(gp, h, 45, 270); assertEquals(expLon, gp.lon, EPS); assertEquals(expLat, gp.lat, EPS);
/** * Tests the functionality of elevationToZenith */ public void testElevationToElevation() { // function must scale correctly assertEquals(45.f, RsMathUtils.elevationToZenith(45.f), 1e-7); // vector function must not accept null as input float[] returndata; try { returndata = RsMathUtils.elevationToZenith(null, null); fail("exception expected"); } catch (RuntimeException e) { } // vector function must scale correctly assertEquals(45.f, (RsMathUtils.elevationToZenith(new float[]{45.f, 45.f, 45.f}, null))[0], 1e-7); // vector function must use the recycle argument if set returndata = new float[3]; assertEquals(returndata, RsMathUtils.elevationToZenith(new float[]{45.f, 45.f, 45.f}, returndata)); }
/** * Converts a vector of elevation angles to a vector of zenith angles. If recycle is not <code>null</code> and has * the same size as the elevation angle vector, recycle will be filled and returned to minimize the memory * fingerprint. Convenience routine. Does the same as zenithToElevation but for code clarity ... * * @param elevation a vector of elevation angles (in degree) * @param recycle optional array which will be filled with the results. can be null. */ public static float[] elevationToZenith(float[] elevation, float[] recycle) { Guardian.assertNotNull("elevation", elevation); // check if we can use the recycle argument to save memory // ------------------------------------------------------- float[] fRet = createOrRecycleArray(recycle, elevation.length); // loop over vector // ---------------- for (int n = 0; n < elevation.length; n++) { fRet[n] = 90.0F - elevation[n]; } return fRet; }
public void testKoschmider() { assertEquals(3.92f, RsMathUtils.koschmieder(2.f), EPS); assertEquals(0.46117648482f, RsMathUtils.koschmieder(17.f), EPS); }
private void processMeris(Band spectralBand, SourceData sourceData, Tile targetTile, Rectangle targetRectangle, SmacAlgorithm algorithm) throws IOException { if (!setBandCoefficients(spectralBand.getName(), algorithm)) { logger.severe("Sensor coefficient file for spectral band '" + spectralBand.getName() + "' not found!"); return; } float[] reflectances = RsMathUtils.radianceToReflectance(sourceData.toa, sourceData.sza, spectralBand.getSolarFlux(), null); Mask mask = sourceProduct.getMaskGroup().get(SMAC_MASK); int i = 0; for (int absY = targetRectangle.y; absY < targetRectangle.y + targetRectangle.height; absY++) { checkForCancellation(); for (int absX = targetRectangle.x; absX < targetRectangle.x + targetRectangle.width; absX++) { sourceData.process[i] = mask.getSampleInt(absX, absY) != 0; i++; } } float[] toa_corr = new float[reflectances.length]; toa_corr = algorithm.run(sourceData.sza, sourceData.saa, sourceData.vza, sourceData.vaa, sourceData.taup550, sourceData.uh2o, sourceData.uo3, sourceData.press, sourceData.process, invalidPixel, reflectances, toa_corr); targetTile.setSamples(toa_corr); }
/** * Calculates the air pressure in a given height given the sea level air pressure. Simple version with no dependency * on temperature etc... This method processes on vectors. If recycle is not <code>null</code> and has the same size * as the sea pressure vector, recycle will be filled and returned to minimize the memory fingerprint. * * @param seaPress vector of sea level air pressure in hPa * @param height vector of height above sea level in m * @param recycle optional array which will be filled with the results. can be null. */ public static float[] simpleBarometric(float[] seaPress, float[] height, float[] recycle) { Guardian.assertNotNull("seaPress", seaPress); Guardian.assertNotNull("height", height); // check if we can use the recycle argument to save memory // ------------------------------------------------------- float[] fRet = createOrRecycleArray(recycle, Math.min(seaPress.length, height.length)); // loop over vector // ---------------- for (int n = 0; n < seaPress.length; n++) { fRet[n] = seaPress[n] * (float) Math.exp(-BAROMETRIC_CONST * (double) height[n] / (double) seaPress[n]); } return fRet; }
/** * Transforms aerosol optical depth to horizontal visibility(km) according to Koschmieder's formula. * * @param opticalDepth aerosol optical depth * * @throws java.lang.IllegalArgumentException * if the given parameter is 0.f */ public static float koschmiederInv(float opticalDepth) { return computeKoschmieder(opticalDepth); }
final float solarFlux = ((Band) sourceRadiance.getNode()).getSolarFlux(); final float sunZenithSample = sourceSamples[sunZenithAngleSampleIndex].getFloat(); value = RsMathUtils.radianceToReflectance((float) value, sunZenithSample, solarFlux);