import java.io.*; class AddAatf { // Copyleft Harvey Greenberg, UW hgreen@u.washington.edu Oct 12, 1998 // July 11, 2000: inserted missing steps in arc/info comments // Nov 7, 2001: // For stream tips, set meanmsq = local - halfarea // October 21, 2008: make the cellsize an optional argument, defaulting to 150 // October 24, 2008: forks from AddAat2 by treating meanmsq and maxmsq // as doubles (long floats) // Calls class Aat.class // This is based on AddAat.java, but the methodology has been changed, // and it also calculates stream order, downstream arc, and principal // upstream arc. // AddAat assumes that you have a river network represented as one or more // topological trees, with all segments pointing downstream. The strahler // calculation may be inaccurate if more than two major downstream rivers // meet at a junction. There is a limit of 7 downstream arcs at a node. // The input/output file is an AAT (arc attribute table) associated with // an ARC/INFO "coverage"("vector" data set). There are a number of //requirements for this coverage: // All arcs point downstream. // There is always one (or zero) downstream arc // Nodes are correctly numbered. (Use "renode" to be safe.) // For "uparc" and "downarc" to be meaningful, arcs must have // uniques IDs (Try cover-id = cover#.) // There should be an item "local", which contains the local // contributing area in cells. // There should be an item "maxmsq", which will receive the contributing // area, in square meters, as measured at the downstream end. // There should be an item "meanmsq", which will receive the mean of the // upstream area and downstream area. // There should be an item "shreve", which will receive the stream order. // This is the count of upstream sources. // There should be an item "strahler", which will receive the stream order, // as calculated by Strahler's method. // There should be an item "segorder", which will receive the stream order, // as calculated by DHSVM's method. // There should be an item "downarc", which will receive the id (cover-id) // of the downstream arc. // There should be an item "uparc", which will receive the ID of the arc // upstream arc with the largest area. // All the above items should be numeric. Binary works well. // The following arc/info code will define those items. ///////////////////////// start of arc/info code ////////////////////////// // TABLES // &if ^ [iteminfo %mystreamcover% -ARC local -exists] &then; additem %mystreamcover%.aat local 4 8 b // &if ^ [iteminfo %mystreamcover% -ARC maxmsq -exists] &then; additem %mystreamcover%.aat maxmsq 8 13 f 0 // &if ^ [iteminfo %mystreamcover% -ARC meanmsq -exists] &then; additem %mystreamcover%.aat meanmsq 8 13 f 0 // &if ^ [iteminfo %mystreamcover% -ARC shreve -exists] &then; additem %mystreamcover%.aat shreve 4 4 b // &if ^ [iteminfo %mystreamcover% -ARC strahler -exists] &then; additem %mystreamcover%.aat strahler 4 4 b // &if ^ [iteminfo %mystreamcover% -ARC segorder -exists] &then; additem %mystreamcover%.aat segorder 4 4 b // &if ^ [iteminfo %mystreamcover% -ARC downarc -exists] &then; additem %mystreamcover%.aat downarc 4 8 b // &if ^ [iteminfo %mystreamcover% -ARC uparc -exists] &then; additem %mystreamcover%.aat uparc 4 8 b // QUIT // /* The item "local" can be filled as follows: // GRID // setwindow myflowdir /* This is a flowdirection grid of the watershed // setcell myflowdir // streamgrid = linegrid(%mystreamcover%) // local = watershed(myflowdir,streamgrid) // QUIT // TABLES // relate add // uff // local.vat // INFO // %mystreamcover%# // value // linear // ro // [unquote ''] // sel %mystreamcover%.aat // calc local = uff//count // calc %mystreamcover%-id = %mystreamcover%# // QUIT // copy %mystreamcover% %mystreamcover%bu // &sys java AddAatf %mystreamcover% // ///////////////////////// end of arc/info code ////////////////////////// // this class does not check types. // The area of a cell (used to convert from cell counts to contributing area) // is hardwired below. // Some of the error handling is crude. It will simply exit if it does not // find the items it wants. // The AAt class completely rewrites the AAT file. It has been tested for // safety, but it is not guaranteed to not corrupt the AAT file. // Remember, java defaults to a memory limit of 16 megs. Use the mx switch, // e.g. "java -mx200m AddAat2 mycover" for large data. // version 1.01: added segorder // version 1.02: different calculation of meanmsq // version 1.03: cell size as an argument, and set verbose false public static void main (String args[]) throws IOException { Aat myatt; int maxid,ilocal,imax,imean,ishreve,shreve=1,istrahler,isegorder,idown, iup,ndone=99,maxdone=0,it=0,nup,ii; double maxmax=0.,area,halfarea; // NOW doubles SET AS AN ARGUMENT Double ob_area; String covername; boolean verbose = false; if (args.length < 1){ System.out.println("The cover name is a required argument."); return; } else covername = args[0]; System.out.println("Cover: " + covername ); if (args.length < 2){ System.out.println("The cell size is defaulting to 150 meters (22500 square meters"); area=22500D; return; } else ob_area = new Double(args[1]); area = ob_area.doubleValue(); halfarea = area / 2; System.out.println("AddAat2, version 1.03 Tue Oct 21 17:25:40 PDT 2008, using a cellsize of " + area + " square meters."); if (verbose) System.out.println("Compiled in verbose mode"); try{ myatt = new Aat(covername); } catch (AatError e){ System.out.print("Error loading AAT file:"); System.out.println(e.getMessage()); return; } // myatt.report(); maxid = myatt.nrecords; ilocal = myatt.findItem("local"); // input (contib. area) imax = myatt.findItem("maxmsq"); // output (tot. contib at outlet) imean = myatt.findItem("meanmsq"); // output (maxmsq - half of local) ishreve = myatt.findItem("shreve"); //output (NEW) istrahler = myatt.findItem("strahler"); //output (NEW) isegorder = myatt.findItem("segorder"); //output (NEWER) idown = myatt.findItem("downarc"); //output (NEW) iup = myatt.findItem("uparc"); //output (NEW) if(ilocal < 0) return; if(imax < 0) return; if(imean < 0) return; if(ishreve < 0) return; if(istrahler < 0) return; if(isegorder < 0) return; if(idown < 0) return; if(iup < 0) return; int flags[] = new int[maxid]; int down[] = new int[maxid]; int upi[] = new int[8]; // first pass: id sources and record downarc for(int i = 0;i < maxid;i++){ myatt.dvalues[imax][i] = (double)myatt.ivalues[ilocal][i]; flags[i] = 1; // tentative myatt.ivalues[idown][i] = -1; down[i] = -1; for(int j = 0;j< maxid;j++){ if(myatt.fnode[i] == myatt.tnode[j]){ // found upstream arc flags[i] = 0; } if(myatt.fnode[j] == myatt.tnode[i]){ // found downstream arc myatt.ivalues[idown][i] = myatt.id[j]; down[i] = j; // use handy array within this program } } // search for connected arcs if(flags[i] == 1){ myatt.ivalues[ishreve][i] = 1; myatt.ivalues[istrahler][i] = 1; myatt.ivalues[isegorder][i] = 1; myatt.ivalues[iup][i] = -1; maxdone++; } else { myatt.ivalues[ishreve][i] = 0; } } // for each arc i System.out.println(maxdone + " source arcs"); System.out.println("Diagnostic intermediate writing to the AAT file."); myatt.writeAat(); // multiple passes until no more are found to be done. while(ndone > 0){ it++; System.out.println("iteration " + it); ndone = 0; for(int i = 0;i < maxid;i++){ // for each arc if(verbose) System.out.println("***Arc " + i + ",id=" + myatt.id[i] + ", flag = " + flags[i]); if(flags[i] == it){ // just done: look down for candidate if(verbose) System.out.println(i + ", flag=" +flags[i] + ",it=" + it); ii = down[i]; //index of downstream arc if(verbose) System.out.println(i + ", id=" + myatt.id[i] + ",ii=" + ii); if((ii >= 0) && (flags[ii] == 0)){ // not a mouth, and not done nup = 0; for(int j = 0;j< maxid;j++){ // looking for upstream arc if(myatt.fnode[ii] == myatt.tnode[j]){ // found upstream arc if(flags[j] > 0){ // upstream arc is ready nup++; upi[nup] = j; } else { nup = 0; break; } } // found upstream arc } // checking every upstream arc if (nup > 0) { // all upstream arcs are ready if(verbose) System.out.println(" Doing " + ii + ", id=" + myatt.id[ii] + ",nup =" + nup); for (int j=1;j <= nup;j++){ // for each upstream arc if(verbose) System.out.println(" j=" + j + ",index=" + upi[j] + ", upid=" + myatt.id[upi[j]]); myatt.ivalues[ishreve][ii] += myatt.ivalues[ishreve][upi[j]]; myatt.dvalues[imax][ii] += myatt.dvalues[imax][upi[j]]; if(j == 1){ myatt.ivalues[istrahler][ii] = myatt.ivalues[istrahler][upi[1]]; myatt.ivalues[isegorder][ii] = myatt.ivalues[isegorder][upi[1]] + 1; maxmax = myatt.id[upi[1]]; myatt.ivalues[iup][ii] = myatt.id[upi[1]]; } else { if(myatt.ivalues[istrahler][upi[j]] == myatt.ivalues[istrahler][ii]) myatt.ivalues[istrahler][ii]++; //not rigorous if 3 upstream else if(myatt.ivalues[istrahler][upi[j]] > myatt.ivalues[istrahler][ii]) myatt.ivalues[istrahler][ii] = myatt.ivalues[istrahler][upi[j]]; if(myatt.ivalues[isegorder][upi[j]] >= myatt.ivalues[isegorder][ii]) myatt.ivalues[isegorder][ii] = myatt.ivalues[isegorder][upi[j]] + 1; if(myatt.dvalues[imax][upi[j]] > maxmax){ maxmax = myatt.dvalues[imax][upi[j]]; myatt.ivalues[iup][ii] = myatt.id[upi[j]]; } } } // for each upstream arc flags[ii] = it + 1; ndone++; maxdone++; } // all upstream arcs are ready } // not a mouth } //just done: look down for candidate } // each arc System.out.println(ndone + " more arcs, " + maxdone + " total. "); } // while // None completed this round. Should be done. if(maxdone != maxid) System.out.println("-------------------Hey, " + maxdone + " of " + maxid + " done!"); for(int i = 0;i < maxid;i++){ myatt.dvalues[imax][i] *= area; // cells to square meters // 11/7/2001: different mean for stream tips if(myatt.ivalues[iup][i] < 0) myatt.dvalues[imean][i] = myatt.dvalues[imax][i] - halfarea; else myatt.dvalues[imean][i] = myatt.dvalues[imax][i] - (myatt.ivalues[ilocal][i] * halfarea); } System.out.println("Writing to the AAT file."); myatt.writeAat(); } }