GeolUnitArea.sml

  Download

More scripts: Advanced

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
### GeolUnitArea.sml
## 26 January 2006
## R. Smith
## MicroImages, Inc.
## standalone script to process sample points and basins
#$ created by the SampleCatchments script.
## Input: Results vector object containing relocated sample points and
## USDbasins vector containing basins (catchments) associated with 
## sample points.
## Output: copy of the USDbasins vector with added GeolUnitArea table 
## in the polygon database with records attached to polygon elements.
## Fields in this table record summed areas and percentages of each
## rock unit for each basin (catchment area).
## Assumption 1:  Polygons have attached PERCENTAGE table created by 
## the Polygon Properties process.  Multiple records in this table are 
## attached to each basin polygon, one for each geologic map
## unit polygon that overlaps the basin polygon.  Each such record 
## includes the area (in square meters) of the current basin polygon that
## is covered by that rock unit polygon.  More than one rock unit polygon 
## of the same type can overlap a given basin polygon.
## Assumption 2: Basins can be composite, consisting
## of more than one polygon element.
## Assumption 3: The sample for a particular basin represents it and
## all upstream basins in the same watershed.  The PointToPoint table
## records the number of upstream samples for each sample, and the
## IDs of those that are immediately adjacent to that sample's basin.
## Compiling a list of all upstream basins requires a recursive
## procedure to exhaustively trace these upstream-adjacent relationships.
## Assumption 4: Geologic map units in the area are indicated by symbols 
## Cu, Du, Mu, Ou, Qal, Tg, Ts, Tv, pCgr, and pCgs in the PERCENTAGE table. 
## Global variables
class VECTOR SampleVect, BasinVectIn, BasinVectOut;
class STRINGLIST idList;
class DATABASE polyDB;
class DBTABLEINFO ptTable, basinInfoTbl, unitAreaTbl, percentTbl;
class DBFIELDINFO sampID, sampIDunit, totArea, checkArea; 
class DBFIELDINFO cuAreaFld, cuPctFld, duAreaFld, duPctFld, muAreaFld, muPctFld, ouAreaFld;
class DBFIELDINFO ouPctFld, qalAreaFld, qalPctFld, tgAreaFld, tgPctFld, tsAreaFld, tsPctFld;
class DBFIELDINFO pCgrAreaFld, pCgrPctFld, pCgsAreaFld, pCgsPctFld, tvAreaFld, tvPctFld;
class DBFIELDINFO totUnitPctFld;
numeric i;
##########################################################################
## define recursive function to get upstream sample IDs from given sample
proc getUpstreamIDs ( string sampleID$ ) 
	{
	local numeric j;
	local string fieldbase$ = "UpSample";		# base string for numbered UpSample fields
	# add current sample ID to global ID List;
	idList.AddToEnd(sampleID$);
	# get record number in PointToPoint table for current sample ID
	local numeric recNum = TableKeyFieldLookup(ptTable, "REC_NO", sampleID$);
	# get number of upstream samples immediately adjacent to the current basin
	local numeric numAdjUp = TableReadFieldNum(ptTable, "NumUpSamples", recNum);
	if ( numAdjUp > 0 )	# if there are adjacent upstream polygons
		{
		# get list of sample IDs for adjacent upstream samples from UpSample[num] fields 
		# in the PolyToPoly table
		local class STRINGLIST tempList;
		for j = 1 to numAdjUp
			{
			# create string for field name holding the appropriate UpSample basin ID
			# and add to local stringlist
			local string field$ = fieldbase$ + NumToStr(j);
			tempList.AddToEnd( TableReadFieldStr(ptTable, field$, recNum) );
			}
		# loop through local list of UpSample fields to get their adjacent upstream basin IDs
		# and call procedure to check for basins further upstream
		for j = 1 to numAdjUp
			{
			getUpstreamIDs( tempList[j-1] );
			}
		}
	}
############################################################
################### Main process ###########################
############################################################
clear();		# clear Console window
###############################################################
## Get input vector and handles for existing tables needed for processing
GetInputVector(SampleVect);
GetInputVector(BasinVectIn);
GetOutputVector(BasinVectOut);
VectorCopyElements(BasinVectIn, BasinVectOut);
CloseVector(BasinVectIn);
# get handles for existing point and polygon tables needed for processing
ptTable = TableGetInfo(SampleVect.point.PointToPoint);
basinInfoTbl = TableGetInfo(BasinVectOut.poly.PolyToPoly);
sampID = FieldGetInfoByName(basinInfoTbl, "REC_NO");		# get DBFIELDINFO for REC_NO field
totArea = FieldGetInfoByName(basinInfoTbl, "TotalArea_sq_km");
percentTbl = TableGetInfo(BasinVectOut.poly.PERCENTAGE);
#########################################################
## create new polygon table
polyDB = OpenVectorPolyDatabase(BasinVectOut);
unitAreaTbl = TableCreate(polyDB, "UnitArea", "Geologic unit areas per basin"); 
unitAreaTbl.RelatedOnly = 1;
# create REC_NO field in GraniteArea table and make it foreign
# key field pointing to same field in PolyToPoly table
sampIDunit = TableAddFieldString(unitAreaTbl, "REC_NO", 12); 
sampIDunit.IsPrimaryKey = 0;
sampIDunit.IsKey = 1;
sampIDunit.Key = sampID;
# add TotalArea_sq_km field in new table using DBFIELDINFO from same field in PolyToPoly
TableAddField(unitAreaTbl, totArea);
# add CheckArea field to verify if search of upstream IDs succeeded
checkArea = TableAddFieldFloat(unitAreaTbl, "CheckArea", 10, 4);
checkArea.UnitType = "Area";
checkArea.Units = "square kilometers";
# add fields for area and % for each rock unit
cuAreaFld = TableAddFieldFloat(unitAreaTbl, "Cu_Area", 10, 4); 
cuPctFld = TableAddFieldFloat(unitAreaTbl, "Cu_Pct", 10, 2);
duAreaFld = TableAddFieldFloat(unitAreaTbl, "Du_Area", 10, 4); 
duPctFld = TableAddFieldFloat(unitAreaTbl, "Du_Pct", 10, 2);
muAreaFld = TableAddFieldFloat(unitAreaTbl, "Mu_Area", 10, 4); 
muPctFld = TableAddFieldFloat(unitAreaTbl, "Mu_Pct", 10, 2);
ouAreaFld = TableAddFieldFloat(unitAreaTbl, "Ou_Area", 10, 4); 
ouPctFld = TableAddFieldFloat(unitAreaTbl, "Ou_Pct", 10, 2);
qalAreaFld = TableAddFieldFloat(unitAreaTbl, "Tg_Area", 10, 4); 
qalPctFld = TableAddFieldFloat(unitAreaTbl, "Tg_Pct", 10, 2);
tgAreaFld = TableAddFieldFloat(unitAreaTbl, "Tg_Area", 10, 4); 
tgPctFld = TableAddFieldFloat(unitAreaTbl, "Tg_Pct", 10, 2);
tsAreaFld = TableAddFieldFloat(unitAreaTbl, "Ts_Area", 10, 4); 
tsPctFld = TableAddFieldFloat(unitAreaTbl, "Ts_Pct", 10, 2);
tvAreaFld = TableAddFieldFloat(unitAreaTbl, "Tv_Area", 10, 4); 
tvPctFld = TableAddFieldFloat(unitAreaTbl, "Tv_Pct", 10, 2);
pCgrAreaFld = TableAddFieldFloat(unitAreaTbl, "pCgr_Area", 10, 4); 
pCgrPctFld = TableAddFieldFloat(unitAreaTbl, "pCgr_Pct", 10, 2);
pCgsAreaFld = TableAddFieldFloat(unitAreaTbl, "pCgs_Area", 10, 4); 
pCgsPctFld = TableAddFieldFloat(unitAreaTbl, "pCgs_Pct", 10, 2);
totUnitPctFld = TableAddFieldFloat(unitAreaTbl, "Total_Unit_Pct", 15, 2);
###################################################################
## loop through records in PolyToPoly table, and make corresponding
## records in new GraniteArea table
for i = 1 to basinInfoTbl.NumRecords
	{
	local array numeric elemList[1];		# array holding list of elements attached to current record
	local numeric numElements;				# number of elements attached to current record
	local array numeric recNumbers[1];	# array of record numbers (1) to attach
	local numeric j;							# counter for element loop
	local string sampID$ = BasinVectOut.poly.PolyToPoly[@i].REC_NO$;
	local numeric totalAreaKm = BasinVectOut.poly.PolyToPoly[@i].TotalArea_sq_km;
	# Add new record to GraniteArea table with values for first two fields
	# from those in current record in PolyToPoly table
	TableNewRecord(unitAreaTbl, sampID$, totalAreaKm);
	}
## loop through records in UnitArea table and sum total contributing
## area for each basin (as check) and areas of each geologic unit in 
## contributing area, then compute percentage for each unit
for i = 1 to unitAreaTbl.NumRecords
	{
	local numeric j, k, m, n;
	local string sampID$ = BasinVectOut.poly.UnitArea[@i].REC_NO$;
	local numeric recNum;	# record number in PolyToPoly table
	local numeric sumBasinArea;	# running sum of polygon areas for basin
	# numeric variables for summed area and percent of each rock unit in map area 
	local numeric cuArea, duArea, muArea, ouArea, qalArea, tgArea, tsArea, tvArea, pCgrArea, pCgsArea;
	local numeric cuPct, duPct, muPct, ouPct, qalPct, tgPct, tsPct, tvPct, pCgrPct, pCgsPct;
	local numeric totUnitPct;
	# array to hold element numbers of polygons PolyToPoly record is attached to
	local array numeric polyList[1];
	local numeric numAttachedPolys;		# number of polygons attached
	# array to hold record numbers of PERCENTAGE table records attached to each polygon
	local array numeric pctRecordList[1]; 
	local numeric numPctRecords;
	# call recursive function to get list of all upstream sample/basin IDs
	getUpstreamIDs( sampID$ );
	# loop through list of contributing basins to sum geologic unit areas
	for j = 1 to idList.GetNumItems()
		{
		# get record number for basin's record in the PolyToPoly table
		recNum = TableKeyFieldLookup(basinInfoTbl, "REC_NO", idList[j-1]);
		# get list of polygon elements attached to that record
		numAttachedPolys = TableGetRecordElementList(basinInfoTbl, recNum, polyList);
		for k = 1 to numAttachedPolys		# loop through polygons
			{
			sumBasinArea += BasinVectOut.poly[ polyList[k] ].POLYSTATS.Area;
			# get list of record numbers of PERCENTAGE table records attached to polygon
			numPctRecords = TableReadAttachment(percentTbl, polyList[k], pctRecordList);
			for m = 1 to numPctRecords		# loop through attached records to compute sums
				{
				n = pctRecordList[m];
				if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Cu") then
					cuArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Du") then
					duArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Mu") then
					muArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Ou") then
					ouArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Qal") then
					qalArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Tg") then
					tgArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Ts") then
					tsArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "Tv") then
					tvArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "pCgr") then
					pCgrArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				else if ( BasinVectOut.poly.PERCENTAGE[@n].FORMATION$ == "pCgs") then
					pCgsArea += BasinVectOut.poly.PERCENTAGE[@n].Area;
				}
			}
		}
	# use summed basin area and summed unit area to calculate percentage
	cuPct = 100 * cuArea / sumBasinArea;
	duPct = 100 * duArea / sumBasinArea;
	muPct = 100 * muArea / sumBasinArea;
	ouPct = 100 * ouArea / sumBasinArea;
	qalPct = 100 * qalArea / sumBasinArea;
	tgPct = 100 * tgArea / sumBasinArea;
	tsPct = 100 * tsArea / sumBasinArea;
	tvPct = 100 * tvArea / sumBasinArea;
	pCgrPct = 100 * pCgrArea / sumBasinArea;
	pCgsPct = 100 * pCgsArea / sumBasinArea;
	# sum unit percentages for each basin as check
	totUnitPct = round( (cuPct + duPct + muPct + ouPct + qalPct + tgPct + tsPct + tvPct + pCgrPct + pCgsPct ) );
	# convert summed areas from square meters to square km
	sumBasinArea = sumBasinArea / 1000000;
	cuArea = cuArea / 1000000;
	duArea = duArea / 1000000;
	muArea = muArea / 1000000;
	ouArea = ouArea / 1000000;
	qalArea = qalArea / 1000000;
	tgArea = tgArea / 1000000;
	tsArea = tsArea / 1000000;
	tvArea = tvArea / 1000000;
	pCgrArea = pCgrArea / 1000000;
	pCgsArea = pCgsArea / 1000000;
	# write computed results to appropriate fields in UnitArea table
	TableWriteField(unitAreaTbl, i, "CheckArea", sumBasinArea);
	TableWriteField(unitAreaTbl, i, "Cu_Area", cuArea);
	TableWriteField(unitAreaTbl, i, "Cu_Pct", cuPct);
	TableWriteField(unitAreaTbl, i, "Du_Area", duArea);
	TableWriteField(unitAreaTbl, i, "Du_Pct", duPct);
	TableWriteField(unitAreaTbl, i, "Mu_Area", muArea);
	TableWriteField(unitAreaTbl, i, "Mu_Pct", muPct);
	TableWriteField(unitAreaTbl, i, "Ou_Area", ouArea);
	TableWriteField(unitAreaTbl, i, "Ou_Pct", ouPct);
	TableWriteField(unitAreaTbl, i, "Qal_Area", qalArea);
	TableWriteField(unitAreaTbl, i, "Qal_Pct", qalPct);
	TableWriteField(unitAreaTbl, i, "Tg_Area", tgArea);
	TableWriteField(unitAreaTbl, i, "Tg_Pct", tgPct);
	TableWriteField(unitAreaTbl, i, "Ts_Area", tsArea);
	TableWriteField(unitAreaTbl, i, "Ts_Pct", tsPct);
	TableWriteField(unitAreaTbl, i, "Tv_Area", tvArea);
	TableWriteField(unitAreaTbl, i, "Tv_Pct", tvPct);
	TableWriteField(unitAreaTbl, i, "pCgr_Area", pCgrArea);
	TableWriteField(unitAreaTbl, i, "pCgr_Pct", pCgrPct);
	TableWriteField(unitAreaTbl, i, "pCgs_Area", pCgsArea);
	TableWriteField(unitAreaTbl, i, "pCgs_Pct", pCgsPct);
	TableWriteField(unitAreaTbl, i, "Total_Unit_Pct", totUnitPct);
	# clear all sum variables for next pass
	sumBasinArea = 0;
	cuArea = 0;		duArea = 0;		muArea = 0;		ouArea = 0;		qalArea = 0;
	tgArea = 0;		tsArea = 0;		tvArea = 0;		pCgrArea = 0;	pCgsArea = 0;	totUnitPct = 0;
	# clear global stringlist of contributing basin IDs
	idList.Clear();
	}