protected OperationData process(IDataset input, IMonitor monitor) throws OperationException {

    double d = (2 * Math.PI) / model.getqValue();
    double p = (2 * Math.PI) / (model.getqValue() + model.getqDelta());
    double m = (2 * Math.PI) / (model.getqValue() - model.getqDelta());

    IDiffractionMetadata dm = getFirstDiffractionMetadata(input);
    if (dm == null) throw new OperationException(this, "No calibration information!");

    IParametricROI[] inOut = new IParametricROI[2];

    IParametricROI conic =
        (IParametricROI)
            DSpacing.conicFromDSpacing(
                dm.getDetector2DProperties(), dm.getDiffractionCrystalEnvironment(), d);
    inOut[0] =
        (IParametricROI)
            DSpacing.conicFromDSpacing(
                dm.getDetector2DProperties(), dm.getDiffractionCrystalEnvironment(), m);
    inOut[1] =
        (IParametricROI)
            DSpacing.conicFromDSpacing(
                dm.getDetector2DProperties(), dm.getDiffractionCrystalEnvironment(), p);

    PolylineROI points =
        PeakFittingEllipseFinder.findPointsOnConic(
            DatasetUtils.convertToDataset(input), null, conic, inOut, 256, null);

    double rms = -1;
    double[] semi = new double[2];
    double[] point = new double[2];
    double ang = 0;

    if (points != null && points.getNumberOfPoints() < 3) {

      EllipticalFitROI efroi = PowderRingsUtils.fitAndTrimOutliers(null, points, 2, false);
      rms = efroi.getRMS();
      semi = efroi.getSemiAxes();
      point = efroi.getPoint();
      ang = efroi.getAngleDegrees();
    }

    Dataset r = DatasetFactory.createFromObject(new double[] {rms});
    r.setName("rms");

    Dataset ax = DatasetFactory.createFromObject(semi);
    ax.setName("semi-axes");

    Dataset po = DatasetFactory.createFromObject(point);
    po.setName("centre");

    Dataset a = DatasetFactory.createFromObject(new double[] {ang});
    a.setName("angle");

    return new OperationData(input, new Serializable[] {r, ax, po, a});
  }
  /**
   * Fetch diffraction metadata, doesn't add it to the IDataset
   *
   * @param image
   * @param altPath alternative for file path if metadata is null or does not hold it
   * @param service
   * @param statusText returned message (can be null)
   * @return diffraction metadata
   */
  public static IDiffractionMetadata getDiffractionMetadata(
      IDataset image, String altPath, ILoaderService service, String[] statusText) {
    // Now always returns IDiffractionMetadata to prevent creation of a new
    // metadata object after listeners have been added to the old metadata
    // TODO improve this section- it's pretty horrible
    IDiffractionMetadata lockedMeta = service.getLockedDiffractionMetaData();

    if (image == null) return lockedMeta;

    int[] shape = image.getShape();
    IMetadata mdImage = null;
    try {
      mdImage = image.getMetadata();
    } catch (Exception e1) {
      // do nothing
    }
    if (lockedMeta != null) {
      if (mdImage instanceof IDiffractionMetadata) {
        IDiffractionMetadata dmd = (IDiffractionMetadata) mdImage;
        if (!dmd.getDiffractionCrystalEnvironment()
                .equals(lockedMeta.getDiffractionCrystalEnvironment())
            || !dmd.getDetector2DProperties().equals(lockedMeta.getDetector2DProperties())) {
          try {
            DiffractionMetadataUtils.copyNewOverOld(lockedMeta, (IDiffractionMetadata) mdImage);
          } catch (IllegalArgumentException e) {
            if (statusText != null)
              statusText[0] = "Locked metadata does not match image dimensions!";
          }
        }
      } else {
        // TODO what if the image is rotated?

        if (shape[0] == lockedMeta.getDetector2DProperties().getPx()
            && shape[1] == lockedMeta.getDetector2DProperties().getPy()) {
        } else {
          IDiffractionMetadata clone = lockedMeta.clone();
          clone.getDetector2DProperties().setPx(shape[0]);
          clone.getDetector2DProperties().setPy(shape[1]);
          if (statusText != null)
            statusText[0] = "Locked metadata does not match image dimensions!";
        }
      }
      if (statusText != null && statusText[0] == null) {
        statusText[0] = "Metadata loaded from locked version";
      }
      return lockedMeta;
    }

    // If not see if the trace has diffraction meta data
    if (mdImage instanceof IDiffractionMetadata) {
      if (statusText != null && statusText[0] == null) {
        statusText[0] = "Metadata loaded from image";
      }
      return (IDiffractionMetadata) mdImage;
    }

    // Try and get the filename here, it will help later on
    String filePath = mdImage == null ? null : mdImage.getFilePath();

    if (filePath == null) {
      filePath = altPath;
    }

    if (filePath != null) {
      // see if we can read diffraction info from nexus files
      NexusDiffractionMetaCreator ndmc = new NexusDiffractionMetaCreator(filePath);
      IDiffractionMetadata difMet = ndmc.getDiffractionMetadataFromNexus(shape);
      if (difMet != null) {
        // TODO comment out
        // image.setMetadata(difMet);
        if (statusText != null && statusText[0] == null) {
          if (ndmc.isCompleteRead()) {
            statusText[0] = "Metadata completely loaded from nexus tree";
            return difMet;
          } else if (ndmc.isPartialRead()) {
            statusText[0] = "Required metadata loaded from nexus tree";
            return difMet;
          } else if (ndmc.anyValuesRead())
            statusText[0] = "Incomplete metadata in nexus tree, loading from preferences";
          else statusText[0] = "No metadata in nexus tree, metadata loaded from preferences";
        }
      }
    }

    // if it is null try and get it from the loader service
    if (mdImage == null && filePath != null) {
      IMetadata md = null;
      try {
        md = service.getMetadata(filePath, null);
      } catch (Exception e) {
        logger.error("Cannot read meta data from part", e);
      }

      // If it is there and diffraction data return it
      if (md instanceof IDiffractionMetadata) {
        if (statusText != null && statusText[0] == null) {
          statusText[0] = "Metadata loaded from file";
        }
        return (IDiffractionMetadata) md;
      }
    }

    // if there is no meta or is not nexus or IDiff create default IDiff and put it in the dataset
    mdImage = DiffractionDefaultMetadata.getDiffractionMetadata(filePath, shape);
    // image.setMetadata(mdImage);
    if (statusText != null && statusText[0] == null) {
      statusText[0] = "No metadata found. Values loaded from preferences:";
    }
    return (IDiffractionMetadata) mdImage;
  }