/*
* Copyright (c) 2012 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package uk.ac.diamond.scisoft.analysis.dataset.function;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.dawnsci.analysis.dataset.impl.function.DatasetToDatasetFunction;
import org.eclipse.dawnsci.analysis.dataset.roi.RectangularROI;
import org.eclipse.january.dataset.DTypeUtils;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.DatasetFactory;
import org.eclipse.january.dataset.DatasetUtils;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.Maths;
/**
* Map and integrate a 2D dataset from Cartesian to rotated Cartesian coordinates, sum over each axis
* and return those sums and the corresponding sums for an unclipped unit version (for clipping compensation)
*/
public class MapToRotatedCartesianAndIntegrate implements DatasetToDatasetFunction {
int ox, oy;
int h, w;
double phi;
private double cp;
private double sp;
Dataset mask;
/**
* Set detector mask used profile calculations
*
* @param mask
*/
public void setMask(Dataset mask) {
this.mask = mask;
}
/**
* Set up mapping of rotated 2D dataset
*
* @param x
* top left x (in pixel coordinates)
* @param y
* top left y
* @param width size along major axis
* @param height size along minor axis
* @param angle in degrees
* (clockwise from positive x axis)
*/
public MapToRotatedCartesianAndIntegrate(int x, int y, int width, int height, double angle) {
ox = x;
oy = y;
h = height;
w = width;
phi = Math.toRadians(angle);
// work out cosine and sine
cp = Math.cos(phi);
sp = Math.sin(phi);
}
/**
* @param x
* @param y
* @param width size along major axis
* @param height size along minor axis
* @param angle
* @param isDegrees
*/
public MapToRotatedCartesianAndIntegrate(int x, int y, int width, int height, double angle, boolean isDegrees) {
ox = x;
oy = y;
h = height;
w = width;
if (isDegrees) {
phi = Math.toRadians(angle);
} else {
phi = angle;
}
// work out cosine and sine
cp = Math.cos(phi);
sp = Math.sin(phi);
}
/**
* @param roi
*/
public MapToRotatedCartesianAndIntegrate(RectangularROI roi) {
int[] pt = roi.getIntPoint();
int[] len = roi.getIntLengths();
ox = pt[0];
oy = pt[1];
w = len[0];
h = len[1];
phi = roi.getAngle();
// work out cosine and sine
cp = Math.cos(phi);
sp = Math.sin(phi);
}
/**
* The class implements mapping of a Cartesian grid sampled data (pixels) to another Cartesian grid
*
* @param datasets
* input 2D dataset
* @return two pairs of 1D dataset for column (or minor axis) and row (or major axis) integration of
* a rotated dataset (second pair is for unclipped unit version of input dataset)
*/
@Override
public List<Dataset> value(IDataset... datasets) {
if (datasets.length == 0)
return null;
List<Dataset> result = new ArrayList<Dataset>();
double msk = 1;
for (IDataset ids : datasets) {
if (ids.getRank() != 2)
return null;
Dataset ds = DatasetUtils.convertToDataset(ids);
final int dtype = DTypeUtils.getBestFloatDType(ds.getDType());
Dataset sumx = DatasetFactory.zeros(new int[] { h }, dtype);
Dataset sumy = DatasetFactory.zeros(new int[] { w }, dtype);
Dataset usumx = DatasetFactory.zeros(new int[] { h }, dtype);
Dataset usumy = DatasetFactory.zeros(new int[] { w }, dtype);
double cx, cy;
double csum;
double cusumx;
for (int y = 0; y < h; y++) {
csum = 0.0;
cusumx = 0.0;
for (int x = 0; x < w; x++) {
// back transformation from tilted to original coordinates
cx = ox + x * cp - y * sp;
cy = oy + x * sp + y * cp;
if (mask != null)
msk = Maths.interpolate(mask, y, x);
final double v = Maths.interpolate(ds, mask, cy, cx);
sumy.set(v + sumy.getDouble(x), x);
usumy.set(msk + usumy.getDouble(x), x);
csum += v;
cusumx += msk;
}
sumx.set(csum, y);
usumx.set(cusumx, y);
}
result.add(sumx);
result.add(sumy);
result.add(usumx);
result.add(usumy);
}
return result;
}
/**
*
* @param datasets
* @return maximum value in
*/
public List<Dataset> maxValue(IDataset... datasets) {
if (datasets.length == 0)
return null;
List<Dataset> result = new ArrayList<Dataset>();
for (IDataset ids : datasets) {
if (ids.getRank() != 2)
return null;
Dataset ds = DatasetUtils.convertToDataset(ids);
final int dtype = DTypeUtils.getBestFloatDType(ds.getDType());
Dataset mx = DatasetFactory.zeros(new int[] { h }, dtype);
Dataset my = DatasetFactory.zeros(new int[] { w }, dtype);
double cx, cy;
double cmax;
for (int y = 0; y < h; y++) {
cmax = Double.NEGATIVE_INFINITY;
for (int x = 0; x < w; x++) {
// back transformation from tilted to original coordinates
cx = ox + x * cp - y * sp;
cy = oy + x * sp + y * cp;
final double v = Maths.interpolate(ds, mask, cy, cx);
my.set(Math.max(v, my.getDouble(x)), x);
if (v > cmax)
cmax = v;
}
mx.set(cmax, y);
}
result.add(mx);
result.add(my);
}
return result;
}
}