Grid1.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.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.Scanner;
import java.util.Set;
import java.util.HashSet;
import static util.Grid1.Type.*;
/**
* Handles ArcGIS ASCII grids.
*
* @author jrf
*/
public class Grid1 {
public enum Type {
BYTE_GRID, INT_GRID, FLOAT_GRID
};
int rows;
int cols;
int nodata;
double cellsize;
double xllcorner;
double yllcorner;
Type type;
double[][] ddata;
int[][] idata;
byte[][] bdata;
// reads an existing grid
public Grid1(Type 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;
if (ty == null)
throw new IllegalArgumentException("Missing GridType ");
try (BufferedReader input = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = input.readLine()) != null) {
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("Grid1 header unrecognized : " + filename);
}
if ((rows > 0) && (cols > 0) && (xllcorner != -9999) && (yllcorner != -9999) && (cellsize > 0) && (hasnodata)) {
processHeader = false;
curRow = 0;
if (ty == INT_GRID)
idata = new int[rows][cols];
if (ty == FLOAT_GRID)
ddata = new double[rows][cols];
if (ty == BYTE_GRID)
bdata = new byte[rows][cols];
}
} else {
line = line.trim();
String[] inData = line.split("\\s+");
switch (ty) {
case INT_GRID:
for (int c = 0; c < cols; c++) {
idata[curRow][c] = Integer.parseInt(inData[c]);
}
break;
case FLOAT_GRID:
for (int c = 0; c < cols; c++) {
ddata[curRow][c] = Double.parseDouble(inData[c]);
}
break;
default:
for (int c = 0; c < cols; c++) {
bdata[curRow][c] = Byte.parseByte(inData[c]);
}
break;
}
curRow++;
}
}
}
}
// clones an existing grid
public Grid1(Grid1 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 == null)
throw new IllegalArgumentException("Missing GridType ");
switch (type) {
case INT_GRID:
idata = new int[rows][cols];
break;
case FLOAT_GRID:
ddata = new double[rows][cols];
break;
default:
bdata = new byte[rows][cols];
break;
}
}
// clones an existing grid
public Grid1(Grid1 par, Type 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 == null)
throw new IllegalArgumentException("Missing GridType ");
switch (ty) {
case 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;
}
}
break;
case FLOAT_GRID:
ddata = new double[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
ddata[i][j] = nod;
}
}
break;
default:
bdata = new byte[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
bdata[i][j] = (byte) nod;
}
}
break;
}
}
// creates a new, empty grid, initialized to zero
public Grid1(Type 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 == null)
throw new IllegalArgumentException("Missing GridType ");
switch (ty) {
case INT_GRID:
idata = new int[rows][cols];
break;
case FLOAT_GRID:
ddata = new double[rows][cols];
break;
default:
bdata = new byte[rows][cols];
break;
}
}
public void clear() {
if (rows == 0)
return;
if (type == INT_GRID) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
idata[i][j] = nodata;
}
}
} else if (type == FLOAT_GRID) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
ddata[i][j] = nodata;
}
}
}
}
public int[][] getIntData() throws ServiceException {
if (rows == 0)
return null;
if (type == INT_GRID) {
return idata;
} else {
throw new ServiceException("Grid1 type mismatch, int");
}
}
public double[][] getFloatData() throws ServiceException {
if (rows == 0)
return null;
if (type == FLOAT_GRID) {
return ddata;
} else {
throw new ServiceException("Grid1 type mismatch, double");
}
}
public byte[][] getByteData() throws ServiceException {
if (rows == 0)
return null;
if (type == BYTE_GRID) {
return bdata;
} else {
throw new ServiceException("Grid1 type mismatch, byte");
}
}
public int rowCount() {
return rows;
}
public int colCount() {
return cols;
}
public int getNoData() {
return nodata;
}
public double getFloatRowCol(int r, int c) {
if (ddata != null) {
if ((r < rows) && (c < cols))
return ddata[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 writeWeightedGrid1(Grid1 sedWeight, File f) throws IOException, ServiceException {
if (f.exists())
f.delete();
if (!f.createNewFile())
throw new ServiceException("Could not save grid file");
try (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);
if (type == 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]) / sedWeight.idata[r][c]);
if (c < (cols - 1))
b.append(" ");
}
o.println(b);
}
} else if (type == FLOAT_GRID) {
for (int r = 0; r < rows; r++) {
StringBuilder b = new StringBuilder();
for (int c = 0; c < cols; c++) {
if (ddata[r][c] == nodata) {
b.append(nodata);
} else {
b.append((ddata[r][c]) / sedWeight.ddata[r][c]);
}
if (c < (cols - 1))
b.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]) / sedWeight.bdata[r][c]);
if (c < (cols - 1))
b.append(" ");
}
o.println(b);
}
}
}
}
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 == 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 == FLOAT_GRID) {
for (int r = 0; r < rows; r++) {
StringBuilder b = new StringBuilder();
for (int c = 0; c < cols; c++) {
b.append(ddata[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);
}
}
}
public void writeGrid1(File f) throws IOException, ServiceException {
if (f.exists())
f.delete();
if (!f.createNewFile())
throw new ServiceException("Could not save grid file");
try (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);
if (type == 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 == FLOAT_GRID) {
for (int r = 0; r < rows; r++) {
StringBuilder b = new StringBuilder();
for (int c = 0; c < cols; c++) {
if (ddata[r][c] == nodata) {
b.append(nodata);
} else {
b.append(ddata[r][c]);
}
if (c < (cols - 1))
b.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);
}
}
}
}
public Set<Integer> intersect(Grid1 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(Grid1 template, int key, double 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)
ddata[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(Grid1 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(Grid1 sl, Grid1 sy, Grid1 r, int nod) throws ServiceException {
double sl_grid[][] = sl.getFloatData();
double sy_grid[][] = sy.getFloatData();
double 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(double val[], int row[], int col[], double weight) {
for (int i = 0; i < val.length; i++) {
int x = row[i];
int y = col[i];
if (ddata[x][y] <= -999)
ddata[x][y] = 0;
ddata[x][y] += (val[i] * weight);
}
}
public void updatePathWeight(int row[], int col[], double weight) {
for (int i = 0; i < row.length; i++) {
int x = row[i];
int y = col[i];
ddata[x][y] += weight;
}
}
public void updatePathMaxLoss(double val[], int row[], int col[]) {
for (int i = 0; i < val.length; i++) {
int x = row[i];
int y = col[i];
if (val[i] > ddata[x][y])
ddata[x][y] = val[i];
}
}
public double getCellsize() {
return cellsize;
}
public int cellCountWithMask(int key, Grid1 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, Grid1 subGrid1) throws ServiceException {
int data[][] = subGrid1.getIntData();
boolean lookingForStart = true;
boolean sawVal;
int counts[] = new int[WeppConstants.MAX_IDS];
for (int i = 0; i < WeppConstants.MAX_IDS; i++) {
counts[i] = 0;
}
for (int i = 0; i < subGrid1.rowCount(); i++) {
sawVal = false;
for (int j = 0; j < subGrid1.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("Grid1:majorValue contains more that MAX number of ID's");
}
}
}
if ((lookingForStart == false) && (sawVal == false))
break;
}
// not found
if (lookingForStart)
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 boolean verifyFloat(double min, double max) {
boolean rc = true;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (ddata[i][j] != nodata) {
if ((ddata[i][j] < min) || (ddata[i][j] > max)) {
// outside range
return false;
}
}
}
}
return rc;
}
public long cellCount(int key) throws ServiceException {
return Arrays
.stream(idata)
.flatMapToInt(r -> Arrays.stream(r))
.filter(v -> v == key)
.summaryStatistics().getCount();
}
DoubleSummaryStatistics getStats() {
return Arrays
.stream(ddata)
.flatMapToDouble(r -> Arrays.stream(r))
.filter(v -> v != nodata)
.summaryStatistics();
}
public static void main(String[] args) throws Exception {
String f = "/od/projects/WEPPWS-Python/WS/flowpathloss.asc";
Grid1 g = new Grid1(FLOAT_GRID, f);
g.print(System.out);
System.out.println(g.getStats());
}
}