use of uk.ac.rdg.resc.edal.cdm.PixelMap in project ncWMS by Unidata.
the class NcwmsController method readSmoothedDataGrid.
private List<Float> readSmoothedDataGrid(ScalarLayer layer, DateTime dateTime, double elevation, RegularGrid imageGrid, UsageLogEntry usageLogEntry) throws InvalidDimensionValueException, IOException {
int width = imageGrid.getXAxis().getSize();
int height = imageGrid.getYAxis().getSize();
RectilinearGrid dataGrid;
if (!(layer.getHorizontalGrid() instanceof RectilinearGrid)) {
return layer.readHorizontalPoints(dateTime, elevation, imageGrid);
} else {
dataGrid = (RectilinearGrid) layer.getHorizontalGrid();
}
PixelMap pixelMap = new PixelMap(dataGrid, imageGrid);
/*
* Check whether it is worth smoothing this data
*/
int imageSize = width * height;
if (pixelMap.getNumUniqueIJPairs() >= imageSize || pixelMap.getNumUniqueIJPairs() == 0) {
/*
* We don't need to smooth the data
*/
return layer.readHorizontalPoints(dateTime, elevation, imageGrid);
}
ReferenceableAxis xAxis = dataGrid.getXAxis();
ReferenceableAxis yAxis = dataGrid.getYAxis();
SortedSet<Double> xCoords = new TreeSet<Double>();
SortedSet<Double> yCoords = new TreeSet<Double>();
double minX = imageGrid.getXAxis().getCoordinateValue(0);
/*
* Loop through all points on the data grid which are needed, and add
* them to sorted sets
*/
Iterator<PixelMapEntry> iterator = pixelMap.iterator();
while (iterator.hasNext()) {
PixelMapEntry pme = iterator.next();
xCoords.add(Utils.getNextEquivalentLongitude(minX, xAxis.getCoordinateValue(pme.getSourceGridIIndex())));
yCoords.add(yAxis.getCoordinateValue(pme.getSourceGridJIndex()));
}
Float[][] data = new Float[xCoords.size()][yCoords.size()];
final CoordinateReferenceSystem crs = layer.getHorizontalGrid().getCoordinateReferenceSystem();
final List<HorizontalPosition> pointsToRead = new ArrayList<HorizontalPosition>();
/*
* Loop through required coords and add to a list to read
*/
for (Double x : xCoords) {
for (Double y : yCoords) {
pointsToRead.add(new HorizontalPositionImpl(x, y, crs));
}
}
/*
* Use the list to read all required points at once
*/
List<Float> points;
try {
points = layer.readHorizontalPoints(dateTime, elevation, new Domain<HorizontalPosition>() {
@Override
public CoordinateReferenceSystem getCoordinateReferenceSystem() {
return crs;
}
@Override
public List<HorizontalPosition> getDomainObjects() {
return pointsToRead;
}
@Override
public long size() {
return pointsToRead.size();
}
});
} catch (InvalidDimensionValueException e) {
e.printStackTrace();
throw new IllegalArgumentException("Problem reading data");
} catch (IOException e) {
e.printStackTrace();
throw new IllegalArgumentException("Problem reading data");
}
/*
* Now populate the data array
*/
int index = 0;
for (int i = 0; i < xCoords.size(); i++) {
for (int j = 0; j < yCoords.size(); j++) {
data[i][j] = points.get(index++);
}
}
/*
* All data reading is done at this point. We now interpolate onto each
* image point, using a BilinearInterpolator
*/
BilinearInterpolator interpolator = new BilinearInterpolator(xCoords, yCoords, data);
List<Float> retData = new ArrayList<Float>();
for (int j = 0; j < height; j++) {
double y = imageGrid.getYAxis().getCoordinateValue(j);
for (int i = 0; i < width; i++) {
double x = imageGrid.getXAxis().getCoordinateValue(i);
retData.add(interpolator.getValue(x, y));
// retData[i][height - 1 - j] = interpolator.getValue(x,y);
}
}
return retData;
}
use of uk.ac.rdg.resc.edal.cdm.PixelMap in project ncWMS by Unidata.
the class AbstractWmsController method readDataGrid.
/**
* Reads a grid of data from the given layer, used by the GetMap operation.
* <p>This implementation simply defers to {@link
* ScalarLayer#readPointList(org.joda.time.DateTime, double,
* uk.ac.rdg.resc.ncwms.datareader.PointList) layer.readPointList()},
* ignoring the usage log entry. No data are cached. Other implementations
* may choose to implement in a different way, perhaps to allow for caching
* of the data. If implementations return cached data they must indicate
* this by setting {@link UsageLogEntry#setUsedCache(boolean)}.</p>
* @param layer The layer containing the data
* @param time The time instant for which we require data. If this does not
* match a time instant in {@link Layer#getTimeValues()} an {@link InvalidDimensionValueException}
* will be thrown. (If this Layer has no time axis, this parameter will be ignored.)
* @param elevation The elevation for which we require data (in the
* {@link Layer#getElevationUnits() units of this Layer's elevation axis}). If
* this does not match a valid {@link Layer#getElevationValues() elevation value}
* in this Layer, this method will throw an {@link InvalidDimensionValueException}.
* (If this Layer has no elevation axis, this parameter will be ignored.)
* @param imageGrid The grid of points, one point per pixel in the image that will
* be created in the GetMap operation
* @param usageLogEntry
* @return a List of data values, one for each point in
* the {@code grid}, in the same order.
* @throws InvalidDimensionValueException if {@code dateTime} or {@code elevation}
* do not represent valid values along the time and elevation axes.
* @throws IOException if there was an error reading from the data source
*/
protected List<Float> readDataGrid(ScalarLayer layer, DateTime dateTime, double elevation, RegularGrid imageGrid, UsageLogEntry usageLogEntry, boolean smoothed) throws InvalidDimensionValueException, IOException {
if (!smoothed) {
return layer.readHorizontalPoints(dateTime, elevation, imageGrid);
} else {
int width = imageGrid.getXAxis().getSize();
int height = imageGrid.getYAxis().getSize();
RectilinearGrid dataGrid;
if (!(layer.getHorizontalGrid() instanceof RectilinearGrid)) {
return layer.readHorizontalPoints(dateTime, elevation, imageGrid);
} else {
dataGrid = (RectilinearGrid) layer.getHorizontalGrid();
}
PixelMap pixelMap = new PixelMap(dataGrid, imageGrid);
/*
* Check whether it is worth smoothing this data
*/
int imageSize = width * height;
if (pixelMap.getNumUniqueIJPairs() >= imageSize || pixelMap.getNumUniqueIJPairs() == 0) {
/*
* We don't need to smooth the data
*/
return layer.readHorizontalPoints(dateTime, elevation, imageGrid);
}
ReferenceableAxis xAxis = dataGrid.getXAxis();
ReferenceableAxis yAxis = dataGrid.getYAxis();
SortedSet<Double> xCoords = new TreeSet<Double>();
SortedSet<Double> yCoords = new TreeSet<Double>();
double minX = imageGrid.getXAxis().getCoordinateValue(0);
/*
* Loop through all points on the data grid which are needed, and add
* them to sorted sets
*/
Iterator<PixelMapEntry> iterator = pixelMap.iterator();
while (iterator.hasNext()) {
PixelMapEntry pme = iterator.next();
xCoords.add(Utils.getNextEquivalentLongitude(minX, xAxis.getCoordinateValue(pme.getSourceGridIIndex())));
yCoords.add(yAxis.getCoordinateValue(pme.getSourceGridJIndex()));
}
Float[][] data = new Float[xCoords.size()][yCoords.size()];
final CoordinateReferenceSystem crs = layer.getHorizontalGrid().getCoordinateReferenceSystem();
final List<HorizontalPosition> pointsToRead = new ArrayList<HorizontalPosition>();
/*
* Loop through required coords and add to a list to read
*/
for (Double x : xCoords) {
for (Double y : yCoords) {
pointsToRead.add(new HorizontalPositionImpl(x, y, crs));
}
}
/*
* Use the list to read all required points at once
*/
List<Float> points;
try {
points = layer.readHorizontalPoints(dateTime, elevation, new Domain<HorizontalPosition>() {
@Override
public CoordinateReferenceSystem getCoordinateReferenceSystem() {
return crs;
}
@Override
public List<HorizontalPosition> getDomainObjects() {
return pointsToRead;
}
@Override
public long size() {
return pointsToRead.size();
}
});
} catch (InvalidDimensionValueException e) {
e.printStackTrace();
throw new IllegalArgumentException("Problem reading data");
} catch (IOException e) {
e.printStackTrace();
throw new IllegalArgumentException("Problem reading data");
}
/*
* Now populate the data array
*/
int index = 0;
for (int i = 0; i < xCoords.size(); i++) {
for (int j = 0; j < yCoords.size(); j++) {
data[i][j] = points.get(index++);
}
}
/*
* All data reading is done at this point. We now interpolate onto each
* image point, using a BilinearInterpolator
*/
BilinearInterpolator interpolator = new BilinearInterpolator(xCoords, yCoords, data);
List<Float> retData = new ArrayList<Float>();
for (int j = 0; j < height; j++) {
double y = imageGrid.getYAxis().getCoordinateValue(j);
for (int i = 0; i < width; i++) {
double x = imageGrid.getXAxis().getCoordinateValue(i);
retData.add(interpolator.getValue(x, y));
}
}
return retData;
}
}
use of uk.ac.rdg.resc.edal.cdm.PixelMap in project ncWMS by Unidata.
the class PhaveosDataReader method read.
@Override
public List<Float> read(String filename, Layer layer, int tIndex, int zIndex, Domain<HorizontalPosition> targetDomain) throws IOException {
NetcdfDataset nc = null;
try {
nc = NetcdfDataset.openDataset(filename);
ucar.nc2.Variable var = nc.findVariable(layer.getId());
// We read in data using a "bounding box" strategy
PixelMap pm = new PixelMap(layer.getHorizontalGrid(), targetDomain);
int iSize = pm.getMaxIIndex() - pm.getMinIIndex() + 1;
int jSize = pm.getMaxJIndex() - pm.getMinJIndex() + 1;
int[] origin = new int[] { pm.getMinJIndex(), pm.getMinIIndex() };
int[] shape = new int[] { jSize, iSize };
Array data = var.read(origin, shape);
// Now copy the data to an array of floats
Index index = data.getIndex();
index.set(new int[index.getRank()]);
float[] arr = new float[(int) targetDomain.size()];
Arrays.fill(arr, Float.NaN);
for (PixelMapEntry pme : pm) {
int i = pme.getSourceGridIIndex() - pm.getMinIIndex();
int j = pme.getSourceGridJIndex() - pm.getMinJIndex();
index.set(new int[] { j, i });
float val = data.getFloat(index);
// Hack to deal with factor-1000 scale in L4 data
if ("mtci_l4".equals(layer.getId())) {
val /= 1000.0f;
}
for (int targetGridPoint : pme.getTargetGridPoints()) {
arr[targetGridPoint] = val > 0.0f ? val : Float.NaN;
}
}
return CdmUtils.wrap(arr);
} catch (InvalidRangeException ire) {
// Shouldn't happen: this would be a programming error
throw new RuntimeException(ire);
} finally {
if (nc != null) {
nc.close();
}
}
}
Aggregations