[GRASS-SVN] r30012 - grass/trunk/gui/wxpython/gui_modules
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Feb 8 01:42:04 EST 2008
Author: cmbarton
Date: 2008-02-08 01:42:04 -0500 (Fri, 08 Feb 2008)
New Revision: 30012
Modified:
grass/trunk/gui/wxpython/gui_modules/georect.py
Log:
Added RMS and point error calculation and display. Improved error checking and convenience features.
Modified: grass/trunk/gui/wxpython/gui_modules/georect.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/georect.py 2008-02-08 06:41:16 UTC (rev 30011)
+++ grass/trunk/gui/wxpython/gui_modules/georect.py 2008-02-08 06:42:04 UTC (rev 30012)
@@ -65,13 +65,10 @@
sys.path.append(imagepath)
# global variables
-global grassdatabase
-global xy_group
global xy_map
global maptype
-xy_group = ''
xy_map = ''
maptype = 'cell'
@@ -132,6 +129,8 @@
self.currentlocation = self.gisrc_dict['LOCATION_NAME']
self.currentmapset = self.gisrc_dict['MAPSET']
+ self.newlocation = '' #location for xy map to georectify
+ self.newmapset = '' #mapset for xy map to georectify
self.new_gisrc = '' #GISRC file for source location/mapset of map(s) to georectify
@@ -218,6 +217,13 @@
"""Create environment to use for location and mapset
that are the source of the file(s) to georectify"""
+ self.newlocation = location
+ self.newmapset = mapset
+
+ # check to see if we are georectifying map in current working location/mapset
+ if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
+ return
+
self.gisrc_dict['LOCATION_NAME'] = location
self.gisrc_dict['MAPSET'] = mapset
self.new_gisrc = utils.GetTempfile()
@@ -227,8 +233,15 @@
f.close()
def SwitchEnv(self, grc):
- """Switches between original working location/mapset and
- location/mapset that is source of file(s) to georectify"""
+ """
+ Switches between original working location/mapset and
+ location/mapset that is source of file(s) to georectify
+ """
+
+ # check to see if we are georectifying map in current working location/mapset
+ if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
+ return
+
if grc == 'original':
os.environ["GISRC"] = str(self.orig_gisrc)
elif grc == 'new':
@@ -410,9 +423,7 @@
self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
self.Bind(wx.EVT_CLOSE, self.parent.Cleanup)
- def OnGroup(self, event):
- global xy_group
-
+ def OnGroup(self, event):
self.xygroup = event.GetString()
def OnMkGroup(self, event):
@@ -426,13 +437,23 @@
dlg = VectGroup(self, wx.ID_ANY, self.grassdatabase, self.xylocation, self.xymapset, self.xygroup)
if dlg.ShowModal() == wx.ID_OK:
dlg.MakeVGroup()
-
+
+ #refresh combobox list
+ try:
+ tmplist = os.listdir(os.path.join(self.grassdatabase,self.xylocation,self.xymapset,'group'))
+ except:
+ return
+ if tmplist != []:
+ for item in tmplist:
+ if os.path.isdir(os.path.join(self.grassdatabase,self.xylocation,self.xymapset,'group',item)):
+ self.groupList.append(item)
+
+ self.cb_group.SetItems(self.groupList)
+
def OnExtension(self, event):
self.extension = event.GetString()
def onPageChanging(self,event=None):
- global xy_group
-
if event.GetDirection() and self.xygroup == '':
wx.MessageBox('You must select a valid image/map group in order to continue')
event.Veto()
@@ -520,7 +541,8 @@
def __init__(self,parent,id=-1,title="Create & manage ground control points",
size=wx.DefaultSize, grwiz=None):
- wx.Frame.__init__(self, parent, id , title, size=(500,400))
+ wx.Frame.__init__(self, parent, id , title, size=(600,300))
+ self.Centre(wx.HORIZONTAL)
toolbar = self.__createToolBar()
@@ -529,6 +551,8 @@
self.grassdatabase = self.grwiz.grassdatabase
self.currentlocation = self.grwiz.currentlocation
self.currentmapset = self.grwiz.currentmapset
+ self.newlocation = self.grwiz.newlocation
+ self.newmapset = self.grwiz.newmapset
self.xylocation = self.grwiz.gisrc_dict['LOCATION_NAME']
self.xymapset = self.grwiz.gisrc_dict['MAPSET']
self.xygroup = self.grwiz.grouppage.xygroup
@@ -542,7 +566,17 @@
self.gr_order = 1 #polynomial order transformation for georectification
self.selected = 0 #gcp list item selected
+ self.GCPcount = 0 #number of GCPs selected to be used for georectification (checked)
+ self.fwd_rmserror = 0.0 # forward RMS error
+ self.bkw_rmserror = 0.0 # backward RMS error
self.mapcoordlist = [(0000000.00,0000000.00,'')] #list map coords and ID of map display they came from
+
+ self.CreateStatusBar(3,1,-1,'gcpstatusbar')
+ self.SetStatusText('RMS error for selected points',0)
+
+ # can put guage into custom statusbar for progress if can figure out how to get progress text from i.rectify
+ #self.gr_gauge = wx.Gauge(self, -1, 100, (-1,-1), (100, 25))
+ #self.gr_guage.Pulse()
p = wx.Panel(self, -1, style=0)
@@ -567,9 +601,9 @@
if os.path.isfile(self.pointsfile):
self.ReadGCPs()
self.ResizeColumns()
- elif self.list.self.list.GetItemCount() == 0:
+ elif self.list.GetItemCount() == 0:
# initialize 3 blank lines in the GCP list (minimum for georectification)
- i = ('0000000.00','0000000.00','0000000.00','0000000.00','0000.00','0000.00')
+ i = ('0000000.00','0000000.00','0000000.00','0000000.00','','')
index = self.list.InsertStringItem(sys.maxint, i[0])
self.list.SetStringItem(index, 1, i[1])
self.list.SetStringItem(index, 2, i[2])
@@ -607,11 +641,15 @@
def SetTarget(self, tgroup, tlocation, tmapset):
"""
- sets rectification target to current location and mapset
+ Sets rectification target to current location and mapset
"""
- self.grwiz.SwitchEnv('new')
- cmdlist = ['i.target', 'group=%s' % tgroup, 'location=%s' % tlocation, 'mapset=%s' % tmapset]
+ # check to see if we are georectifying map in current working location/mapset
+ if self.newlocation == self.currentlocation and self.newmapset == self.currentmapset:
+ cmdlist = ['i.target', 'c', 'group=%s' % tgroup]
+ else:
+ self.grwiz.SwitchEnv('new')
+ cmdlist = ['i.target', 'group=%s' % tgroup, 'location=%s' % tlocation, 'mapset=%s' % tmapset]
gcmd.Command(cmd=cmdlist)
def addToolbarButton(self, toolbar, label, icon, help, handler):
@@ -626,7 +664,7 @@
def toolbarData(self):
return (
- ('savegcp', Icons["savefile"].GetBitmap(), Icons["savefile"].GetLabel(), self.SaveGCPs),
+ ('savegcp', Icons["savefile"].GetBitmap(), 'Save GCPs to POINTS file', self.SaveGCPs),
('addgcp', wx.ArtProvider.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR, (16,16)), 'Add new GCP', self.AddGCP),
('deletegcp', wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR, (16,16)), 'Delete selected GCP', self.DeleteGCP),
('cleargcp', Icons["cleargcp"].GetBitmap(), Icons["cleargcp"].GetLabel(), self.ClearGCP),
@@ -638,8 +676,10 @@
def SaveGCPs(self, event):
"""
- make a POINTS file or save GCP coordinates to existing POINTS file
+ Make a POINTS file or save GCP coordinates to existing POINTS file
"""
+
+ self.GCPcount = 0
f = open(self.pointsfile, mode='w')
try:
f.write('# Ground Control Points File\n')
@@ -652,6 +692,7 @@
for index in range(self.list.GetItemCount()):
if self.list.IsChecked(index) == True:
check = "1"
+ self.GCPcount += 1
else:
check = "0"
coord0 = self.list.GetItem(index, 0).GetText()
@@ -665,7 +706,7 @@
def DeleteGCP(self, event):
"""
- deletes selected line in GCP list
+ Deletes selected item in GCP list
"""
self.list.DeleteItem(self.selected)
@@ -673,20 +714,20 @@
def AddGCP(self, event):
"""
- appends a line to GCP list
+ Appends an item to GCP list
"""
- self.list.Append(['0000000.00','0000000.00','0000000.00','0000000.00','0000.00','0000.00'])
+ self.list.Append(['0000000.00','0000000.00','0000000.00','0000000.00','',''])
index = self.list.GetItemCount() - 1
self.mapcoordlist.append((0000000.00,0000000.00,''))
- self.list.CheckItem(index, True)
self.list.SetItemState(index, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
self.ResizeColumns()
return index
def SetGCPData(self, coordtype, coord, mapdisp=None, check=True):
"""
- inserts coordinates into line in GCP list
+ Inserts coordinates from mouse click on map
+ into selected item of GCP list and checks it for use
"""
index = self.selected
@@ -700,59 +741,87 @@
self.list.SetStringItem(index, 2, coord0)
self.list.SetStringItem(index, 3, coord1)
self.mapcoordlist[index] = (coord[0], coord[1], mapdisp)
- if coordtype == 'rms':
- self.list.SetStringItem(index, 4, coord0)
- self.list.SetStringItem(index, 5, coord1)
self.list.CheckItem(index, check)
self.ResizeColumns()
def ClearGCP(self, event):
"""
- sets all values in selected GCP line to 0
+ Clears all values in selected item of GCP list and unchecks it
"""
index = self.selected
- for i in range(6):
+ for i in range(4):
self.list.SetStringItem(index, i, '0000000.00')
+ self.list.SetStringItem(index, 4, '')
+ self.list.SetStringItem(index, 5, '')
self.mapcoordlist[index] = (0000000.00,0000000.00,'')
+ self.list.CheckItem(index, False)
def ReadGCPs(self):
"""
- reads GCPs and georectified coordinates from POINTS file
+ Reads GCPs and georectified coordinates from POINTS file
"""
-
+
+ self.GCPcount = 0
f = open(self.pointsfile)
try:
+ GCPcnt = 0
for line in f:
if line[0] != '#' and line !='':
line = line.strip(' \n')
coords = line.split()
if coords[4] == '1':
check = True
+ self.GCPcount +=1
else:
check = False
index = self.AddGCP(event=None)
for i in range(4):
self.list.SetStringItem(index, i, coords[i])
self.list.CheckItem(index, check)
- self.RefreshGCPMarks(None)
finally:
f.close()
+ self.RefreshGCPMarks(None)
+
+ if self.CheckGCPcount():
+ self.RMSError(self.xygroup, self.gr_order)
def OnRMS(self, event):
"""
- calculates RMS error
+ RMS button handler
"""
- pass
+ self.RMSError(self.xygroup,self.gr_order)
+
+ def CheckGCPcount(self, msg=False):
+ """
+ Checks to make sure that the minimum number of GCPs have been defined and
+ are active for the selected transformation order
+ """
+ if (self.GCPcount < 3 and self.gr_order == 1) or \
+ (self.GCPcount < 6 and self.gr_order == 2) or \
+ (self.GCPcount < 10 and self.gr_order == 3):
+ if msg:
+ s1 = 'Insufficient points defined and active (checked)\n'
+ s2 = 'for selected rectification method.\n'
+ s3 = '3+ points needed for 1st order,\n'
+ s4 = '6+ points for 2nd order, and\n'
+ s5 = '10+ points for 3rd order.'
+ wx.MessageBox('%s%s%s%s%s' % (s1, s2, s3, s4, s5))
+ return False
+ else:
+ return True
def OnGeorect(self, event):
"""
- georectifies map using i.rectify or v.transform
+ Georectifies map(s) in group using i.rectify or v.transform
"""
global maptype
+ self.SaveGCPs()
+
+ if self.CheckGCPcount(msg=True) == False:
+ return
if maptype == 'cell':
- print 'in cell rectify'
cmdlist = ['i.rectify', '-ca', 'group=%s' % self.xygroup, 'extension=%s' % self.extension, 'order=%s' % self.gr_order]
p = gcmd.Command(cmd=cmdlist)
stdout = p.ReadStdOutput()
@@ -815,7 +884,7 @@
def OnItemActivated(self, event):
"""
- when item double clicked, open editor for coordinate values; update values
+ When item double clicked, open editor to update coordinate values
"""
coords = []
index = event.m_itemIndex
@@ -833,8 +902,8 @@
def RefreshGCPMarks(self, event):
"""
- Update GCP and map coord maps and redraw
- active GCP markers on both
+ Updates GCP and map coord maps and redraws
+ active (checked) GCP markers
"""
self.grwiz.SwitchEnv("new")
self.grwiz.mapwin.UpdateMap()
@@ -868,11 +937,54 @@
def OnGRMethod(self, event):
"""
- sets transformation type for georectifying
+ sets transformation order for georectifying
"""
self.gr_order = event.GetInt() + 1
+
+ def RMSError(self, xygroup, order):
+ """
+ Uses g.transform to calculate forward and backward error for each used GCP
+ in POINTS file and insert error values into GCP list.
+ Calculates total forward and backward RMS error for all used points
+ """
+
+ # save GCPs to points file to make sure that all checked GCPs are used
+ self.SaveGCPs(None)
+
+ if self.CheckGCPcount(msg=True) == False:
+ return
+
+ #get list of forward and reverse rms error values for each point
+ self.grwiz.SwitchEnv('new')
+ cmdlist = ['g.transform', 'group=%s' % xygroup, 'order=%s' % order]
+ p = gcmd.Command(cmdlist)
+ errlist = p.ReadStdOutput()
+ if errlist == []:
+ return
+
+ #insert error values into GCP list for checked items
+ i = 0
+ sumsq_fwd_err = 0.0
+ sumsq_bkw_err = 0.0
+ for index in range(self.list.GetItemCount()):
+ if self.list.IsChecked(index):
+ fwd_err,bkw_err = errlist[i].split()
+ self.list.SetStringItem(index, 4, fwd_err)
+ self.list.SetStringItem(index, 5, bkw_err)
+ sumsq_fwd_err += float(fwd_err)**2
+ sumsq_bkw_err += float(bkw_err)**2
+ i += 1
+ else:
+ self.list.SetStringItem(index, 4, '')
+ self.list.SetStringItem(index, 5, '')
+
+ #calculate RMS error
+ self.fwd_rmserror = round((sumsq_fwd_err/i)**0.5,4)
+ self.bkw_rmserror = round((sumsq_bkw_err/i)**0.5,4)
+ self.ResizeColumns()
+ self.SetStatusText('forward: %s' % self.fwd_rmserror,1)
+ self.SetStatusText('backward: %s' % self.bkw_rmserror,2)
-
class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
style=0):
@@ -886,10 +998,11 @@
# this is called by the base class when an item is checked/unchecked
def OnCheckItem(self, index, flag):
pass
+
class VectGroup(wx.Dialog):
"""
- dialog to create a vector group (VREF file) for georectifying
+ Dialog to create a vector group (VREF file) for georectifying
"""
def __init__(self, parent, id, grassdb, location, mapset, group,
@@ -964,7 +1077,7 @@
label = self.addmap.GetString(index)
if self.addmap.IsChecked(index):
self.vgrouplist.append(label)
- self.addmap.SetSelection(index) # so that (un)checking also selects (moves the highlight)
+ self.addmap.SetSelection(index)
event.Skip()
def RemoveVect(self, event):
@@ -972,7 +1085,7 @@
label = self.remmap.GetString(index)
if self.remmap.IsChecked(index):
self.vgrouplist.remove(label)
- self.remmap.SetSelection(index) # so that (un)checking also selects (moves the highlight)
+ self.remmap.SetSelection(index)
event.Skip()
def MakeVGroup(self):
@@ -1038,7 +1151,7 @@
self.Layout()
def GetValues(self, columns=None):
- """Return list of values (as string).
+ """Return list of values (as strings).
"""
valuelist = []
valuelist.append(self.xcoord.GetValue())
More information about the grass-commit
mailing list