/**
  * Invoked when a factory is requested for a specific version. This method should create a factory
  * for the exact version specified by the argument, or return {@code null} if no such factory is
  * available. In the later case, this class will fallback on the factory specified at {@linkplain
  * #URN_AuthorityFactory(AuthorityFactory, String, Citation) construction time}.
  *
  * @param version The version for the factory to create.
  * @return The factory, of {@code null} if there is none for the specified version.
  * @throws FactoryException if an error occured while creating the factory.
  */
 protected AuthorityFactory createVersionedFactory(final Version version) throws FactoryException {
   final Hints hints = new Hints(factory.getImplementationHints());
   hints.put(Hints.VERSION, version);
   final List<AuthorityFactory> factories =
       Arrays.asList(new AuthorityFactory[] {new AllAuthoritiesFactory(hints), factory});
   return FallbackAuthorityFactory.create(factories);
 }
Example #2
0
  /**
   * Tests the "Resample" operation with a stereographic coordinate system on a paletted image
   *
   * @throws FactoryException
   * @throws NoSuchAuthorityCodeException
   */
  @Test
  public void testReprojectPalette() throws NoSuchAuthorityCodeException, FactoryException {

    // do it again, make sure the image does not turn black since
    GridCoverage2D input = ushortCoverage;
    // Create a Palette image from the input coverage
    RenderedImage src = input.getRenderedImage();
    ImageWorker iw = new ImageWorker(src).rescaleToBytes().forceIndexColorModel(false);
    src = iw.getRenderedOperation();

    // Setting Force ReplaceIndexColorModel and CoverageProcessingView as SAME
    Hints hints = GeoTools.getDefaultHints().clone();
    hints.put(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, true);
    hints.put(Hints.COVERAGE_PROCESSING_VIEW, ViewType.SAME);

    // Create a new GridCoverage
    GridCoverageFactory factory = new GridCoverageFactory(hints);
    GridCoverage2D palette = factory.create("test", src, input.getEnvelope());

    CoordinateReferenceSystem targetCRS = CRS.parseWKT(GOOGLE_MERCATOR_WKT);
    GridCoverage2D coverage_ = project(palette, targetCRS, null, "bilinear", hints, true);

    // reproject the ushort and check that things did not go bad, that is it turned black
    coverage_ = (GridCoverage2D) Operations.DEFAULT.extrema(coverage_);
    Object minimums = coverage_.getProperty(Extrema.GT_SYNTHETIC_PROPERTY_MINIMUM);
    Assert.assertTrue(minimums instanceof double[]);
    final double[] mins = (double[]) minimums;
    Object maximums = coverage_.getProperty(Extrema.GT_SYNTHETIC_PROPERTY_MAXIMUM);
    Assert.assertTrue(maximums instanceof double[]);
    final double[] max = (double[]) maximums;
    boolean fail = true;
    for (int i = 0; i < mins.length; i++) if (mins[i] != max[i] && max[i] > 0) fail = false;
    Assert.assertFalse("Reprojection failed", fail);

    // Ensure the CRS is correct
    CoordinateReferenceSystem targetCoverageCRS = coverage_.getCoordinateReferenceSystem();
    Assert.assertTrue(CRS.equalsIgnoreMetadata(targetCRS, targetCoverageCRS));
  }
  @RequestMapping(
      value = "/projects/{id}/cleanse",
      method = RequestMethod.POST,
      produces = "application/xml")
  @PreAuthorize("hasPermission(#project, 'write')")
  public void processCleanse(
      @ModelAttribute(value = "project") Project project,
      @RequestParam(value = "operation", required = true) String operation,
      @RequestParam(value = "fromDate", required = false) String fromDateString,
      @RequestParam(value = "toDate", required = false) String toDateString,
      @RequestParam(value = "animal") List<Long> animalIds,
      @RequestParam(value = "maxSpeed", required = false) Double maxSpeed,
      @RequestParam(value = "minArgosClass", required = false) String minArgosClassCode,
      @RequestParam(value = "maxDop", required = false) Double maxDop,
      HttpServletRequest request,
      HttpServletResponse response)
      throws IOException, RserveInterfaceException {
    Date fromDate = null;
    Date toDate = null;
    try {
      if (StringUtils.isNotBlank(fromDateString)) {
        fromDate = isoDateFormat.parse(fromDateString);
      }
      if (StringUtils.isNotBlank(toDateString)) {
        toDate = (toDateString == null) ? null : isoDateFormat.parse(toDateString);
      }
    } catch (java.text.ParseException e1) {
      PrintWriter out = response.getWriter();
      out.append("<?xml version=\"1.0\"?>\n");
      out.append("<cleanse-response xmlns=\"http://oztrack.org/xmlns#\">\n");
      out.append("    <error>Invalid date parameters</error>\n");
      out.append("</cleanse-response>\n");
      response.setStatus(200);
      return;
    }

    MultiPolygon multiPolygon = null;
    String[] polygonsWkt = request.getParameterValues("polygon");
    if ((polygonsWkt != null) && (polygonsWkt.length > 0)) {
      Hints hints = new Hints();
      hints.put(Hints.CRS, DefaultGeographicCRS.WGS84);
      GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(hints);
      WKTReader reader = new WKTReader(geometryFactory);
      ArrayList<Polygon> polygons = new ArrayList<Polygon>();
      for (String polygonWkt : polygonsWkt) {
        try {
          Polygon polygon = (Polygon) reader.read(polygonWkt);
          polygons.add(polygon);
        } catch (ParseException e) {
          throw new RuntimeException("Error reading polygon: " + polygonWkt, e);
        }
      }
      multiPolygon = geometryFactory.createMultiPolygon(polygons.toArray(new Polygon[0]));
    }

    Set<PositionFix> speedFilterPositionFixes = null;
    if (maxSpeed != null) {
      speedFilterPositionFixes = new HashSet<PositionFix>();
      SearchQuery searchQuery = new SearchQuery();
      searchQuery.setProject(project);
      searchQuery.setFromDate(fromDate);
      searchQuery.setToDate(toDate);
      searchQuery.setAnimalIds(animalIds);
      List<PositionFix> positionFixList = positionFixDao.getProjectPositionFixList(searchQuery);
      RserveInterface rserveInterface = new RserveInterface(rserveConnectionPool);
      Map<Long, Set<Date>> animalDates =
          rserveInterface.runSpeedFilter(project, positionFixList, maxSpeed);
      for (PositionFix positionFix : positionFixList) {
        Set<Date> dates = animalDates.get(positionFix.getAnimal().getId());
        // Need to create new java.util.Date here because positionFix.detectionTime is a
        // java.sql.Timestamp.
        // Date and Timestamp have same hashCode but their equals methods differ, breaking contains
        // call.
        if ((dates != null) && dates.contains(new Date(positionFix.getDetectionTime().getTime()))) {
          speedFilterPositionFixes.add(positionFix);
        }
      }
    }

    ArgosClass minArgosClass = ArgosClass.fromCode(minArgosClassCode);

    if (operation.equals("delete")) {
      int numDeleted =
          positionFixDao.setDeleted(
              project,
              fromDate,
              toDate,
              animalIds,
              multiPolygon,
              speedFilterPositionFixes,
              minArgosClass,
              maxDop,
              true);
      positionFixDao.renumberPositionFixes(project);
      PrintWriter out = response.getWriter();
      out.append("<?xml version=\"1.0\"?>\n");
      out.append("<cleanse-response xmlns=\"http://oztrack.org/xmlns#\">\n");
      out.append("    <num-deleted>" + numDeleted + "</num-deleted>\n");
      out.append("</cleanse-response>\n");
      response.setStatus(200);
      return;
    } else if (operation.equals("undelete")) {
      int numUndeleted =
          positionFixDao.setDeleted(
              project,
              fromDate,
              toDate,
              animalIds,
              multiPolygon,
              speedFilterPositionFixes,
              minArgosClass,
              maxDop,
              false);
      positionFixDao.renumberPositionFixes(project);
      PrintWriter out = response.getWriter();
      out.append("<?xml version=\"1.0\"?>\n");
      out.append("<cleanse-response xmlns=\"http://oztrack.org/xmlns#\">\n");
      out.append("    <num-undeleted>" + numUndeleted + "</num-undeleted>\n");
      out.append("</cleanse-response>\n");
      response.setStatus(200);
      return;
    } else {
      PrintWriter out = response.getWriter();
      out.append("<?xml version=\"1.0\"?>\n");
      out.append("<cleanse-response xmlns=\"http://oztrack.org/xmlns#\">\n");
      out.append("    <error>" + "Unknown operation: " + operation + "</error>\n");
      out.append("</cleanse-response>\n");
      response.setStatus(400);
      return;
    }
  }
 Object convertSafe(Object source, Class<?> target) throws Exception {
   Hints hints = new Hints();
   hints.put(ConverterFactory.SAFE_CONVERSION, new Boolean(true));
   return factory.createConverter(source.getClass(), target, hints).convert(source, target);
 }
  protected Attribute setAttributeContent(
      Attribute target,
      StepList xpath,
      Object value,
      String id,
      AttributeType targetNodeType,
      boolean isXlinkRef,
      Expression sourceExpression,
      Object source,
      final Map<Name, Expression> clientProperties,
      boolean ignoreXlinkHref) {
    Attribute instance = null;

    Map<Name, Expression> properties = new HashMap<Name, Expression>(clientProperties);

    if (ignoreXlinkHref) {
      properties.remove(XLINK_HREF_NAME);
    }

    if (properties.containsKey(XLINK_HREF_NAME) && resolveDepth > 0) {
      // local resolve

      String refid =
          referenceToIdentifier(getValue(properties.get(XLINK_HREF_NAME), source).toString());

      if (refid != null) {

        final Hints hints = new Hints();
        if (resolveDepth > 1) {
          hints.put(Hints.RESOLVE, ResolveValueType.ALL);
          // only the top-level resolve thread should monitor timeout
          hints.put(Hints.RESOLVE_TIMEOUT, Integer.MAX_VALUE);
          hints.put(Hints.ASSOCIATION_TRAVERSAL_DEPTH, resolveDepth - 1);
        } else {
          hints.put(Hints.RESOLVE, ResolveValueType.NONE);
        }

        // let's try finding it
        FeatureFinder finder = new FeatureFinder(refid, hints);
        // this will be null if joining or sleeping is interrupted
        Feature foundFeature = null;
        if (resolveTimeOut == Integer.MAX_VALUE) {
          // not the top-level resolve thread so do not monitor timeout
          finder.run();
          foundFeature = finder.getFeature();
        } else {
          Thread thread = new Thread(finder);
          long startTime = System.currentTimeMillis();
          thread.start();
          try {
            while (thread.isAlive()
                && (System.currentTimeMillis() - startTime) / 1000 < resolveTimeOut) {
              Thread.sleep(RESOLVE_TIMEOUT_POLL_INTERVAL);
            }
            thread.interrupt();
            // joining ensures synchronisation
            thread.join();
            foundFeature = finder.getFeature();
          } catch (InterruptedException e) {
            // clean up as best we can
            thread.interrupt();
            throw new RuntimeException("Interrupted while resolving resource " + refid);
          }
        }

        if (foundFeature != null) {
          // found it
          instance =
              xpathAttributeBuilder.set(
                  target,
                  xpath,
                  Collections.singletonList(foundFeature),
                  id,
                  targetNodeType,
                  false,
                  sourceExpression);
          properties.remove(XLINK_HREF_NAME);
        }
      }
    }

    if (instance == null) {
      instance =
          xpathAttributeBuilder.set(
              target, xpath, value, id, targetNodeType, false, sourceExpression);
    }

    setClientProperties(instance, source, properties);

    return instance;
  }
  /**
   * Tests the creation of new coordinate reference systems.
   *
   * @throws FactoryException if a coordinate reference system can't be created.
   */
  @Test
  public void testCreation() throws FactoryException {
    out.println();
    out.println("Testing CRS creations");
    out.println("---------------------");
    out.println();
    out.println("create Coodinate Reference System....1: ");
    final DatumFactory datumFactory = ReferencingFactoryFinder.getDatumFactory(null);
    final CSFactory csFactory = ReferencingFactoryFinder.getCSFactory(null);
    final CRSFactory crsFactory = ReferencingFactoryFinder.getCRSFactory(null);
    final MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null);

    final Ellipsoid airy1830;
    final Unit<Length> meters = SI.METER;
    airy1830 = datumFactory.createEllipsoid(name("Airy1830"), 6377563.396, 6356256.910, meters);
    out.println();
    out.println("create Coodinate Reference System....2: ");
    out.println(airy1830.toWKT());

    final PrimeMeridian greenwich;
    final Unit<Angle> degrees = NonSI.DEGREE_ANGLE;
    greenwich = datumFactory.createPrimeMeridian(name("Greenwich"), 0, degrees);
    out.println();
    out.println("create Coodinate Reference System....3: ");
    out.println(greenwich.toWKT());

    // NOTE: we could use the following pre-defined constant instead:
    //       DefaultPrimeMeridian.GREENWICH;
    final GeodeticDatum datum;
    datum = datumFactory.createGeodeticDatum(name("Airy1830"), airy1830, greenwich);
    out.println();
    out.println("create Coodinate Reference System....4: ");
    out.println(datum.toWKT());

    // NOTE: we could use the following pre-defined constant instead:
    //       DefaultEllipsoidalCS.GEODETIC_2D;
    final EllipsoidalCS ellCS;
    ellCS =
        csFactory.createEllipsoidalCS(
            name("Ellipsoidal"),
            csFactory.createCoordinateSystemAxis(
                name("Longitude"), "long", AxisDirection.EAST, degrees),
            csFactory.createCoordinateSystemAxis(
                name("Latitude"), "lat", AxisDirection.NORTH, degrees));
    out.println();
    out.println("create Coodinate Reference System....5: ");
    out.println(ellCS); // No WKT for coordinate systems

    final GeographicCRS geogCRS;
    geogCRS = crsFactory.createGeographicCRS(name("Airy1830"), datum, ellCS);
    out.println();
    out.println("create Coodinate Reference System....6: ");
    out.println(geogCRS.toWKT());

    final MathTransform p;
    final ParameterValueGroup param = mtFactory.getDefaultParameters("Transverse_Mercator");
    param.parameter("semi_major").setValue(airy1830.getSemiMajorAxis());
    param.parameter("semi_minor").setValue(airy1830.getSemiMinorAxis());
    param.parameter("central_meridian").setValue(49);
    param.parameter("latitude_of_origin").setValue(-2);
    param.parameter("false_easting").setValue(400000);
    param.parameter("false_northing").setValue(-100000);
    out.println();
    out.println("create Coodinate System....7: ");
    out.println(param);

    // NOTE: we could use the following pre-defined constant instead:
    //       DefaultCartesianCS.PROJECTED;
    final CartesianCS cartCS;
    cartCS =
        csFactory.createCartesianCS(
            name("Cartesian"),
            csFactory.createCoordinateSystemAxis(name("Easting"), "x", AxisDirection.EAST, meters),
            csFactory.createCoordinateSystemAxis(
                name("Northing"), "y", AxisDirection.NORTH, meters));
    out.println();
    out.println("create Coodinate Reference System....8: ");
    out.println(cartCS); // No WKT for coordinate systems

    final Hints hints = new Hints();
    hints.put(Hints.DATUM_FACTORY, datumFactory);
    hints.put(Hints.CS_FACTORY, csFactory);
    hints.put(Hints.CRS_FACTORY, crsFactory);
    hints.put(Hints.MATH_TRANSFORM_FACTORY, mtFactory);

    final ReferencingFactoryContainer container = new ReferencingFactoryContainer(hints);
    assertSame(datumFactory, container.getDatumFactory());
    assertSame(csFactory, container.getCSFactory());
    assertSame(crsFactory, container.getCRSFactory());
    assertSame(mtFactory, container.getMathTransformFactory());

    final Conversion conversion = new DefiningConversion("GBN grid", param);
    final ProjectedCRS projCRS =
        crsFactory.createProjectedCRS(
            name("Great_Britian_National_Grid"), geogCRS, conversion, cartCS);
    out.println();
    out.println("create Coodinate System....9: ");
    out.println(projCRS.toWKT());
  }
  /**
   * Returns the specified property.
   *
   * @param name Property name.
   * @param opNode Operation node.
   */
  public Object getProperty(String name, Object opNode) {
    validate(name, opNode);

    if (opNode instanceof RenderedOp && name.equalsIgnoreCase("roi")) {
      RenderedOp op = (RenderedOp) opNode;

      ParameterBlock pb = op.getParameterBlock();

      // Retrieve the rendered source image and its ROI.
      RenderedImage src = pb.getRenderedSource(0);
      Object property = src.getProperty("ROI");
      if (property == null
          || property.equals(java.awt.Image.UndefinedProperty)
          || !(property instanceof ROI)) {
        return java.awt.Image.UndefinedProperty;
      }

      // Return undefined also if source ROI is empty.
      ROI srcROI = (ROI) property;
      if (srcROI.getBounds().isEmpty()) {
        return java.awt.Image.UndefinedProperty;
      }

      // Retrieve the Interpolation object.
      Interpolation interp = (Interpolation) pb.getObjectParameter(1);

      // Determine the effective source bounds.
      Rectangle srcBounds = null;
      PlanarImage dst = op.getRendering();
      if (dst instanceof GeometricOpImage && ((GeometricOpImage) dst).getBorderExtender() == null) {
        srcBounds =
            new Rectangle(
                src.getMinX() + interp.getLeftPadding(),
                src.getMinY() + interp.getTopPadding(),
                src.getWidth() - interp.getWidth() + 1,
                src.getHeight() - interp.getHeight() + 1);
      } else {
        srcBounds = new Rectangle(src.getMinX(), src.getMinY(), src.getWidth(), src.getHeight());
      }

      // If necessary, clip the ROI to the effective source bounds.
      if (!srcBounds.contains(srcROI.getBounds())) {
        srcROI = srcROI.intersect(new ROIShape(srcBounds));
      }

      // Retrieve the Warp object.
      Warp warp = (Warp) pb.getObjectParameter(0);

      // Setting constant image to be warped as a ROI
      Rectangle dstBounds = op.getBounds();

      // Setting layout of the constant image
      ImageLayout2 layout = new ImageLayout2();
      int minx = (int) srcBounds.getMinX();
      int miny = (int) srcBounds.getMinY();
      int w = (int) srcBounds.getWidth();
      int h = (int) srcBounds.getHeight();
      layout.setMinX(minx);
      layout.setMinY(miny);
      layout.setWidth(w);
      layout.setHeight(h);
      RenderingHints hints = op.getRenderingHints();
      hints.add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout));

      final PlanarImage constantImage =
          ConstantDescriptor.create(new Float(w), new Float(h), new Byte[] {(byte) 255}, hints);

      PlanarImage roiImage = null;

      // Make sure to specify tileCache, tileScheduler, tileRecyclier, by cloning hints.
      RenderingHints warpingHints = op.getRenderingHints();
      warpingHints.remove(JAI.KEY_IMAGE_LAYOUT);

      // Creating warped roi by the same way (Warp, Interpolation, source ROI) we warped the
      // input image.
      final ParameterBlock paramBlk = new ParameterBlock();
      paramBlk.addSource(constantImage);
      paramBlk.add(warp);
      paramBlk.add(interp);
      paramBlk.add(null);
      paramBlk.add(srcROI);

      // force in the image layout, this way we get exactly the same
      // as the affine we're eliminating
      Hints localHints = new Hints(op.getRenderingHints());
      localHints.remove(JAI.KEY_IMAGE_LAYOUT);
      ImageLayout il = new ImageLayout();
      il.setMinX(dstBounds.x);
      il.setMinY(dstBounds.y);
      il.setWidth(dstBounds.width);
      il.setHeight(dstBounds.height);
      localHints.put(JAI.KEY_IMAGE_LAYOUT, il);
      roiImage = JAI.create("Warp", paramBlk, localHints);
      ROI dstROI = new ROI(roiImage, 1);

      // If necessary, clip the warped ROI to the destination bounds.
      if (!dstBounds.contains(dstROI.getBounds())) {
        dstROI = dstROI.intersect(new ROIShape(dstBounds));
      }

      // Return the warped and possibly clipped ROI.
      return dstROI;
    }

    return java.awt.Image.UndefinedProperty;
  }
Example #8
0
  @Test
  public void NetCDFTestOn4DcoveragesWithImposedSchemas()
      throws NoSuchAuthorityCodeException, FactoryException, IOException, ParseException {
    File mosaic = new File(TestData.file(this, "."), "NetCDFTestOn4DcoveragesWithImposedSchemas");
    if (mosaic.exists()) {
      FileUtils.deleteDirectory(mosaic);
    }
    assertTrue(mosaic.mkdirs());

    File file = TestData.file(this, "O3NO2-noZ.nc");
    File auxFile = TestData.file(this, "O3NO2-noZ.xml");
    FileUtils.copyFileToDirectory(file, mosaic);
    FileUtils.copyFileToDirectory(auxFile, mosaic);
    file = new File(mosaic, "O3NO2-noZ.nc");

    final Hints hints =
        new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, CRS.decode("EPSG:4326", true));
    hints.put(
        Utils.AUXILIARY_FILES_PATH,
        new File(mosaic, "O3NO2-noZ.xml").getAbsolutePath()); // impose def

    // Get format
    final AbstractGridFormat format =
        (AbstractGridFormat) GridFormatFinder.findFormat(file.toURI().toURL(), hints);
    final NetCDFReader reader = (NetCDFReader) format.getReader(file.toURI().toURL(), hints);

    assertNotNull(format);
    try {
      String[] names = reader.getGridCoverageNames();
      for (String coverageName : names) {

        final String[] metadataNames = reader.getMetadataNames(coverageName);
        assertNotNull(metadataNames);
        assertEquals(metadataNames.length, 12);

        // Parsing metadata values
        assertEquals("true", reader.getMetadataValue(coverageName, "HAS_TIME_DOMAIN"));
        final String timeMetadata = reader.getMetadataValue(coverageName, "TIME_DOMAIN");
        assertEquals(
            "2012-04-01T00:00:00.000Z/2012-04-01T00:00:00.000Z,2012-04-01T01:00:00.000Z/2012-04-01T01:00:00.000Z",
            timeMetadata);
        assertNotNull(timeMetadata);
        assertEquals(
            "2012-04-01T00:00:00.000Z",
            reader.getMetadataValue(coverageName, "TIME_DOMAIN_MINIMUM"));
        assertEquals(
            "2012-04-01T01:00:00.000Z",
            reader.getMetadataValue(coverageName, "TIME_DOMAIN_MAXIMUM"));

        if (coverageName.equalsIgnoreCase("O3")) {
          assertEquals("true", reader.getMetadataValue(coverageName, "HAS_ELEVATION_DOMAIN"));
          final String elevationMetadata =
              reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN");
          assertNotNull(elevationMetadata);
          assertEquals("10.0/10.0,450.0/450.0", elevationMetadata);
          assertEquals(2, elevationMetadata.split(",").length);
          assertEquals("10.0", reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN_MINIMUM"));
          assertEquals("450.0", reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN_MAXIMUM"));
        } else {
          // Note that This sample doesn't have elevation for NO2
          assertEquals("false", reader.getMetadataValue(coverageName, "HAS_ELEVATION_DOMAIN"));
          final String elevationMetadata =
              reader.getMetadataValue(coverageName, "ELEVATION_DOMAIN");
          assertNull(elevationMetadata);
        }

        // subsetting the envelope
        final ParameterValue<GridGeometry2D> gg =
            AbstractGridFormat.READ_GRIDGEOMETRY2D.createValue();
        final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope(coverageName);
        final GeneralEnvelope reducedEnvelope =
            new GeneralEnvelope(
                new double[] {
                  originalEnvelope.getLowerCorner().getOrdinate(0),
                  originalEnvelope.getLowerCorner().getOrdinate(1)
                },
                new double[] {
                  originalEnvelope.getMedian().getOrdinate(0),
                  originalEnvelope.getMedian().getOrdinate(1)
                });
        reducedEnvelope.setCoordinateReferenceSystem(
            reader.getCoordinateReferenceSystem(coverageName));

        // Selecting bigger gridRange for a zoomed result
        final Dimension dim = new Dimension();
        GridEnvelope gridRange = reader.getOriginalGridRange(coverageName);
        dim.setSize(gridRange.getSpan(0) * 4.0, gridRange.getSpan(1) * 2.0);
        final Rectangle rasterArea = ((GridEnvelope2D) gridRange);
        rasterArea.setSize(dim);
        final GridEnvelope2D range = new GridEnvelope2D(rasterArea);
        gg.setValue(new GridGeometry2D(range, reducedEnvelope));

        final ParameterValue<List> time = ImageMosaicFormat.TIME.createValue();
        final SimpleDateFormat formatD = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        formatD.setTimeZone(TimeZone.getTimeZone("GMT"));
        final Date timeD = formatD.parse("2012-04-01T00:00:00.000Z");
        time.setValue(
            new ArrayList() {
              {
                add(timeD);
              }
            });

        final ParameterValue<List> elevation = ImageMosaicFormat.ELEVATION.createValue();
        elevation.setValue(
            new ArrayList() {
              {
                add(450d); // Elevation
              }
            });

        GeneralParameterValue[] values =
            coverageName.equalsIgnoreCase("O3")
                ? new GeneralParameterValue[] {gg, time, elevation}
                : new GeneralParameterValue[] {gg, time};

        GridCoverage2D coverage = reader.read(coverageName, values);
        assertNotNull(coverage);
        if (TestData.isInteractiveTest()) {
          coverage.show();
        } else {
          PlanarImage.wrapRenderedImage(coverage.getRenderedImage()).getTiles();
        }
      }
    } catch (Throwable t) {
      throw new RuntimeException(t);
    } finally {
      if (reader != null) {
        try {
          reader.dispose();
        } catch (Throwable t) {
          // Does nothing
        }
      }
    }
  }