/* * 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.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 a 2D dataset from Cartesian to Polar coordinates and return that remapped dataset * and an unclipped unit version (for clipping compensation) * * Cartesian coordinate system is x from left to right and y from top to bottom on the display * so corresponding polar coordinate is radius from centre and azimuthal angle clockwise from positive x axis */ public class MapToPolar implements DatasetToDatasetFunction { double cx, cy; double srad, sphi, erad, ephi; /** * Set up mapping of annular sector of 2D dataset * * @param x * centre x * @param y * centre y * @param sr * start radius * @param sp * start phi in degrees * @param er * end radius * @param ep * end phi in degrees */ public MapToPolar(double x, double y, double sr, double sp, double er, double ep) { this(x, y, sr, sp, er, ep, true); } /** * @param x * @param y * @param sr * @param sp * @param er * @param ep * @param isDegrees */ public MapToPolar(double x, double y, double sr, double sp, double er, double ep, boolean isDegrees) { cx = x; cy = y; srad = sr; erad = er; if (isDegrees) { sphi = Math.toRadians(sp); ephi = Math.toRadians(ep); } else { sphi = sp; ephi = ep; } if (sphi > ephi) { double tphi = sphi; sphi = ephi; ephi = tphi; } } /** * The class implements mapping of a Cartesian grid sampled data (pixels) to polar grid * * @param datasets * input 2D dataset * @return two 2D dataset where rows label radii and columns label azimuthal angles */ @Override public List<Dataset> value(IDataset... datasets) { if (datasets.length == 0) return null; List<Dataset> result = new ArrayList<Dataset>(); for (IDataset ids : datasets) { if (ids.getRank() != 2) throw new IllegalArgumentException("operating on 2d arrays only"); Dataset ds = DatasetUtils.convertToDataset(ids); // work out azimuthal resolution as roughly equal to pixel at outer radius double dphi = 1.0 / erad; int nr = (int) Math.ceil(erad - srad); int np = (int) Math.ceil((ephi - sphi) / dphi); if (nr == 0) nr = 1; if (np == 0) np = 1; Dataset polarmap = DatasetFactory.zeros(new int[] { nr, np }, DTypeUtils.getBestFloatDType(ds.getDType())); Dataset unitpolarmap = DatasetFactory.zeros(polarmap); // unclipped polar of unit field double rad, phi; double x, y; for (int r = 0; r < nr; r++) { rad = srad + r; for (int p = 0; p < np; p++) { unitpolarmap.set(dphi * rad, r, p); phi = sphi + p * dphi; x = cx + rad * Math.cos(phi); y = cy + rad * Math.sin(phi); polarmap.set(dphi * rad * Maths.interpolate(ds, y, x), r, p); } } result.add(polarmap); result.add(unitpolarmap); } return result; } }