""" Ascending or Descending: Calculates accumulative Wts for accumulative row areas and num points for ascending or descending classes both with ascending counts. Categorical: Calculates Wts for each row, then reports those Wts for rows having >= Confidence. For rows having < Confidence, Wts are produced from sum of row areas and num points of classes < Confidence. Required Input(0): Integer raster dataset Optional Input(1): Attribute field name Required Input(2): Points feature class Required Input - Output type(3): Ascending, Descending, Categorical, Unique Required Output (4): Weights table Required Input(5): Confident_Contrast Required Input(6): Unitarea Required Input(7): MissingDataValue Derived Output(8) - Success of calculation, whether Valid table: True or False """ # Import system modules import sys, os, traceback import math import SDMValues # Create the Geoprocessor object import arcgisscripting gp = arcgisscripting.create() # Check out any necessary licenses gp.CheckOutExtension("spatial") class ErrorExit(Exception): pass def MakeWts(patternNTP, patternArea, unit, totalNTP, totalArea, Type): """ >>> Graeme's Fortran algorithm - Appendix II <<< class(s=totalArea, b=patternArea,unit=unit,db=patternNTP,ds=totalNTP) print *, ‘ area of study region ?‘ read *, s print *, ‘area of binary map pattern?’ read *, b print , ‘ area of unit cell?’ read *, unit print *, ‘no of deposits on pattern?’ read *, db print , ‘ total no of deposits?’ read *, ds """ db = patternNTP ds = totalNTP s = totalArea/unit b = patternArea/unit ##gp.addwarning("%s"%[db,ds,s,b]) try: #>>>>>>>>>>>> Traps #Traps and fixes for various acceptable data anomalies if db > ds: #Graeme's trap gp.addwarning( 'Input error: More than one TP per Unitcell in study area.') return tuple([0.0]*7) if Type == 'Categorical': # Categorical generalization if db == 0: #db = 0.01 return tuple([0.0]*7) elif db == ds: db -= 0.01 # Won't work when s-b < ds-db #return tuple([0.0]*7) else: # Ascending and Descending generalization if db ==0: #no accumulation #db = 0.01 return tuple([0.0]*7) elif db == ds: #Maximum accumulation #return tuple([0.0]*7) db -= 0.01 # Won't work when s-b < ds-db # Fix b so can compute W- when db = MaxTPs if (s - b) <= (ds - db): b = s + db - ds - 0.01 # Warning if cannot compute W+ if (b-db) <= 0.0: gp.addwarning( 'More than one TP per Unitcell in pattern.') return tuple([0.0]*7) #<<<<<<<<<<<<<<<<< 0: gp.AddField_management(wtstable,"CODE","text","5","#","#","Symbol") gp.AddField_management (wtstable, "AREA_SQ_KM", "double") gp.AddField_management (wtstable, "AREA_UNITS", "double") gp.AddField_management (wtstable, "NO_POINTS", "long") gp.AddField_management(wtstable,"WPLUS","double","10","4","#","W+") gp.AddField_management(wtstable,"S_WPLUS","double","10","4","#","W+ Std") gp.AddField_management(wtstable,"WMINUS","double","10","4","#","W-") gp.AddField_management(wtstable,"S_WMINUS","double","10","4","#","W- Std") gp.AddField_management(wtstable,"CONTRAST","double","10","4","#","Contrast") gp.AddField_management(wtstable,"S_CONTRAST","double","10","4","#","Contrast Std") gp.AddField_management(wtstable,"STUD_CNT","double","10","4","#","Studentized Contrast") gp.AddField_management(wtstable,"GEN_CLASS","long","#","#","#","Generalized Class") gp.AddField_management(wtstable,"WEIGHT","double","10","6","#","Generalized Weight") gp.AddField_management(wtstable,"W_STD","double","10","6","#","Generalized Weight Std") OIDName = gp.Describe(wtstable).OIDFieldName #Fill output table rows depending on Type desc = gp.describe(EvidenceLayer) cellsize = desc.MeanCellWidth if desc.datatype == 'RasterLayer': EvidenceLayer =desc.catalogpath if Type == "Descending": wtsrows = gp.InsertCursor(wtstable) rows = gp.SearchCursor(EvidenceLayer,'','','Value','Value D') row = rows.Next() while row: #gp.AddMessage("Inserting row.") wtsrow = wtsrows.NewRow() wtsrow.rastervalu = row.Value wtsrow.SetValue('class',row.Value) if len(CodeName) > 0: wtsrow.Code = row.GetValue(CodeName) wtsrow.Count = row.Count statsrows = gp.SearchCursor(Statistics,'rastervalu = %i'%row.Value) if statsrows: statsrow = statsrows.Next() if statsrow: rowFreq = statsrow.Frequency else: rowFreq = 0 wtsrow.Frequency = rowFreq #gp.addmessage('Desc: Class: %d, Count: %d, Freq: %d'%(row.Value,row.Count, rowFreq)) wtsrows.InsertRow(wtsrow) row = rows.next() del wtsrows, wtsrow else: # Ascending or Categorical or Unique wtsrows = gp.InsertCursor(wtstable) rows = gp.SearchCursor(EvidenceLayer) row = rows.Next() while row: wtsrow = wtsrows.NewRow() wtsrow.rastervalu = row.Value wtsrow.SetValue('class',row.Value) if len(CodeName) > 0: wtsrow.Code = row.GetValue(CodeName) wtsrow.Count = row.Count statsrows = gp.SearchCursor(Statistics,'rastervalu = %i'%row.Value) if statsrows: statsrow = statsrows.Next() if statsrow: wtsrow.Frequency = statsrow.Frequency else: wtsrow.Frequency = 0 wtsrows.InsertRow(wtsrow) row = rows.Next() del wtsrows, wtsrow del row,rows # Calculate fields #gp.AddMessage('Calculating weights...') #gp.AddMessage("[count] * %f * %f /1000000.0"%(cellsize,cellsize)) gp.CalculateField_management (wtstable, "area", "[count] * %f / 1000000.0"%(cellsize**2)) gp.CalculateField_management (wtstable, "areaunits", "[area] / %f"% Unitarea) # Calculate accumulative fields if Type in ("Ascending", "Descending"): wtsrows = gp.UpdateCursor(wtstable) wtsrows.reset() wtsrow = wtsrows.Next() if wtsrow: if wtsrow.GetValue('class') <> MissingDataValue: lastTotalTP = wtsrow.Frequency lastTotalArea = wtsrow.Area # sq km lastTotalAreaUnits = wtsrow.AreaUnits # unit cells wtsrow.NO_POINTS = lastTotalTP wtsrow.AREA_SQ_KM = lastTotalArea # sq km wtsrow.AREA_UNITS = lastTotalAreaUnits # unit cells else: lastTotalTP = 0 lastTotalArea = 0 lastTotalAreaUnits = 0 wtsrow.NO_POINTS = wtsrow.Frequency wtsrow.AREA_SQ_KM = wtsrow.Area # sq km wtsrow.AREA_UNITS = wtsrow.AreaUnits # unit cells #gp.addmessage('%s: Freq: %d, Area: %f, UnitAreas: %f'%(Type, wtsrow.Frequency,wtsrow.Area, wtsrow.AreaUnits)) wtsrows.UpdateRow(wtsrow) wtsrow = wtsrows.Next() while wtsrow: if wtsrow.GetValue('class') <> MissingDataValue: lastTotalTP += wtsrow.Frequency lastTotalArea += wtsrow.Area lastTotalAreaUnits += wtsrow.AreaUnits wtsrow.NO_POINTS = lastTotalTP wtsrow.AREA_SQ_KM = lastTotalArea # sq km wtsrow.AREA_UNITS = lastTotalAreaUnits # unit cells else: wtsrow.NO_POINTS = wtsrow.Frequency wtsrow.AREA_SQ_KM = wtsrow.Area #sq km wtsrow.AREA_UNITS = wtsrow.AreaUnits # unit cells #gp.addmessage('%s: Freq: %d, Area: %f, UnitAreas: %f'%(Type,wtsrow.Frequency,wtsrow.Area, wtsrow.AreaUnits)) wtsrows.UpdateRow(wtsrow) wtsrow = wtsrows.Next() totalArea = lastTotalArea # sq km totalTPs = lastTotalTP del wtsrow,wtsrows #Calculate non-accumulative fields elif Type in ("Categorical", "Unique"): totalArea = 0 totalTPs = 0 wtsrows = gp.UpdateCursor(wtstable) wtsrow = wtsrows.Next() while wtsrow: wtsrow.NO_POINTS = wtsrow.Frequency wtsrow.AREA_SQ_KM = wtsrow.Area # sq km wtsrow.AREA_UNITS = wtsrow.AreaUnits # unit cells if wtsrow.GetValue('class') <> MissingDataValue: totalTPs += wtsrow.Frequency totalArea += wtsrow.Area wtsrows.UpdateRow(wtsrow) wtsrow = wtsrows.Next() del wtsrow,wtsrows else: gp.AddWarning('Type %s not implemented'%Type) #Calculate weights, etc from filled-in fields wtsrows = gp.UpdateCursor(wtstable) wtsrow = wtsrows.Next() while wtsrow: #gp.AddMessage('Got to here...%i'%wtsrow.Class) #No calculations for missingdata class if wtsrow.GetValue('class') == MissingDataValue: wtsrow.wplus = 0.0 wtsrow.s_wplus = 0.0 wtsrow.wminus = 0.0 wtsrow.s_wminus = 0.0 wtsrow.contrast = 0.0 wtsrow.s_contrast = 0.0 wtsrow.stud_cnt = 0.0 else: wts = MakeWts(wtsrow.NO_POINTS, wtsrow.AREA_SQ_KM, Unitarea, totalTPs, totalArea, Type) if not wts: gp.AddError("Weights calculation aborted.") raise ErrorExit (wp,sp,wm,sm,c,sc,c_sc) = wts #gp.AddMessage(str((wp,sp,wm,sm,c,sc,c_sc))) wtsrow.wplus = wp wtsrow.s_wplus = sp wtsrow.wminus = wm wtsrow.s_wminus = sm wtsrow.contrast = c wtsrow.s_contrast = sc wtsrow.stud_cnt = c_sc wtsrows.UpdateRow(wtsrow) wtsrow = wtsrows.Next() del wtsrow,wtsrows #Generalize table #Get Study Area size in Evidence counts evRows = gp.SearchCursor(EvidenceLayer) evRow = evRows.Next() studyArea = 0 while evRow: studyArea = studyArea + evRow.Count evRow = evRows.Next() del evRow, evRows #gp.AddMessage("studyArea size(cells)=" + str(studyArea)) #Get total number of training points ds = gp.GetCount_management(tempTrainingPoints) #TP selected #gp.AddMessage("ds="+str(ds)) Success = 1 #Assume Valid Table: Has confident classes if Type in ("Ascending", "Descending", "Categorical"): #gp.AddMessage("Generalizing " + Type + "...") if Type != "Categorical": #i.e., Ascending or Descending #Select confident rows WgtsTblRows = gp.SearchCursor(wtstable,"STUD_CNT >= " + str(Confident_Contrast)) #Get confidence row OID with maximum contrast WgtsTblRow = WgtsTblRows.Next() maxContrast = -9999999.0 patNoTPs = 0; patArea = 0.0 maxOID = -1 while WgtsTblRow: if WgtsTblRow.Class <> MissingDataValue: if (WgtsTblRow.Contrast > maxContrast) and (WgtsTblRow.STUD_CNT >= Confident_Contrast): maxContrast = WgtsTblRow.Contrast maxOID = WgtsTblRow.GetValue(OIDName) maxWplus = WgtsTblRow.Wplus maxWplus_Std = WgtsTblRow.S_Wplus maxWminus = WgtsTblRow.Wminus maxWminus_Std = WgtsTblRow.S_Wminus maxStdContr = WgtsTblRow.STUD_CNT patNoTPs += WgtsTblRow.No_points patArea += WgtsTblRow.Area_units WgtsTblRow = WgtsTblRows.Next() #Set state of calculation #gp.AddMessage("Max OID: " + str(maxOID)) if maxOID >= 0: #Select rows with OID <= maxOID and Set new field values Where = OIDName + " <= " + str(maxOID) WgtsTblRows = gp.UpdateCursor(wtstable, Where) WgtsTblRow = WgtsTblRows.Next() while WgtsTblRow: """ Missing data row should be processed after Gen_Class=2 is complete. Then MD row should be found. If found, get area and num points of pattern=2 and compute MD std. """ if WgtsTblRow.Class == MissingDataValue: WgtsTblRow.Gen_Class = MissingDataValue WgtsTblRow.Weight = 0.0 WgtsTblRow.W_Std = 0.0 else: WgtsTblRow.Gen_Class = 2 WgtsTblRow.Weight = maxWplus WgtsTblRow.W_Std = maxWplus_Std WgtsTblRows.UpdateRow(WgtsTblRow) WgtsTblRow = WgtsTblRows.Next() #gp.AddMessage("Set IN rows.") #Select rows with OID > maxOID and Set new field values Where = OIDName + " > " + str(maxOID) WgtsTblRows = gp.UpdateCursor(wtstable, Where) WgtsTblRow = WgtsTblRows.Next() while WgtsTblRow: if WgtsTblRow.Class == MissingDataValue: #gp.AddMessage("Setting missing data gen_class...") WgtsTblRow.Gen_Class = MissingDataValue WgtsTblRow.Weight = 0.0 WgtsTblRow.W_Std = 0.0 else: WgtsTblRow.Gen_Class = 1 WgtsTblRow.Weight = maxWminus WgtsTblRow.W_Std = maxWminus_Std WgtsTblRows.UpdateRow(WgtsTblRow) WgtsTblRow = WgtsTblRows.Next() #gp.AddMessage("Set OUT rows.") else: gp.AddWarning("No row Contrast for type %s satisfied the user confidence contrast = %s"%(Type,Confident_Contrast)) gp.AddWarning("Table %s is incomplete."%wtstable) #gp.Delete(wtstable) Success = 0 # Invalid Table: No confidence else: #Categorical #Get Wts and Wts_Std for class values outside confidence Out_Area = 0 Out_NumTPs = 0.0 #Out_SumWStds = 0.0 Out_Num = 0 #>>>>>>>>>>>>>>>>Out Rows>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #Select rows having less than specified absolute confidence; they are assigned to Out_Gen_Class WhereClause = "(STUD_CNT > -%f) and (STUD_CNT < %f)" %(Confident_Contrast, Confident_Contrast) #gp.AddMessage(WhereClause) WgtsTblRows = gp.SearchCursor(wtstable, WhereClause) WgtsTblRow = WgtsTblRows.Next() #Categorical might have a Class.Value = 0 Out_Gen_Class = int(99) if WgtsTblRow: #gp.AddMessage("Processing no-confidence rows...") while WgtsTblRow: #gp.AddMessage("Class="+str(WgtsTblRow.Class)) ## ## Missing data row should be processed after Outside classes are complete. ## Then MD row should be found. If found, get area and num points of ## Outside classes and compute MD std. ## if WgtsTblRow.Class != MissingDataValue: #Process Out Rows for total TPs=Out_NumTPs, total Area=Out_Area, number=Out_Num #Categorical might have a Class.Value = 0, therefore #Give Outside generalized class a value=10^n + 99, some n >= 0... if WgtsTblRow.Class >= Out_Gen_Class: Out_Gen_Class += 100 Out_NumTPs += WgtsTblRow.no_points Out_Area += WgtsTblRow.Area Out_Num = Out_Num + 1 WgtsTblRow = WgtsTblRows.Next() #Calculate Wts from Out Area and Out TPs for combined Out Rows if Out_Num>0: if Out_NumTPs == 0: Out_NumTPs = 0.01 Wts = MakeWts(float(Out_NumTPs), Out_Area, Unitarea, totalTPs, totalArea, Type) if not Wts: gp.AddError("Weights calculation aborted.") #raise ErrorExit #gp.AddMessage("Num Out TPs=%d, Area Out Rows=%f: %f, %f"%(Out_NumTPs,Out_Area,Wts[0],Wts[1])) #gp.AddMessage("Got wts stats." + str(Wts)) #At,Aj,Adt,Adj = studyArea/Unit,float(ds),Out_Area/fac/Unit,float(Out_NumTPs) #<<<<<<<<<<<<<<<<= Confident_Contrast: #In Rows WgtsTblRow.Gen_Class = WgtsTblRow.Class WgtsTblRow.Weight = WgtsTblRow.Wplus WgtsTblRow.W_Std = WgtsTblRow.S_Wplus In_Num += 1 elif Out_Num > 0: #Out Rows if WgtsTblRow.Class == Out_Gen_Class: gp.AddError("Categorical: Class value of the outside generalized class is same as an inside class.") raise ErrorExit WgtsTblRow.Gen_Class = Out_Gen_Class WgtsTblRow.Weight = Wts[0] WgtsTblRow.W_Std = Wts[1] WgtsTblRows.UpdateRow(WgtsTblRow) #gp.AddMessage("Class=" + str(WgtsTblRow.Class)) WgtsTblRow = WgtsTblRows.Next() if In_Num == 0: gp.AddWarning("No row Contrast for type %s satisfied the user confidence contrast = %s"%(Type,Confident_Contrast)) gp.AddWarning("Table %s is incomplete."%wtstable) Success = 0 # Invalid Table: fails confidence test #end of Categorical generalization else: #Type is Unique #gp.AddMessage("Setting Unique Generalization") WgtsTblRows = gp.UpdateCursor(wtstable) WgtsTblRow = WgtsTblRows.Next() while WgtsTblRow: WgtsTblRow.Gen_Class = WgtsTblRow.Class WgtsTblRow.Weight = 0.0 WgtsTblRow.W_Std = 0.0 WgtsTblRows.UpdateRow(WgtsTblRow) #gp.AddMessage("Class=" + str(WgtsTblRow.Class)) WgtsTblRow = WgtsTblRows.Next() del WgtsTblRow, WgtsTblRows gp.AddMessage("Done creating table.") #gp.AddWarning("Success: %s"%Success) #Delete extraneous fields gp.DeleteField_management(wtstable, "area;areaunits;count;rastervalu;frequency;sum_raster") #Set Output Parameter gp.SetParameterAsText(4, gp.Describe(wtstable).CatalogPath) gp.SetParameter(8, Success) except ErrorExit: Success = 0 # Invalid Table: Error gp.SetParameter(8, Success) print 'Aborting wts calculation' except Exception, msg: # get the traceback object tb = sys.exc_info()[2] # tbinfo contains the line number that the code failed on and the code from that line tbinfo = traceback.format_tb(tb)[0] # concatenate information together concerning the error into a message string pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n " + \ str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n" # generate a message string for any geoprocessing tool errors msgs = "GP ERRORS:\n" + gp.GetMessages(2) + "\n" gp.AddError(msgs) # return gp messages for use with a script tool gp.AddError(pymsg) # print messages for use in Python/PythonWin print pymsg print msgs raise