it.geosolutions.geobatch.destination.vulnerability.VulnerabilityComputation.java Source code

Java tutorial

Introduction

Here is the source code for it.geosolutions.geobatch.destination.vulnerability.VulnerabilityComputation.java

Source

/*
 *  Copyright (C) 2007-2012 GeoSolutions S.A.S.
 *  http://www.geo-solutions.it
 *
 *  GPLv3 + Classpath exception
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package it.geosolutions.geobatch.destination.vulnerability;

import it.geosolutions.geobatch.destination.common.InputObject;
import it.geosolutions.geobatch.destination.common.OutputObject;
import it.geosolutions.geobatch.destination.ingestion.MetadataIngestionHandler;
import it.geosolutions.geobatch.destination.vulnerability.TargetManager.TargetInfo;
import it.geosolutions.geobatch.destination.vulnerability.VulnerabilityMonitor.Message.TYPE;
import it.geosolutions.geobatch.flow.event.ProgressListenerForwarder;
import it.geosolutions.jaiext.bandmerge.BandMergeCRIF;
import it.geosolutions.jaiext.bandmerge.BandMergeDescriptor;
import it.geosolutions.jaiext.nullop.NullCRIF;
import it.geosolutions.jaiext.nullop.NullDescriptor;

import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.media.jai.BorderExtender;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;

import org.apache.commons.lang3.StringUtils;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureSource;
import org.geotools.data.Transaction;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geometry.Envelope2D;
import org.geotools.image.jai.Registry;
import org.geotools.jdbc.JDBCDataStore;
import org.geotools.referencing.operation.transform.AffineTransform2D;
import org.jaitools.imageutils.ImageLayout2;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.metadata.spatial.PixelOrientation;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vividsolutions.jts.geom.Geometry;

/**
 * This class is the entry point for the vulnerability process (method computeVulnerability) and it implements the computation's main loop
 * 
 * @author DamianoG
 * @author Nicola Lagomarsini
 * @author Daniele Romagnoli, GeoSolutions SAS
 */
public class VulnerabilityComputation extends InputObject {

    public static final String JAI_EXT_PRODUCT = "it.geosolutions.jaiext.roiaware";

    private static final int MAX_TEMP_CALC = 20;

    private static final int BBOX_COORD_NUM = 4;

    private final static Logger LOGGER = LoggerFactory.getLogger(VulnerabilityComputation.class);

    private static Pattern TYPE_NAME_PARTS = Pattern
            .compile("^([A-Z]{2})_([A-Z]{1})_([A-Za-z]+)_([0-9]{8})(_.*?)?$");

    public static String GEO_TYPE_NAME = "siig_geo_ln_arco_X";

    public static String VULNERABILITY_TYPE_NAME = "siig_t_vulnerabilita_X";

    private static String DISTANCE_TYPE_NAME = "siig_d_distanza";

    private static String ID_GEO_ARCO = "id_geo_arco";

    public static String PARTNER_FIELD = "fk_partner";

    public static String GEOID = "id_geo_arco";

    public final static String RASTER_PATH_PROP = "SIIG_RASTERS_PATH";

    private static final BorderExtender type = BorderExtender.createInstance(BorderExtender.BORDER_ZERO);

    private Long startOriginId;

    private Long endOriginId;

    private Long totPages;

    private Long pageNumber;

    private int pixelArea;

    private Map vulnerabilityCfg;

    String codicePartner;
    String date;

    int currentArc = 0;
    double currentDistance = 0;

    int partner;

    static {
        try {
            Registry.registerRIF(JAI.getDefaultInstance(), new BandMergeDescriptor(), new BandMergeCRIF(),
                    JAI_EXT_PRODUCT);

            Registry.registerRIF(JAI.getDefaultInstance(), new NullDescriptor(), new NullCRIF(), JAI_EXT_PRODUCT);

        } catch (Throwable e) {
            // swallow exception in case the op has already been registered.
        }
    }

    /**
     * @param startOriginId the startOriginId to set
     */
    public void setStartOriginId(Long startOriginId) {
        this.startOriginId = startOriginId;
    }

    /**
     * @param endOriginId the endOriginId to set
     */
    public void setEndOriginId(Long endOriginId) {
        this.endOriginId = endOriginId;
    }

    /**
     * @param pixelArea the pixelArea to set
     */
    public void setPixelArea(int pixelArea) {
        this.pixelArea = pixelArea;
    }

    /**
     * @param totPages the totPages to set
     */
    public void setTotPages(Long totPages) {
        this.totPages = totPages;
    }

    /**
     * @param pageNumber the pageNumber to set
     */
    public void setPageNumber(Long pageNumber) {
        this.pageNumber = pageNumber;
    }

    /**
     * @param inputTypeName
     * @param listenerForwarder
     */
    public VulnerabilityComputation(String inputTypeName, ProgressListenerForwarder listenerForwarder,
            MetadataIngestionHandler metadataHandler, JDBCDataStore dataStore) {
        super(inputTypeName, listenerForwarder, metadataHandler, dataStore);
        // default area
        pixelArea = 100;
    }

    public int getPartner() {
        return partner;
    }

    public String getCodicePartner() {
        return codicePartner;
    }

    public String getDate() {
        return date;
    }

    public void removeVulnerabilityImports() throws IOException {
        removeOldImports();
    }

    @Override
    protected String getInputTypeName(String inputTypeName) {
        return inputTypeName.replace("_ORIG", "").replace("_CALCS", "");
    }

    @Override
    protected boolean parseTypeName(String typeName) {
        Matcher m = TYPE_NAME_PARTS.matcher(typeName);
        if (m.matches()) {
            // partner alphanumerical abbreviation (from siig_t_partner)
            codicePartner = m.group(1);
            // partner numerical id (from siig_t_partner)
            partner = Integer.parseInt(partners.get(codicePartner).toString());
            date = m.group(4);
            return true;
        }
        return false;
    }

    private String getTypeName(String typeName, int aggregationLevel) {
        return typeName.replace("X", aggregationLevel + "");
    }

    /**
     * Compute the vulnerability for each arc. The Algorithm is:
     * 
     * ForEach(target) buffers = computeBuffers(allDistance, arc); ForEach(distance) if(!isAccepted(distance,target)) saveOnDB(0,arc,target,distance)
     * continue; sum = computeSum(buffer, target); ForEach(arc) saveOnDB(sum,arc,target,distance);
     * 
     * 
     * @param datastoreParams
     * @param crs
     * @param aggregationLevel
     * @param bbox
     * @throws IOException
     */
    public void computeVulnerability(CoordinateReferenceSystem crs, int aggregationLevel, String writeMode,
            RenderedImage currentImage, Map<Integer, TargetInfo> currentBPT, String targetID, int minTileX,
            int maxTileX, int minTileY, int maxTileY, boolean skipArcs, Integer xStart, Integer yStart,
            Integer xStop, Integer yStop, String idStart, Envelope2D bbox, VulnerabilityMonitor monitor,
            ConcurrentSkipListSet<BigDecimal> arcIdsSet) throws IOException {

        reset();
        // Initial checks
        if (isValid()) {

            crs = checkCrs(crs);

            String outFeatureName = getTypeName(VULNERABILITY_TYPE_NAME, aggregationLevel);

            //
            // Load All needed resources: properties files, Rendered Images,
            // GeotifReaders
            //
            // final TargetPropertiesLoader propertiesLoader = new TargetPropertiesLoader();
            vulnerabilityCfg = (Map) readResourceFromXML("/vulnerability.xml");
            String basePath = System.getProperty(RASTER_PATH_PROP, "");
            if (!basePath.equals("")) {
                basePath = basePath + File.separator + codicePartner;
            }

            VulnerabilityStatsEngine vse = new VulnerabilityStatsEngine(basePath, vulnerabilityCfg, dataStore,
                    DISTANCE_TYPE_NAME, pixelArea);

            // Setup the OutputObject (in thet case the vulnerability table)
            // remove old values for the partner and detect the max id
            Transaction transaction = new DefaultTransaction();
            OutputObject vulnerabilityObj = new OutputObject(dataStore, transaction, outFeatureName, GEOID);

            VulnerabilityOperation concreteOperation;
            // Human targets
            if (targetID.equalsIgnoreCase("Human")) {
                //
                // Load the concrete operation (Update)
                //
                concreteOperation = prepareVulnerabilityOperation("UPDATE", vulnerabilityObj);
                // Not Human targets
            } else {
                //
                // Load the concrete operation (Insert or PurgeInsert)
                //
                concreteOperation = prepareVulnerabilityOperation(writeMode, vulnerabilityObj);
            }

            //
            // Start the vulnerability Computation
            //
            try {

                List<Double> allDistances = vse.getDistances();
                int reportingLoopStep = allDistances.size() > 10 ? 50 : 100;

                // setup geo input / output object
                String geoName = getTypeName(GEO_TYPE_NAME, aggregationLevel);
                if (aggregationLevel == 3) {
                    geoName = geoName.replace("ln", "pl");
                }
                // Creation of the input reader
                createInputReader(dataStore, null, geoName);

                Filter partnerFilter = filterFactory.equals(filterFactory.property(PARTNER_FIELD),
                        filterFactory.literal(partner));
                setInputFilter(partnerFilter);

                LOGGER.info("Start computation: ThreadName: " + Thread.currentThread().getName()
                        + " - startOriginId: " + startOriginId + " - endOriginId: " + endOriginId);
                // Setting of the monitor parameters

                try {
                    if (aggregationLevel != 3) {
                        // Vulnerability computation for the level 1 or 2
                        vulnerabilityLevel12(currentImage, currentBPT, targetID, minTileX, maxTileX, minTileY,
                                maxTileY, skipArcs, xStart, yStart, xStop, yStop, idStart, bbox, outFeatureName,
                                monitor.getTrace(), vse, transaction, vulnerabilityObj, concreteOperation, monitor,
                                allDistances, reportingLoopStep, geoName, arcIdsSet);
                    } else {
                        // Vulnerability computation for the level 3
                        vulnerabilityLevel3(currentImage, currentBPT, targetID, bbox, outFeatureName,
                                monitor.getTrace(), vse, vulnerabilityObj, concreteOperation, monitor, allDistances,
                                reportingLoopStep, geoName, partnerFilter, arcIdsSet);
                    }
                } catch (Exception e) {
                    monitor.incrementErrors();
                    monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                            "Raster=" + targetID + ", Error occurred on raster: " + targetID + " for distance "
                                    + currentDistance + " on arc:" + currentArc,
                            e));
                    LOGGER.error("Raster=" + targetID + ", Error occurred on raster: " + targetID + " for distance "
                            + currentDistance + " on arc:" + currentArc + "\n" + e.getMessage(), e);
                }

            } finally {
                closeInputReader();
                LOGGER.info(
                        "Write errors for " + targetID + ": " + (monitor.getErrors() - monitor.getStartErrors()));
                monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.CLOSE));
                transaction.close();
            }
        }
    }

    /**
     * This method calculates the vulnerability for the levels 1 and 2
     * 
     * @param currentImage
     * @param currentBPT
     * @param keySet
     * @param targetID
     * @param minTileX
     * @param maxTileX
     * @param minTileY
     * @param maxTileY
     * @param skipArcs
     * @param xStart
     * @param yStart
     * @param xStop
     * @param yStop
     * @param idStart
     * @param bbox
     * @param outFeatureName
     * @param trace
     * @param vse
     * @param statsMap
     * @param transaction
     * @param vulnerabilityObj
     * @param concreteOperation
     * @param monitor
     * @param inputFeature
     * @param allDistances
     * @param reportingLoopStep
     * @param geoName
     * @param total
     * @throws NoninvertibleTransformException
     * @throws TransformException
     * @throws IOException
     */
    private void vulnerabilityLevel12(RenderedImage currentImage, Map<Integer, TargetInfo> currentBPT,
            String targetID, int minTileX, int maxTileX, int minTileY, int maxTileY, boolean skipArcs,
            Integer xStart, Integer yStart, Integer xStop, Integer yStop, String idStart, Envelope2D bbox,
            String outFeatureName, int trace, VulnerabilityStatsEngine vse, Transaction transaction,
            OutputObject vulnerabilityObj, VulnerabilityOperation concreteOperation, VulnerabilityMonitor monitor,
            List<Double> allDistances, int reportingLoopStep, String geoName,
            ConcurrentSkipListSet<BigDecimal> arcIdsSet)
            throws NoninvertibleTransformException, TransformException, IOException {

        // Preliminary checks
        if (minTileX > maxTileX) {
            int temp = minTileX;
            minTileX = maxTileX;
            maxTileX = temp;
        }
        if (minTileY > maxTileY) {
            int temp = minTileY;
            minTileY = maxTileY;
            maxTileY = temp;
        }

        // Load the Transformation associated with the selected
        // target and calculate the inverse
        TargetInfo firstInfo = currentBPT.get(0);
        MathTransform w2g = firstInfo.getGG2D().getCRSToGrid2D(PixelOrientation.UPPER_LEFT);
        MathTransform g2w = w2g.inverse();
        // Load the target dimensions for modifying the spatial
        // filter

        // Definition of the dimensions associated to the input image
        int tileWidth = currentImage.getTileWidth();
        int tileHeight = currentImage.getTileHeight();
        int tileGridX = currentImage.getTileGridXOffset();
        int tileGridY = currentImage.getTileGridYOffset();
        // Variables used for mapping the tile in the model space

        // Iteration on image tiles
        for (int x = minTileX; x < maxTileX; x++) {

            // For each tile, the points are transformed in the
            // world crs
            int minX = PlanarImage.tileXToX(x, tileGridX, tileWidth);

            if (xStart != null && xStart > x) {
                continue;
            }

            if (xStop != null && xStop < x) {
                continue;
            }

            for (int y = minTileY; y < maxTileY; y++) {

                int minY = PlanarImage.tileYToY(y, tileGridY, tileHeight);

                if (yStart != null && yStart > y) {
                    continue;
                }

                if (yStop != null && yStop < y) {
                    continue;
                }

                Envelope2D worldEnvelope = calculateWorldEnvelope(minX, minY, tileWidth, tileHeight, g2w);
                calculateTile(worldEnvelope, bbox, x, y, xStart, yStart, idStart, concreteOperation, monitor,
                        arcIdsSet, vse, currentBPT, allDistances, currentImage, targetID, outFeatureName,
                        vulnerabilityObj);
            }
        }

    }

    private Envelope2D calculateWorldEnvelope(int minX, int minY, int tileWidth, int tileHeight, MathTransform g2w)
            throws TransformException {
        double[] srcPts = new double[BBOX_COORD_NUM];
        double[] dstPts = new double[BBOX_COORD_NUM];

        // Source Coordinates
        srcPts[0] = minX;
        srcPts[1] = minY;
        srcPts[2] = minX + tileWidth;
        srcPts[3] = minY + tileHeight;
        // Coordinates transformation
        g2w.transform(srcPts, 0, dstPts, 0, 2);
        // Creation of the BoundingBox associated with
        // the selected tile
        double height = Math.abs(dstPts[1] - dstPts[3]);
        double width = Math.abs(dstPts[0] - dstPts[2]);

        // Setting of the bounding box
        Envelope2D env = new Envelope2D();

        env.x = dstPts[0];
        env.y = dstPts[3];
        env.height = height;
        env.width = width;

        return env;
    }

    private void calculateBatch(int batchSize, ConcurrentSkipListSet<BigDecimal> arcIdsSet,
            VulnerabilityStatsEngine vse, List<Double> allDistances, Map<Integer, TargetInfo> currentBPT,
            VulnerabilityMonitor monitor, RenderedImage currentImage, String targetID, int x, int y,
            VulnerabilityOperation concreteOperation, String outFeatureName, OutputObject vulnerabilityObj) {

        // Initialize lists of the calculated arcs for this batch
        List<SimpleFeature> arcList = new ArrayList<SimpleFeature>();
        List<String> arcIds = new ArrayList<String>();
        List<MultipleBufferMap> bufferList = new ArrayList<MultipleBufferMap>();
        List<ResultStatsMap> statList = new ArrayList<ResultStatsMap>();

        // we calculate a batch of batchSize features at a time
        calculateBuffersOnBatch(batchSize, arcIdsSet, vse, allDistances, monitor, targetID, x, y, arcList, arcIds,
                bufferList);

        // Operations are executed only if there is at least one arc
        if (!arcList.isEmpty()) {
            try {

                // Iteration on all the buffers
                for (Double processedDistance : allDistances) {
                    // Update of the currentDistance variable for exception logging
                    currentDistance = processedDistance;
                    // Check if the distance is
                    // related to the selected
                    // target
                    // Empty map used for containing
                    // only the accepted targets
                    Map<Integer, TargetInfo> acceptedBands = mapAcceptedBands(currentBPT, processedDistance);
                    // Statistical computation

                    // The statistics are calculated
                    // only if almost one of the
                    // targets accepts the current
                    // distance
                    boolean bandAccepted = !acceptedBands.isEmpty();
                    if (bandAccepted) {
                        // Number of ResultStatsMap
                        // already present
                        int statListSize = statList.size();
                        // Number of buffer to
                        // calculate
                        int buffListSize = bufferList.size();
                        // If the ResultStatsMap are
                        // not enough, they are
                        // calculated until they
                        // reach the desired
                        // number
                        if (statListSize < buffListSize) {
                            int difference = buffListSize - statListSize;

                            for (int i = 0; i < difference; i++) {
                                statList.add(new ResultStatsMap(vulnerabilityCfg));
                            }
                        }
                        for (ResultStatsMap stats : statList) {
                            stats.initStatsMap(acceptedBands);
                        }
                        // extract all the buffers for current distance for all the arcs in current batch
                        List<Geometry> geometryList = calculateGeometryList(bufferList, processedDistance);
                        // Compute Stats for all buffers -> Vulnerability
                        try {
                            vse.computeStats(geometryList, currentImage, statList, false, acceptedBands);

                        } catch (Exception e) {
                            monitor.incrementErrors();
                            monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                                    "Raster=" + targetID + ", TILE=(" + x + "," + y
                                            + ") Error calculating stats on batch of arcs: "
                                            + StringUtils.join(arcIds, ","),
                                    e));

                            LOGGER.error("Raster=" + targetID + ", TILE=(" + x + "," + y
                                    + ") Error calculating stats on batch of arcs: "
                                    + StringUtils.join(arcIds, ","), e);
                        }

                    }
                    // Iteration on all the
                    // geometries list
                    for (int i = 0; i < arcList.size(); i++) {

                        // Selection of the arc
                        SimpleFeature arc = arcList.get(i);
                        // Selection of the arcId
                        String arcId = arcIds.get(i);

                        // ResultStatsMap associated
                        // with the arc
                        ResultStatsMap resMap;
                        if (bandAccepted) {
                            resMap = statList.get(i);
                        } else {
                            resMap = new ResultStatsMap(vulnerabilityCfg);
                            resMap.initStatsMap(new HashMap<Integer, TargetInfo>());
                        }

                        try {
                            // Writing of the result
                            // for the selected
                            // distance and Id

                            concreteOperation.writeOutputObjects(monitor.getTrace(), vulnerabilityObj,
                                    monitor.getTotal(), outFeatureName, arc, buildFid(arcId, processedDistance),
                                    resMap.getStatsMap(), partner);
                            // DEBUG: indication of
                            // which arc is
                            // calculated
                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug("Raster=" + targetID + ", TILE=(" + x + "," + y + ") Computed arc "
                                        + arcId + " for distance=" + processedDistance);
                            }
                        } catch (Exception e) {
                            monitor.incrementErrors();
                            monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                                    "Raster=" + targetID + ", TILE=(" + x + "," + y

                                            + ") Error writing objects on " + outFeatureName + ": Computed arc "
                                            + arcId + " for distance=" + processedDistance,
                                    e));
                            LOGGER.error("Raster=" + targetID + ", TILE=(" + x + "," + y
                                    + ") Error writing objects on " + outFeatureName + ": Computed arc " + arcId
                                    + " for distance=" + processedDistance, e);
                        }
                    }
                }
                monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.PROGRESS,
                        "Calculating vulnerability for " + targetID));
                for (int i = 0; i < arcList.size(); i++) {
                    monitor.incrementCounter();
                }

            } catch (Exception e) {
                monitor.incrementErrors();
                monitor.newMessage(
                        new VulnerabilityMonitor.Message(TYPE.ERROR, "Raster=" + targetID + ", TILE=(" + x + "," + y

                                + ") Error computing batch of arcs", e));
                LOGGER.error("Raster=" + targetID + ", TILE=(" + x + "," + y + ") Error computing batch of arcs",
                        e);
            }
        }
    }

    /**
     * Calculate all the buffers geometries for the next batchSize set of arcs.
     * 
     * @param batchSize
     * @param arcIdsSet
     * @param vse
     * @param allDistances
     * @param monitor
     * @param targetID
     * @param x
     * @param y
     * @param arcList
     * @param arcIds
     * @param bufferList
     * @return
     */
    private int calculateBuffersOnBatch(int batchSize, ConcurrentSkipListSet<BigDecimal> arcIdsSet,
            VulnerabilityStatsEngine vse, List<Double> allDistances, VulnerabilityMonitor monitor, String targetID,
            int x, int y, List<SimpleFeature> arcList, List<String> arcIds, List<MultipleBufferMap> bufferList) {

        int batchCounter = 0;
        try {
            while (batchCounter < batchSize && hasMoreInput(true)) {
                SimpleFeature inputFeature = readInput();

                BigDecimal arcId = ((BigDecimal) inputFeature.getAttribute(ID_GEO_ARCO));

                // Check if the feature has been already
                // taken
                boolean newArc = arcIdsSet.add(arcId);
                if (newArc) {
                    try {
                        MultipleBufferMap mbm = vse.computeBuffersOnArcs(Collections.singletonList(inputFeature),
                                allDistances);
                        bufferList.add(mbm);
                        arcList.add(inputFeature);
                        arcIds.add(arcId.toString());
                    } catch (Exception e) {
                        monitor.incrementErrors();
                        monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                                "Error calculating buffers for arc " + arcId, e));
                        LOGGER.error("Error calculating buffers for arc " + arcId, e);
                    }
                }

                batchCounter++;
            }
        } catch (Exception e1) {
            monitor.incrementErrors();
            monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                    "Raster=" + targetID + ", TILE=(" + x + "," + y + ") Error reading arcs", e1));
            LOGGER.error("Raster=" + targetID + ", TILE=(" + x + "," + y + ") Error reading arcs batch", e1);
        }
        return batchCounter;
    }

    private void calculateTile(Envelope2D env, Envelope2D bbox, int x, int y, Integer xStart, Integer yStart,
            String idStart, VulnerabilityOperation concreteOperation, VulnerabilityMonitor monitor,
            ConcurrentSkipListSet<BigDecimal> arcIdsSet, VulnerabilityStatsEngine vse,
            Map<Integer, TargetInfo> currentBPT, List<Double> allDistances, RenderedImage currentImage,
            String targetID, String outFeatureName, OutputObject vulnerabilityObject) {

        // Creation of a spatial filter for taking only
        // the features associated
        // to the selected bounding box
        if ((xStart != null && x == xStart) && (yStart != null && y == yStart) && idStart != null) {
            setInputFilter(
                    concreteOperation.buildOriginFilterExtended(partner, monitor.getTotal(), env, bbox, idStart));
        } else {
            setInputFilter(
                    concreteOperation.buildOriginFilterExtended(partner, monitor.getTotal(), env, bbox, null));
        }

        try {

            while (hasMoreInput(true)) {
                calculateBatch(MAX_TEMP_CALC, arcIdsSet, vse, allDistances, currentBPT, monitor, currentImage,
                        targetID, x, y, concreteOperation, outFeatureName, vulnerabilityObject);
            }
        } catch (Exception e) {
            monitor.incrementErrors();
            monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                    "Raster=" + targetID + ", TILE=(" + x + "," + y + ") Generic error", e));
            LOGGER.error("Raster=" + targetID + ", TILE=(" + x + "," + y + ") Generic error", e);
        }
    }

    /**
      * This method calculates the vulnerability for the level 3
      * 
      * @param currentImage
      * @param currentBPT
      * @param keySet
      * @param targetID
      * @param bbox
      * @param outFeatureName
      * @param trace
      * @param vse
      * @param vulnerabilityObj
      * @param concreteOperation
      * @param monitor
      * @param allDistances
      * @param reportingLoopStep
      * @param geoName
      * @param partnerFilter
      * @param total
      * @throws IOException
      */
    private void vulnerabilityLevel3(RenderedImage currentImage, Map<Integer, TargetInfo> currentBPT,
            String targetID, Envelope2D bbox, String outFeatureName, int trace, VulnerabilityStatsEngine vse,
            OutputObject vulnerabilityObj, VulnerabilityOperation concreteOperation, VulnerabilityMonitor monitor,
            List<Double> allDistances, int reportingLoopStep, String geoName, Filter partnerFilter,
            ConcurrentSkipListSet<BigDecimal> arcIdsSet) throws IOException {

        SimpleFeature currentCell;
        // Setting of the input filter
        BigDecimal idCellStart = new BigDecimal(startOriginId);
        BigDecimal idCellStop = new BigDecimal(endOriginId);

        concreteOperation.setStartOriginId(idCellStart.longValue());
        concreteOperation.setEndOriginId(idCellStop.longValue());
        // Creation of the input filter used
        setInputFilter(concreteOperation.buildOriginFilterExtended(partner, monitor.getTotal(), null, bbox, null));
        try {
            while ((currentCell = readInputSorted()) != null) {

                calculateCell(currentImage, currentBPT, targetID, outFeatureName, trace, vse, vulnerabilityObj,
                        concreteOperation, monitor, allDistances, reportingLoopStep, geoName, partnerFilter,
                        arcIdsSet, currentCell);
            }
        } catch (Exception e) {
            monitor.incrementErrors();
            monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                    "Raster=" + targetID + ", TILE=(" + idCellStart + "," + idCellStop + ") Generic error", e));
            LOGGER.error("Raster=" + targetID + ", CELLS=(" + idCellStart + "," + idCellStop + ") Generic error",
                    e);
        }
        //monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.FINISH, "Vulnerability calculation completed"));
    }

    private void calculateCell(RenderedImage currentImage, Map<Integer, TargetInfo> currentBPT, String targetID,
            String outFeatureName, int trace, VulnerabilityStatsEngine vse, OutputObject vulnerabilityObj,
            VulnerabilityOperation concreteOperation, VulnerabilityMonitor monitor, List<Double> allDistances,
            int reportingLoopStep, String geoName, Filter baseFilter, ConcurrentSkipListSet<BigDecimal> arcIdsSet,
            SimpleFeature currentCell) {

        // Selection of the id associated to the feature.
        BigDecimal cellId = ((BigDecimal) currentCell.getAttribute(ID_GEO_ARCO));

        // Check if the feature has been already taken
        boolean newCell = arcIdsSet.add(cellId);
        if (newCell) {

            Map<Double, ResultStatsMap> statList = new TreeMap<Double, ResultStatsMap>();

            // For level 3, get all the arcs that intersect with
            // the current grid cell
            FeatureIterator<SimpleFeature> iterator = null;

            try {
                iterator = getArcsForCell(geoName, baseFilter, currentCell);

                while (iterator.hasNext()) {
                    calculateBetchOfArcsForCell(currentImage, currentBPT, vse, allDistances, statList, iterator,
                            cellId.toString(), MAX_TEMP_CALC, monitor, targetID);
                }
            } catch (Exception e) {
                monitor.incrementErrors();
                monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                        "Raster=" + targetID + ", Error reading arcs for cell " + cellId, e));
                LOGGER.error("Raster=" + targetID + ", Error reading arcs for cell " + cellId, e);
            } finally {
                if (iterator != null) {
                    iterator.close();
                }
            }

            // write cell stats
            for (Double processedDistance : allDistances) {
                try {
                    // Writing of the result for the
                    // selected distance and Id
                    concreteOperation.writeOutputObjects(trace, vulnerabilityObj, monitor.getTotal(),
                            outFeatureName, currentCell, buildFid(cellId.toString(), processedDistance),
                            statList.get(processedDistance).getStatsMap(), partner);
                } catch (Exception e) {
                    monitor.incrementErrors();
                    monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                            "Raster=" + targetID + ", Error writing cell " + cellId + " on " + geoName, e));

                    LOGGER.error("Raster=" + targetID + ", Error writing objects on " + geoName, e);
                }
            }

            // Update of the LoopCounter
            monitor.incrementCounter();
            monitor.newMessage(
                    new VulnerabilityMonitor.Message(TYPE.PROGRESS, "Calculating vulnerability for " + targetID));

            // DEBUG: indication of which arc is calculated
            if (LOGGER.isDebugEnabled() && currentCell != null) {
                LOGGER.debug("Raster=" + targetID + ", Computed cell " + cellId);
            }
        }
    }

    private FeatureIterator<SimpleFeature> getArcsForCell(String geoName, Filter partnerFilter,
            SimpleFeature currentCell) throws IOException {
        FeatureIterator<SimpleFeature> iterator;
        // Cell element
        Geometry cell = (Geometry) currentCell.getDefaultGeometry();
        String linearGeoName = geoName.replace("pl", "ln");
        FeatureSource<SimpleFeatureType, SimpleFeature> reader = createInputReader(dataStore, null, linearGeoName);
        // Iterator for selecting all the geometries
        // intersecting the cell

        Filter featureFilter = filterFactory.and(
                filterFactory.intersects(filterFactory.property(getInputGeometryName(dataStore, linearGeoName)),
                        filterFactory.literal(cell)),
                partnerFilter);

        FeatureCollection<SimpleFeatureType, SimpleFeature> features = reader.getFeatures(featureFilter);

        iterator = features.features();
        return iterator;
    }

    private void calculateBetchOfArcsForCell(RenderedImage currentImage, Map<Integer, TargetInfo> currentBPT,
            VulnerabilityStatsEngine vse, List<Double> allDistances, Map<Double, ResultStatsMap> statList,
            FeatureIterator<SimpleFeature> iterator, String cellId, int batchSize, VulnerabilityMonitor monitor,
            String targetID) throws Exception {

        List<SimpleFeature> arcList = new ArrayList<SimpleFeature>();
        Set<String> arcIds = new HashSet<String>();
        // Temporary counter used for calculating only a fixed number of geometries for each time
        int batchArcsCounter = 0;
        while (batchArcsCounter < batchSize && iterator.hasNext()) {
            SimpleFeature sf = (SimpleFeature) iterator.next();
            // addition of the simple feature to the
            // list
            arcList.add(sf);
            arcIds.add(sf.getAttribute(ID_GEO_ARCO).toString());
            batchArcsCounter++;
        }

        // BUFFER CALCULATION
        // If at least an arc is present
        if (!arcList.isEmpty()) {
            try {
                MultipleBufferMap mbm = vse.computeBuffersOnArcs(arcList, allDistances);

                for (Double processedDistance : allDistances) {
                    // Update of the currentDistance variable for exception logging
                    currentDistance = processedDistance;
                    // Creation of the ResultStatsMap for the selected distance if not present
                    if (!statList.containsKey(processedDistance)) {
                        statList.put(processedDistance, new ResultStatsMap(vulnerabilityCfg));
                    }
                    // Check if the distance is related
                    // to the selected target
                    Map<Integer, TargetInfo> acceptedBands = mapAcceptedBands(currentBPT, processedDistance);
                    // Statistics computation

                    // The statistics are calculated
                    // only if at least one of the targets
                    // accepts the current distance
                    if (!acceptedBands.isEmpty()) {
                        try {
                            vse.computeStats(mbm.getBuffersForDistance(processedDistance), currentImage,
                                    statList.get(processedDistance), false, acceptedBands);
                        } catch (Exception e) {
                            monitor.incrementErrors();
                            monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR,
                                    "Raster=" + targetID + ", CELL=(" + cellId
                                            + ") Error calculating stats on batch of arcs: "
                                            + StringUtils.join(arcIds, ","),
                                    e));

                            LOGGER.error("Raster=" + targetID + ", CELL=(" + cellId
                                    + ") Error calculating stats on batch of arcs: "
                                    + StringUtils.join(arcIds, ","), e);
                        }
                    }

                }
            } catch (Exception e) {
                monitor.incrementErrors();
                monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR, "Raster=" + targetID + ", CELL=("
                        + cellId + ") Error calculating buffers for arc " + StringUtils.join(arcIds, ","), e));
                LOGGER.error("Raster=" + targetID + ", CELL=(" + cellId + ") Error calculating buffers for arcs "
                        + StringUtils.join(arcIds, ","), e);
            }
        }
    }

    /**
     * Private method used for preparing the vulnerability operation associated to the input write mode
     * 
     * @param writeMode
     * @param vulnerabilityObj
     * @return
     * @throws IOException
     */
    private VulnerabilityOperation prepareVulnerabilityOperation(String writeMode, OutputObject vulnerabilityObj)
            throws IOException {
        VulnerabilityOperation concreteOperation = VulnerabilityOperation.instantiateWriterFromString(writeMode);
        LOGGER.info("Using writer " + VulnerabilityOperation.class);
        concreteOperation.initFeature(vulnerabilityObj, partner);
        // Setup filtering
        concreteOperation.setStartOriginId(startOriginId);
        concreteOperation.setEndOriginId(endOriginId);
        concreteOperation.setPageNumber(pageNumber);
        concreteOperation.setTotPages(totPages);

        return concreteOperation;
    }

    /**
     * Remove the initial features if the writeMode parameter is PURGE_INSERT
     * 
     * @param writeMode
     * @param aggregationLevel
     * @throws IOException
     */
    public void removeFeatures(String writeMode, int aggregationLevel) throws IOException {
        if (writeMode.equalsIgnoreCase("PURGE_INSERT")) {
            // Selection of the type name
            String outFeatureName = getTypeName(VULNERABILITY_TYPE_NAME, aggregationLevel);
            // Creation of a new Transaction
            Transaction transaction = new DefaultTransaction();
            try {
                // Preparing of the Purge_Insert operation which removes all the features already present
                OutputObject vulnerabilityObj = new OutputObject(dataStore, transaction, outFeatureName, GEOID);
                prepareVulnerabilityOperation(writeMode, vulnerabilityObj);
            } finally {
                // Closing Transaction
                transaction.close();
            }
        }
    }

    /**
     * Private method used for checking if the input feature has been already calculated.
     * 
     * @param targetID
     * @param skipArcs
     * @param outFeatureName
     * @param transaction
     * @param inputFeature
     * @param featureSize
     * @return
     * @throws IOException
     */
    /*private int checkInputFeature(String targetID, boolean skipArcs, String outFeatureName,
        Transaction transaction, SimpleFeature inputFeature, int featureSize)
        throws IOException {
    if (inputFeature != null && skipArcs && targetID.equalsIgnoreCase("NotHuman")) {
        // Selection of the id associated to the
        // feature.
        BigDecimal arcId = ((BigDecimal) inputFeature.getAttribute(ID_GEO_ARCO));
        
        if (!FeatureLoaderUtils
                .createFeatureSource(dataStore, transaction, outFeatureName)
                .getFeatures(
                        filterFactory.equals(filterFactory.property(GEOID),
                                filterFactory.literal(arcId))).isEmpty()) {
            featureSize = 0;
        }
    }
    return featureSize;
    }*/

    /**
     * Private method which returns the Geometry list associated to the processed distance
     * 
     * @param bufferList
     * @param processedDistance
     * @return
     */
    private static List<Geometry> calculateGeometryList(List<MultipleBufferMap> bufferList,
            Double processedDistance) {
        List<Geometry> geometryList = new ArrayList<Geometry>();
        // Addition of the buffer
        // associated with the
        // selected distance and arc
        for (MultipleBufferMap mbm : bufferList) {

            // Use the cell for crop
            // the raster if the
            // aggregation level ==
            // 3, use the buffer
            // otherwise
            Geometry bufferArea = (Geometry) mbm.getBuffersForDistance(processedDistance).get(0);

            geometryList.add(bufferArea);
        }
        return geometryList;
    }

    /**
     * Private method for writing the results on the Database for the level 3
     * 
     * @param targetID
     * @param outFeatureName
     * @param trace
     * @param errors
     * @param vulnerabilityObj
     * @param concreteOperation
     * @param inputFeature
     * @param allDistances
     * @param geoName
     * @param total
     * @param idArco
     * @param statList
     * @return
     * @throws IOException
         
    private int writeResultsOnDB(String targetID, String outFeatureName, int trace, int errors,
        OutputObject vulnerabilityObj, VulnerabilityOperation concreteOperation,
        SimpleFeature inputFeature, List<Double> allDistances, String geoName, 
        String idArco, Map<Double, ResultStatsMap> statList, VulnerabilityMonitor monitor) throws IOException {
    // Iteration on all the buffers
    for (Double processedDistance : allDistances) {
        try {
            // Writing of the result for the
            // selected distance and Id
            concreteOperation.writeOutputObjects(trace, vulnerabilityObj, monitor.getTotal(),
                    outFeatureName, inputFeature, buildFid(idArco, processedDistance), statList
                            .get(processedDistance).getStatsMap(), partner);
        } catch (Exception e) {
            monitor.incrementErrors();
            monitor.newMessage(new VulnerabilityMonitor.Message(TYPE.ERROR, "Raster=" + targetID
                    + ", Error writing objects on " + geoName,
                    e));
                
            LOGGER.error("Raster=" + targetID + ", Error writing objects on " + geoName, e);
        }
    }
    return errors;
    }*/

    /**
     * Method which returns a map for all the accepted bands for the processed distance
     * 
     * @param inputAcceptedBands
     * @param currentBPT
     * @param processedDistance
     * @return
     */
    private Map<Integer, TargetInfo> mapAcceptedBands(Map<Integer, TargetInfo> currentBPT,
            Double processedDistance) {
        Map<Integer, TargetInfo> acceptedBands = new TreeMap<Integer, TargetManager.TargetInfo>();

        // Set of all the bands
        Set<Integer> keys = currentBPT.keySet();
        // Cycle on all the targets
        for (int band : keys) {
            // Selection of the
            // TargetInfo
            TargetInfo infoPerBand = currentBPT.get(band);
            // TargetManager associated
            TargetManager mng = infoPerBand.getManager();
            // If the distance is
            // related to the target,
            // then it is added to the
            // map of the accepted band
            if (mng.isDistanceRelatedToTarget(processedDistance)) {
                acceptedBands.put(band, infoPerBand);
            }
        }
        return acceptedBands;
    }

    /**
     * Build the Fid associated to the arcId
     * 
     * @param idArco
     * @param el
     * @return
     */
    private static String buildFid(String idArco, Double el) {
        return idArco + "." + el.intValue();
    }

    /**
     * Method used for merging the input Rasters into a 2 images, one for human targets and the other for not human targets
     * 
     * @param humanTargets
     * @param notHumanTargets
     * @param bandPerTargetH
     * @param bandPerTargetNH
     * @throws IOException
     * @throws java.awt.geom.NoninvertibleTransformException
     * @throws TransformException
     * @throws MismatchedDimensionException
     */
    public RenderedImage[] rasterCalculation(Map<Integer, TargetInfo> bandPerTargetH,
            Map<Integer, TargetInfo> bandPerTargetNH) throws IOException,
            java.awt.geom.NoninvertibleTransformException, MismatchedDimensionException, TransformException {
        // Initialization of the images
        RenderedImage humanTargets = null;
        RenderedImage notHumanTargets = null;
        String basePath = System.getProperty(RASTER_PATH_PROP, "");
        if (!basePath.equals("")) {
            basePath = basePath + File.separator + codicePartner;
        }
        // Read of the resources
        Map vulnerabilityConf = (Map) readResourceFromXML("/vulnerability.xml");
        // Vulnerability engine used for extracting the Targets
        VulnerabilityStatsEngine vsengine = new VulnerabilityStatsEngine(basePath, vulnerabilityConf, dataStore,
                DISTANCE_TYPE_NAME, pixelArea);
        // Target Map
        Map<String, TargetInfo> targetInfo = vsengine.getTargetInfo();

        /*
         * Creation of 2 images: one for the HUMAN TARGETS and the other for NOT HUMAN TARGETS
         */
        // List of Human Targets
        List<RenderedImage> humanList = new ArrayList<RenderedImage>();

        // List of Not Human Targets
        List<RenderedImage> notHumanList = new ArrayList<RenderedImage>();

        // Counters indicating which band is associated to the TargetInfo and
        // Image
        int humanBandCounter = 0;
        int notHumanBandCounter = 0;

        // Iterator on all the targets
        Iterator<String> rasterIter = targetInfo.keySet().iterator();

        // Initializations of the parameters for merging the input rasters
        Envelope2D globalBBOXHuman = null;
        Envelope2D globalBBOXNotHuman = null;
        List<AffineTransform> tfHuman = new ArrayList<AffineTransform>();
        List<AffineTransform> tfNotHuman = new ArrayList<AffineTransform>();
        AffineTransform g2WHuman = null;
        AffineTransform g2WNotHuman = null;
        // Cycle on all the rasters
        while (rasterIter.hasNext()) {
            // save the ID of this target
            String targetID = rasterIter.next();

            // Load the target manager, init its status and check if the actual
            // distance is a valid distance for it
            TargetInfo info = targetInfo.get(targetID);

            // Getting of the transformation parameters
            GridGeometry2D gg2D = info.getGG2D();
            Envelope2D envelope = gg2D.getEnvelope2D();
            AffineTransform w2g = (AffineTransform) gg2D.getCRSToGrid2D(PixelOrientation.UPPER_LEFT);
            // getting information about current Target
            TargetManager manager = info.getManager();

            // Image associated to the current target
            RenderedImage newImage = info.getRaster();
            // Image data type
            int imgDataType = newImage.getSampleModel().getDataType();
            // Check if the image really exists
            if (newImage != null) {
                // If the target is human
                if (manager.isHumanTarget()) {
                    // Other check for ensuring the target is correct
                    if (imgDataType != DataBuffer.TYPE_FLOAT) {
                        System.out.println("Wrong data type");
                    }

                    // perform union
                    if (globalBBOXHuman == null) {
                        globalBBOXHuman = new Envelope2D(envelope);
                    } else {
                        globalBBOXHuman.include(envelope);
                    }
                    // Selection of the first g2w transform as the global one
                    if (g2WHuman == null) {
                        g2WHuman = (AffineTransform) gg2D.getGridToCRS2D(PixelOrientation.UPPER_LEFT);
                    }

                    // Creation of the transformation from destination Raster space to source Raster space
                    AffineTransform temp = new AffineTransform(w2g);
                    temp.concatenate(g2WHuman);
                    tfHuman.add(temp);

                    // Addition of the TargetInfo of this target
                    bandPerTargetH.put(humanBandCounter, info);
                    // Update of the bandCounter
                    humanBandCounter++;
                    // Addition of the image to the associated list
                    humanList.add(newImage);

                } else {
                    // Other check for ensuring the target is correct
                    if (imgDataType != DataBuffer.TYPE_BYTE) {
                        System.out.println("Wrong data type");
                    }

                    // perform union
                    if (globalBBOXNotHuman == null) {
                        globalBBOXNotHuman = envelope;
                    } else {
                        globalBBOXNotHuman.include(envelope);
                    }
                    // Selection of the first g2w transform as the global one
                    if (g2WNotHuman == null) {
                        g2WNotHuman = (AffineTransform) gg2D.getGridToCRS2D(PixelOrientation.UPPER_LEFT);
                    }
                    // Creation of the transformation from destination Raster space to source Raster space
                    AffineTransform temp = new AffineTransform(w2g);
                    temp.concatenate(g2WNotHuman);
                    tfNotHuman.add(temp);

                    // Addition of the TargetInfo of this target
                    bandPerTargetNH.put(notHumanBandCounter, info);
                    // Update of the bandCounter
                    notHumanBandCounter++;
                    // Addition of the image to the associated list
                    notHumanList.add(newImage);
                }
            }
        }

        // computing final raster space for the two targets
        GridGeometry2D humanGG2D = new GridGeometry2D(PixelInCell.CELL_CORNER, new AffineTransform2D(g2WHuman),
                globalBBOXHuman, null);
        globalBBOXHuman = humanGG2D.getEnvelope2D(); // take into account integer pixel roundings

        GridGeometry2D noHumanGG2D = new GridGeometry2D(PixelInCell.CELL_CORNER, new AffineTransform2D(g2WNotHuman),
                globalBBOXNotHuman, null);
        globalBBOXNotHuman = noHumanGG2D.getEnvelope2D(); // take into account integer pixel roundings

        // BandMerge of the images
        RenderedImage[] imagesHuman = new RenderedImage[humanList.size()];
        RenderedImage[] imagesNotHuman = new RenderedImage[notHumanList.size()];
        // Setting of the final layout
        ImageLayout layoutH = new ImageLayout2();
        GridEnvelope2D gridRange2D = humanGG2D.getGridRange2D();
        layoutH.setMinX(gridRange2D.x);
        layoutH.setMinY(gridRange2D.y);
        layoutH.setWidth(gridRange2D.width);
        layoutH.setHeight(gridRange2D.height);
        // Definition of the TileCache
        RenderingHints hintsH = new RenderingHints(JAI.KEY_TILE_CACHE, JAI.getDefaultInstance().getTileCache());
        // Setting of the layout as hint
        hintsH.put(JAI.KEY_IMAGE_LAYOUT, layoutH);
        // Merging of the input human targets
        humanTargets = BandMergeDescriptor.create(null, 0, hintsH, tfHuman, humanList.toArray(imagesHuman));
        // Setting of the final layout
        ImageLayout layoutNH = new ImageLayout2();
        gridRange2D = noHumanGG2D.getGridRange2D();
        layoutNH.setMinX(gridRange2D.x);
        layoutNH.setMinY(gridRange2D.y);
        layoutNH.setWidth(gridRange2D.width);
        layoutNH.setHeight(gridRange2D.height);
        // Definition of the TileCache
        RenderingHints hintsNH = new RenderingHints(JAI.KEY_TILE_CACHE, JAI.getDefaultInstance().getTileCache());
        hintsNH.put(JAI.KEY_IMAGE_LAYOUT, layoutNH);
        // Merging of the input not human targets
        notHumanTargets = BandMergeDescriptor.create(null, 0, hintsNH, tfNotHuman,
                notHumanList.toArray(imagesNotHuman));

        // cache the final images
        humanTargets = NullDescriptor.create(humanTargets,
                new RenderingHints(JAI.KEY_TILE_CACHE, JAI.getDefaultInstance().getTileCache()));

        notHumanTargets = NullDescriptor.create(notHumanTargets,
                new RenderingHints(JAI.KEY_TILE_CACHE, JAI.getDefaultInstance().getTileCache()));

        // Clearing of the initial lists
        notHumanList.clear();
        humanList.clear();
        // create a new array of the new images
        return new RenderedImage[] { humanTargets, notHumanTargets };
    }

    /**
     * Method used for extracting the cells from this vulnerability object. If a cell ID is set and skipArcs is true, then only the cells which are
     * greater than that selected are used.
     * 
     * @param cellStart
     * @param skipArcs
     * @return
     * @throws IOException
     */
    public FeatureCollection<SimpleFeatureType, SimpleFeature> geometryIDList(String cellStart, boolean skipArcs)
            throws IOException {
        // Define the aggregation level
        int aggregationLevel = 3;
        // setup geo input / output object
        String geoName = getTypeName(GEO_TYPE_NAME, aggregationLevel);
        geoName = geoName.replace("ln", "pl");
        createInputReader(dataStore, null, geoName);

        // Setting of the input filter
        // Simple filter on the partner

        Filter filter = filterFactory.equals(filterFactory.property(PARTNER_FIELD), filterFactory.literal(partner));
        // Needed if the user restart the computation from the cellStart id
        if (skipArcs && cellStart != null) {
            filter = filterFactory.and(filter,
                    filterFactory.greaterOrEqual(filterFactory.property(GEOID), filterFactory.literal(cellStart)));
        }

        setInputFilter(filter);

        FeatureCollection<SimpleFeatureType, SimpleFeature> cells = readCollectionSorted();

        return cells;
    }

}