Grid.java [src/java/util] Revision: default Date:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package util;
import csip.api.server.ServiceException;
import java.io.*;
import java.util.Scanner;
import java.util.Set;
import java.util.HashSet;
import util.WeppConstants.GridType;
/**
* Handles ArcGIS ASCII grids.
*
* @author jrf
*/
public class Grid {
int rows;
int cols;
int nodata;
double cellsize;
double xllcorner;
double yllcorner;
GridType type;
float[][] fdata;
int[][] idata;
byte[][] bdata;
//
// reads an existing grid
public Grid(GridType ty, String filename) throws IOException, ServiceException {
rows = 0;
cols = 0;
int curRow = 0;
boolean processHeader = true;
boolean hasnodata = false;
this.type = ty;
xllcorner = -9999;
yllcorner = -9999;
cellsize = 0;
BufferedReader input = new BufferedReader(new FileReader(filename));
while (input.ready()) {
String line = input.readLine();
if (processHeader) {
Scanner sc = new Scanner(line);
String name = sc.next();
if (name.equals("nrows")) {
rows = sc.nextInt();
} else if (name.equals("ncols")) {
cols = sc.nextInt();
} else if (name.equals("xllcorner")) {
xllcorner = sc.nextDouble();
} else if (name.equals("yllcorner")) {
yllcorner = sc.nextDouble();
} else if (name.equals("NODATA_value")) {
nodata = sc.nextInt();
hasnodata = true;
} else if (name.equals("cellsize")) {
cellsize = sc.nextDouble();
} else {
throw new ServiceException("Grid header unrecognized : " + filename);
}
if ((rows > 0) && (cols > 0) && (xllcorner != -9999) && (yllcorner != -9999) && (cellsize > 0) && (hasnodata)) {
processHeader = false;
curRow = 0;
if (ty == GridType.INT_GRID) {
idata = new int[rows][cols];
}
if (ty == GridType.FLOAT_GRID) {
fdata = new float[rows][cols];
}
if (ty == GridType.BYTE_GRID) {
bdata = new byte[rows][cols];
}
}
} else {
int row = 0;
line = line.trim();
String[] inData = line.split("\\s+");
if (ty == GridType.INT_GRID) {
for (int c = 0; c < cols; c++) {
idata[curRow][c] = Integer.parseInt(inData[c]);
}
} else if (ty == GridType.FLOAT_GRID) {
for (int c = 0; c < cols; c++) {
fdata[curRow][c] = Float.parseFloat(inData[c]);
}
} else {
for (int c = 0; c < cols; c++) {
bdata[curRow][c] = Byte.parseByte(inData[c]);
}
}
curRow = curRow + 1;
}
}
}
// clones an existing grid
public Grid(Grid par) {
this.rows = par.rows;
this.cols = par.cols;
this.nodata = par.nodata;
this.cellsize = par.cellsize;
this.type = par.type;
this.xllcorner = par.xllcorner;
this.yllcorner = par.yllcorner;
this.type = par.type;
if (type == GridType.INT_GRID) {
idata = new int[rows][cols];
// for (int i = 0; i < rows; i++) {
// for (int j = 0; j < cols; j++) {
// idata[i][j] = 0;
// }
// }
} else if (type == GridType.FLOAT_GRID) {
fdata = new float[rows][cols];
// for (int i = 0; i < rows; i++) {
// for (int j = 0; j < cols; j++) {
// fdata[i][j] = 0;
// }
// }
} else {
bdata = new byte[rows][cols];
// for (int i = 0; i < rows; i++) {
// for (int j = 0; j < cols; j++) {
// bdata[i][j] = 0;
// }
// }
}
}
// clones an existing grid
public Grid(Grid par, GridType ty, int nod) {
this.rows = par.rows;
this.cols = par.cols;
this.nodata = nod;
this.cellsize = par.cellsize;
this.type = ty;
this.xllcorner = par.xllcorner;
this.yllcorner = par.yllcorner;
if (ty == GridType.INT_GRID) {
idata = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
idata[i][j] = nod;
}
}
} else if (ty == GridType.FLOAT_GRID) {
fdata = new float[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
fdata[i][j] = nod;
}
}
} else {
bdata = new byte[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
bdata[i][j] = (byte) nod;
}
}
}
}
// creates a new, empty grid, initialized to zero
public Grid(GridType ty, int rows, int cols, int nodata, double cellsize, double xllcorner, double yllcorner) {
this.rows = rows;
this.cols = cols;
this.nodata = nodata;
this.cellsize = cellsize;
this.type = ty;
this.xllcorner = xllcorner;
this.yllcorner = yllcorner;
if (ty == GridType.INT_GRID) {
idata = new int[rows][cols];
// for (int i = 0; i < rows; i++) {
// for (int j = 0; j < cols; j++) {
// idata[i][j] = 0;
// }
// }
} else if (ty == GridType.FLOAT_GRID) {
fdata = new float[rows][cols];
// for (int i = 0; i < rows; i++) {
// for (int j = 0; j < cols; j++) {
// fdata[i][j] = 0;
// }
// }
} else {
bdata = new byte[rows][cols];
// for (int i = 0; i < rows; i++) {
// for (int j = 0; j < cols; j++) {
// bdata[i][j] = 0;
// }
// }
}
}
public void clear() {
if (rows == 0) {
return;
}
if (type == GridType.INT_GRID) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
idata[i][j] = nodata;
}
}
} else if (type == GridType.FLOAT_GRID) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
fdata[i][j] = nodata;
}
}
}
}
public int[][] getIntData() throws ServiceException {
if (rows == 0) {
return null;
}
if (type == GridType.INT_GRID) {
return idata;
} else {
throw new ServiceException("Grid type mismatch, int");
}
}
public float[][] getFloatData() throws ServiceException {
if (rows == 0) {
return null;
}
if (type == GridType.FLOAT_GRID) {
return fdata;
} else {
throw new ServiceException("Grid type mismatch, float");
}
}
public byte[][] getByteData() throws ServiceException {
if (rows == 0) {
return null;
}
if (type == GridType.BYTE_GRID) {
return bdata;
} else {
throw new ServiceException("Grid type mismatch, byte");
}
}
public int rowCount() {
return rows;
}
public int colCount() {
return cols;
}
public int getNoData() {
return nodata;
}
public float getFloatRowCol(int r, int c) {
if (fdata != null) {
if ((r < rows) && (c < cols)) {
return fdata[r][c];
}
}
return nodata;
}
public int getIntRowCol(int r, int c) {
if (idata != null) {
if ((r < rows) && (c < cols)) {
return idata[r][c];
}
}
return nodata;
}
public void writeWeightedGrid(Grid sedWeight, File f) throws IOException, ServiceException {
if (f.exists()) {
f.delete();
}
if (!f.createNewFile()) {
throw new ServiceException("Could not save grid file");
}
PrintStream o = new PrintStream(f);
o.println("ncols " + cols);
o.println("nrows " + rows);
o.println("xllcorner " + xllcorner);
o.println("yllcorner " + yllcorner);
o.println("cellsize " + cellsize);
o.println("NODATA_value " + nodata);
StringBuffer b = new StringBuffer();
if (type == GridType.INT_GRID) {
for (int r = 0; r < rows; r++) {
b.delete(0, b.length());
for (int c = 0; c < cols; c++) {
b.append((idata[r][c]) / sedWeight.idata[r][c]);
if (c < (cols - 1)) {
b.append(" ");
}
}
o.println(b);
}
} else if (type == GridType.FLOAT_GRID) {
for (int r = 0; r < rows; r++) {
b.delete(0, b.length());
for (int c = 0; c < cols; c++) {
if (fdata[r][c] == nodata) {
b.append(nodata);
} else {
b.append((fdata[r][c]) / sedWeight.fdata[r][c]);
}
if (c < (cols - 1)) {
b.append(" ");
}
}
o.println(b);
}
} else {
for (int r = 0; r < rows; r++) {
b.delete(0, b.length());
for (int c = 0; c < cols; c++) {
b.append((bdata[r][c]) / sedWeight.bdata[r][c]);
if (c < (cols - 1)) {
b.append(" ");
}
}
o.println(b);
}
}
o.close();
}
public void writeGrid(File f) throws IOException, ServiceException {
if (f.exists()) {
f.delete();
}
if (!f.createNewFile()) {
throw new ServiceException("Could not save grid file");
}
PrintStream o = new PrintStream(f);
o.println("ncols " + cols);
o.println("nrows " + rows);
o.println("xllcorner " + xllcorner);
o.println("yllcorner " + yllcorner);
o.println("cellsize " + cellsize);
o.println("NODATA_value " + nodata);
StringBuffer b = new StringBuffer();
if (type == GridType.INT_GRID) {
for (int r = 0; r < rows; r++) {
b.delete(0, b.length());
for (int c = 0; c < cols; c++) {
b.append(idata[r][c]);
if (c < (cols - 1)) {
b.append(" ");
}
}
o.println(b);
}
} else if (type == GridType.FLOAT_GRID) {
for (int r = 0; r < rows; r++) {
b.delete(0, b.length());
for (int c = 0; c < cols; c++) {
if (fdata[r][c] == nodata) {
b.append(nodata);
} else {
b.append(fdata[r][c]);
}
if (c < (cols - 1)) {
b.append(" ");
}
}
o.println(b);
}
} else {
for (int r = 0; r < rows; r++) {
b.delete(0, b.length());
for (int c = 0; c < cols; c++) {
b.append(bdata[r][c]);
if (c < (cols - 1)) {
b.append(" ");
}
}
o.println(b);
}
}
o.close();
}
public Set<Integer> intersect(Grid gr) throws ServiceException {
Set<Integer> subs = new HashSet<>();
int gdata[][] = gr.getIntData();
int gnodata = gr.getNoData();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (idata[i][j] != nodata) {
if (gdata[i][j] != gnodata) {
subs.add(gdata[i][j]);
}
}
}
}
return subs;
}
//
// A template grid that contains the id's that have to match the key passed to this
// function. When the key matches the template cell this grids data cell is
// updated with the val passed. Tpically used to fill in a subcatchment with a
// single value.
//
public void update(Grid template, int key, float val) throws ServiceException {
int data[][] = template.getIntData();
for (int i = 0; i < template.rowCount(); i++) {
for (int j = 0; j < template.colCount(); j++) {
if (data[i][j] == key) {
fdata[i][j] = val;
}
}
}
}
//
// A template grid that contains all ids in the correct positions. When one
// of the vals match the template grid the new value is set in this grid.
// This is a seletive mask that only copies a portion of the template grid.
//
public void maskSubareas(Grid template, int vals[], int newVal) throws ServiceException {
int data[][] = template.getIntData();
for (int i = 0; i < template.rowCount(); i++) {
for (int j = 0; j < template.colCount(); j++) {
for (int k = 0; k < vals.length; k++) {
if (data[i][j] == vals[k]) {
idata[i][j] = newVal;
break;
}
}
}
}
}
public void maskChannels(Grid sl, Grid sy, Grid r, int nod) throws ServiceException {
float sl_grid[][] = sl.getFloatData();
float sy_grid[][] = sy.getFloatData();
float r_grid[][] = r.getFloatData();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (idata[i][j] != nodata) {
sl_grid[i][j] = nod;
sy_grid[i][j] = nod;
r_grid[i][j] = nod;
}
}
}
}
public void updatePathWeightedLoss(float val[], int row[], int col[], float weight) {
for (int i = 0; i < val.length; i++) {
int x = row[i];
int y = col[i];
if (fdata[x][y] <= -999) {
fdata[x][y] = 0;
}
fdata[x][y] += (val[i] * weight);
}
}
public void updatePathWeight(int row[], int col[], float weight) {
for (int i = 0; i < row.length; i++) {
int x = row[i];
int y = col[i];
fdata[x][y] += weight;
}
}
public void updatePathMaxLoss(float val[], int row[], int col[]) {
for (int i = 0; i < val.length; i++) {
int x = row[i];
int y = col[i];
if (val[i] > fdata[x][y]) {
fdata[x][y] = val[i];
}
}
}
public double getCellsize() {
return cellsize;
}
public int cellCountWithMask(int key, Grid mask) throws ServiceException {
int data[][] = mask.getIntData();
boolean lookingForStart = true;
boolean sawVal;
int count = 0;
for (int i = 0; i < rows; i++) {
sawVal = false;
for (int j = 0; j < cols; j++) {
if (idata[i][j] == key) {
sawVal = true;
lookingForStart = false;
if (data[i][j] == 1) {
count++;
}
}
}
if ((lookingForStart == false) && (sawVal == false)) {
break;
}
}
return count;
}
public int majorValue(int key, Grid subGrid) throws ServiceException {
int data[][] = subGrid.getIntData();
boolean lookingForStart = true;
boolean sawVal = false;
int counts[] = new int[WeppConstants.MAX_IDS];
if (key < 0) {
return -999;
}
for (int i = 0; i < WeppConstants.MAX_IDS; i++) {
counts[i] = 0;
}
for (int i = 0; i < subGrid.rowCount(); i++) {
sawVal = false;
for (int j = 0; j < subGrid.colCount(); j++) {
if (data[i][j] == key) {
sawVal = true;
lookingForStart = false;
if (idata[i][j] < WeppConstants.MAX_IDS) {
if (idata[i][j] >= 0) {
counts[idata[i][j]]++;
} else {
// there is really no data here in the grid.
}
} else {
throw new ServiceException("Grid::majorValue contains more that MAX number of ID's");
}
}
}
if ((lookingForStart == false) && (sawVal == false)) {
break;
}
}
if (lookingForStart == true) {
// not found
return -999;
}
int max = 0;
int majorId = 0;
for (int i = 0; i < WeppConstants.MAX_IDS; i++) {
if (counts[i] > max) {
max = counts[i];
majorId = i;
}
}
return majorId;
}
public int cellCount(int key) throws ServiceException {
boolean lookingForStart = true;
boolean sawVal = false;
int count = 0;
for (int i = 0; i < rows; i++) {
sawVal = false;
for (int j = 0; j < cols; j++) {
if (idata[i][j] == key) {
count++;
}
}
if ((lookingForStart == false) && (sawVal == false)) {
break;
}
}
return count;
}
public boolean verifyFloat(double min, double max) {
boolean rc = true;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (fdata[i][j] != nodata) {
if ((fdata[i][j] < min) || (fdata[i][j] > max)) {
// outside range
return false;
}
}
}
}
return rc;
}
public void print(PrintStream o) throws IOException, ServiceException {
o.println("ncols " + cols);
o.println("nrows " + rows);
o.println("xllcorner " + xllcorner);
o.println("yllcorner " + yllcorner);
o.println("cellsize " + cellsize);
o.println("NODATA_value " + nodata);
if (type == GridType.INT_GRID) {
for (int r = 0; r < rows; r++) {
StringBuilder b = new StringBuilder();
for (int c = 0; c < cols; c++) {
b.append(idata[r][c]).append(" ");
}
o.println(b);
}
} else if (type == GridType.FLOAT_GRID) {
for (int r = 0; r < rows; r++) {
StringBuilder b = new StringBuilder();
for (int c = 0; c < cols; c++) {
b.append(fdata[r][c]).append(" ");
}
o.println(b);
}
} else {
for (int r = 0; r < rows; r++) {
StringBuilder b = new StringBuilder();
for (int c = 0; c < cols; c++) {
b.append(bdata[r][c]).append(" ");
}
o.println(b);
}
}
}
}