1 votos

Suma de múltiples GridCoverage Objects con GeoTools?

Estoy trabajando en Java y GeoTools para procesar algunos rásters ASCII. Actualmente, estoy tratando de obtener los rásteres sumados en una gran cuadrícula. He probado un par de métodos, pero parece que el rendimiento se degrada.

(Estos son copiados manualmente, así que pido disculpas por los errores tipográficos)

Al principio lo intenté:

Operatons op = new Operations(null);
GridCoverage2D sum = initialise();
for (GridCoverage2D grid : grid){
    sum = op.add(sum, grid);
}

Esto se ha hecho aparentemente rápido, pero cuando intento acceder a la suma tarda siglos, así que asumo que estas operaciones se llevan a cabo con pereza. Luego traté de añadir un escritor en el medio para acceder a la cuadrícula por lo que se calcula sobre la marcha.

Operatons op = new Operations(null);
GridCoverage2D sum = initialise();
for (GridCoverage2D grid : grid){
    sum = op.add(sum, grid);
    GridCoverageWriter writer = new ArcGridWriter(File.createTempFile(...))
    writer.write(sum);
}

Lo que mejoró un poco las cosas. Luego pensé que hacer una suma recursiva podría ayudar, pero estoy obteniendo resultados continuamente más lentos todavía y martillando un solo procesador. ¿Hay alguna forma de aumentar la velocidad de estas operaciones o estoy enfocando esto de manera equivocada?

Las cuadrículas son de aproximadamente 4000x4000. Por el momento, la suma de 6 cuadrículas tarda 5 minutos, la de 8 tarda unos 15 y la de 10 tarda casi media hora. Las cuadrículas se generan utilizando un modelo fortran al que no tengo acceso y podría haber hasta cerca de 100 cuadrículas sumadas. He remuestreado las cuadrículas para que todas caigan en la misma envoltura. El único problema con el primer enfoque es el tiempo de ejecución, pero me preguntaba si habría una forma más eficiente de hacerlo.

0voto

Adam Ernst Puntos 6939

Hay básicamente dos formas de hacerlo, una con un Op.add como tienes ahora y la otra con Jiffle.

GridCoverage2D[] grids = new GridCoverage2D[nRasters];
    for (int k = 0; k < nRasters; k++) {
      WritableRaster raster2 = RasterFactory.createBandedRaster(java.awt.image.DataBuffer.TYPE_INT, w, h, 1, null);
      for (int i = 0; i < w; i++) {// width...

        for (int j = 0; j < h; j++) {
          raster2.setSample(i, j, 0, k);
        }
      }
      grids[k] = gcf.create("name", raster2, referencedEnvelope);

    }

    Operations op = new Operations(null);
    float[][] zero = new float[w][h];
    for (int i = 0; i < w; i++) {
      for (int j = 0; j < h; j++) {
        zero[i][j] = 0.0f;
      }
    }

    long start = new Date().getTime();
    GridCoverage2D sum = gcf.create("name", zero, referencedEnvelope);
    for (GridCoverage2D grid : grids) {
      sum = (GridCoverage2D) op.add(sum, grid);
    }
    long mid = new Date().getTime();
    System.out.println("calc = " + (mid - start));

    String url = "sum.tif";
    File file = new File(url);
    GeoTiffWriter writer = new GeoTiffWriter(file);
    writer.write(sum, null);
    writer.dispose();
    long end = new Date().getTime();
    System.out.println("write = " + (end - mid));
    System.out.println("total = " + (end - start));
    org.geotools.process.Process jiffle = Processors.createProcess(new NameImpl("ras", "Jiffle"));
    Map<String, Object> inputs = new HashMap<>();

    String[] sourceNames = new String[nRasters];
    String letters = "abcdefghijklmnopqrstuvwxyz";
    String script = "dest = ";
    for(int i = 0;i<nRasters;i++) {
      sourceNames[i] = letters.substring(i, i + 1);
      script += sourceNames[i] + " + ";
    }
    script = script.substring(0, script.length() - 3) + ";";

    System.out.println(script);
    inputs.put(JiffleProcess.IN_SOURCE_NAME, sourceNames);
    inputs.put(JiffleProcess.IN_COVERAGE, grids);
    inputs.put(JiffleProcess.IN_SCRIPT, script);
    start = new Date().getTime();
    Map<String, Object> output = jiffle.execute(inputs, null);
    GridCoverage2D result = (GridCoverage2D) output.get(JiffleProcess.OUT_RESULT);
    mid = new Date().getTime();
    System.out.println("calc = " + (mid - start));

    url = "sum2.tif";
    file = new File(url);
    writer = new GeoTiffWriter(file);
    writer.write(result, null);
    writer.dispose();
    end = new Date().getTime();
    System.out.println("write = " + (end - mid));
    System.out.println("total = " + (end - start));

Obtengo resultados más rápidos con Op.add (aproximadamente 2 veces más rápido con 10 cuadrículas de 4kx4k). Pero en mi máquina es del orden de 5-10 segundos.

calc = 122 ms
write = 5331 ms
total = 5453 ms

calc = 7762 ms
write = 2574 ms
total = 10336 ms

Actualización

Curiosamente, (como informas) si tus cuadrículas no son cuadradas Op.add es mucho más lento. Resultados como antes pero height = 4001 da (mientras que 4001x4001 es lo mismo que antes):

calc = 142 ms
write = 8,360,682 ms
total = 8,360,824 ms

calc = 7177 ms
write = 2802 ms
total = 9979 ms

Así que si tienes rejillas "irregulares", Jiffle podría ser el camino a seguir.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X