@Override
  public void process(ProcessletInputs in, ProcessletOutputs out, ProcessletExecutionInfo info)
      throws ProcessletException {
    try {

      // validate against allowed values in process definition file
      URL processDefinitionUrl =
          this.getClass().getResource("/" + this.getClass().getSimpleName() + ".xml");

      // get validated data inputs or default values
      DataInputHandler dataInputHandler =
          new DataInputHandler(new File(processDefinitionUrl.toURI()));
      String srsName = dataInputHandler.getValidatedStringValue(in, "srsName");
      String filter = dataInputHandler.getValidatedStringValue(in, "filter");
      double x = DataInputHandler.getDoubleInputValue(in, "x");
      double y = DataInputHandler.getDoubleInputValue(in, "y");
      double z = DataInputHandler.getDoubleInputValue(in, "z");

      LOG.debug(
          String.format(
              "DataInputs: srsName: %s, poi: (%f, %f, %f), filter: %s", srsName, x, y, z, filter));

      responseValues = new ResponseValues();
      responseValues.clientSrsName = srsName;

      // transform non-AGEA coordinates to AGEA
      if (!srsName.equals("Mouse_AGEA_1.0")) {
        ABAServiceVO vo = getTransformPOI(srsName, x, y, z);
        if (vo.getTransformationXMLResponseString().startsWith("Error:")) {
          throw new OWSException(
              "Transformation Coordinates Error: ", vo.getTransformationXMLResponseString());
        }
        x = Double.parseDouble(vo.getTransformedCoordinateX());
        y = Double.parseDouble(vo.getTransformedCoordinateY());
        z = Double.parseDouble(vo.getTransformedCoordinateZ());
      }

      LOG.debug("X from Transformation Method: " + x);
      LOG.debug("Y from Transformation Method: " + y);
      LOG.debug("Z from Transformation Method: " + z);

      String srsFromClient = srsName;
      Point3d poiFromClient = new Point3d(x, y, z);

      // get plane; defaults to sagittal
      ImageSeriesPlane desiredPlane =
          filter.equals("maptype:coronal") ? ImageSeriesPlane.CORONAL : ImageSeriesPlane.SAGITTAL;

      // 1. get strong gene(s) at POI
      List<ABAGene> strongGenes = ABAUtil.retrieveStrongGenesAtAGEAPOI(x, y, z, NBR_STRONG_GENES);

      // make sure we have something
      if (strongGenes.size() == 0) {
        throw new OWSException(
            "No 'strong genes' found at " + "coordinates, hence no images to return.",
            ControllerException.NO_APPLICABLE_CODE);
      }

      if (LOG.isDebugEnabled()) {
        StringBuilder buf = new StringBuilder();
        for (ABAGene gene : strongGenes) {
          buf.append(gene.getGenesymbol()).append(", ");
        }
        LOG.debug("Strong genes: {}", buf.toString());
      }

      // 2. get image series'es for strong genes and desired plane
      List<ImageSeries> imageSerieses = new ArrayList<ImageSeries>();
      for (ABAGene gene : strongGenes) {
        ImageSeries imageSeries = retrieveImagesSeriesForGene(gene.getGenesymbol(), desiredPlane);
        if (imageSeries != null) {
          imageSerieses.add(imageSeries);
        }
      }

      // make sure we have something
      if (imageSerieses.size() == 0) {
        throw new OWSException(
            "No image series found for 'strong "
                + "genes' and desired plane, hence no images to "
                + "return.",
            ControllerException.NO_APPLICABLE_CODE);
      }

      if (LOG.isDebugEnabled()) {
        StringBuilder buf = new StringBuilder();
        for (ImageSeries is : imageSerieses) {
          buf.append(is.imageSeriesId).append(':');
          buf.append(is.imageSeriesPlane).append(", ");
        }
        LOG.debug("Image Serieses id:plane: {}", buf.toString());
      }

      Point3d poiForProximity = new Point3d(poiFromClient);

      // divide POI coords by 100
      Point3d poi100 = new Point3d();
      poi100.scale(0.01, poiForProximity);

      LOG.debug("POI for closest position (srs, xyz): {}, {}", srsFromClient, poi100.toString());

      // 3. get ......... for each image series
      for (ImageSeries imageSeries : imageSerieses) {

        // begin to add values to image
        Image image = new Image(imageSeries.imageSeriesId);

        // get atlas map
        // find closest point, get other values including position
        // add more (atlas map) values to image
        getClosestPosition(imageSeries, poi100, image);

        LOG.debug("Position: {}", image.abaImagePosition);

        // get best image id in image series based on position
        // add more (image elements) values to image
        // match position to find image in series, get imageid
        //  /image-series/images/image/position
        //  /image-series/images/image/imageid
        retrieveImageForPosition(imageSeries.imageSeriesId, image.abaImagePosition, image);

        LOG.debug("Image id: {}", image.imageId);

        // zoom level not applicable
        // image.zoomLevel = zoomLevel;

        // assemble aba view image uri
        image.imageURI = assembleImageURI(image.downloadImagePath, HI_RES, MIME);
        image.thumbnailurl = assembleImageURI(image.downloadImagePath, THUMB, MIME);

        LOG.debug("Image URI: {}", image.imageURI.toString());

        responseValues.images.add(image);
      } // for

      // ImagesResponseDocument 'is a' org.apache.xmlbeans.XmlObject
      //	'is a' org.apache.xmlbeans.XmlTokenSource
      ImagesResponseDocument document = completeResponse();

      if (LOG.isDebugEnabled()) {
        XmlOptions opt = (new XmlOptions()).setSavePrettyPrint();
        opt.setSaveSuggestedPrefixes(Utilities.SuggestedNamespaces());
        opt.setSaveNamespacesFirst();
        opt.setSaveAggressiveNamespaces();
        opt.setUseDefaultNamespace();
        LOG.debug("Xml:\n{}", document.xmlText(opt));
      }

      // 4. Send it
      // get reader on document
      XMLStreamReader reader = document.newXMLStreamReader();

      // get ComplexOutput object from ProcessletOutput...
      ComplexOutput complexOutput = (ComplexOutput) out.getParameter("Get2DImagesByPOIOutput");

      LOG.debug("Setting complex output (requested=" + complexOutput.isRequested() + ")");

      // ComplexOutput objects can be huge so stream it
      XMLStreamWriter writer = complexOutput.getXMLStreamWriter();
      XMLAdapter.writeElement(writer, reader);

      // transform any exceptions into ProcessletException wrapping
      // OWSException
    } catch (MissingParameterException e) {
      LOG.error(e.getMessage(), e);
      throw new ProcessletException(new OWSException(e));
    } catch (InvalidParameterValueException e) {
      LOG.error(e.getMessage(), e);
      throw new ProcessletException(new OWSException(e));
    } catch (InvalidDataInputValueException e) {
      LOG.error(e.getMessage(), e);
      throw new ProcessletException(e); // is already OWSException
    } catch (OWSException e) {
      LOG.error(e.getMessage(), e);
      throw new ProcessletException(e); // is already OWSException
    } catch (Throwable e) {
      String message = "Unexpected exception occurred: " + e.getMessage();
      LOG.error(message, e);
      throw new ProcessletException(
          new OWSException(message, e, ControllerException.NO_APPLICABLE_CODE));
    }
  }
  public ABAServiceVO getTransformPOI(String fromSrsName, double x, double y, double z)
      throws OWSException {

    ABAConfigurator config = ABAConfigurator.INSTANCE;

    String tempX = "";
    String tempY = "";
    String tempZ = "";
    String toSrsName = "Mouse_AGEA_1.0";
    String hostName = "";
    String portNumber = "";
    String transformedCoordinatesString = "";
    ABAServiceVO vo = new ABAServiceVO();

    // Call getTransformationChain method here...
    // ABAVoxel
    LOG.debug("1.1:");

    tempX = ";x=" + String.valueOf(x);
    tempY = ";y=" + String.valueOf(y);
    tempZ = ";z=" + String.valueOf(z);

    String delimitor = config.getValue("incf.deploy.port.delimitor");

    hostName = config.getValue("incf.deploy.host.name");
    portNumber = config.getValue("incf.aba.port.number");
    portNumber = delimitor + portNumber;

    String servicePath =
        "/central/atlas?service=WPS&version=1.0.0&request=Execute&Identifier=GetTransformationChain&DataInputs=inputSrsName="
            + fromSrsName
            + ";outputSrsName="
            + toSrsName
            + ";filter=NONE";
    String transformationChainURL = "http://" + hostName + portNumber + servicePath;
    LOG.debug("1.4: {}", transformationChainURL);

    try {

      XMLUtilities xmlUtilities = new XMLUtilities();
      transformedCoordinatesString =
          xmlUtilities.coordinateTransformation(transformationChainURL, tempX, tempY, tempZ);

      LOG.debug("2:");
      // Start - exception handling
      /*	    	if (transformedCoordinatesString.startsWith("Error:")) {
      	    		LOG.debug("********************ERROR*********************");
      				throw new OWSException(
      						"Transformed Coordinates Error: ", transformedCoordinatesString);
      	    	}
      */
      // End - exception handling
      ABAUtil util = new ABAUtil();
      String[] tempArray = util.getTabDelimNumbers(transformedCoordinatesString);
      vo.setTransformedCoordinateX(tempArray[0]);
      vo.setTransformedCoordinateY(tempArray[1]);
      vo.setTransformedCoordinateZ(tempArray[2]);
      vo.setTransformationXMLResponseString(transformedCoordinatesString);

    } catch (Exception e) {
      e.printStackTrace();
    }

    return vo;
  }