You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
|
Feb
(1) |
Mar
(15) |
Apr
(20) |
May
(2) |
Jun
(9) |
Jul
(3) |
Aug
(2) |
Sep
(17) |
Oct
(16) |
Nov
(38) |
Dec
(40) |
2010 |
Jan
(51) |
Feb
(11) |
Mar
(24) |
Apr
(31) |
May
(24) |
Jun
(3) |
Jul
(9) |
Aug
(1) |
Sep
(29) |
Oct
(33) |
Nov
(81) |
Dec
(6) |
2011 |
Jan
(2) |
Feb
(4) |
Mar
(13) |
Apr
(4) |
May
(24) |
Jun
(4) |
Jul
(19) |
Aug
(46) |
Sep
(10) |
Oct
(28) |
Nov
(31) |
Dec
|
From: <jb...@us...> - 2010-10-05 00:15:01
|
Revision: 643 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=643&view=rev Author: jblance Date: 2010-10-05 00:14:54 +0000 (Tue, 05 Oct 2010) Log Message: ----------- Fixes to edit record Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Added Paths: ----------- pytrainer/trunk/schemas/pytrainer-0.1.xsd Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-04 04:50:08 UTC (rev 642) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-05 00:14:54 UTC (rev 643) @@ -128,6 +128,7 @@ ''' Draw a plot style graph ''' + print "drawGraph 131: DEPRECIATED drawPlot called" #data = {'linewidth':3, 'x':(1,2,3), 'y':(3,9,1)} logging.debug('>>') if box is None: Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-10-04 04:50:08 UTC (rev 642) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-10-05 00:14:54 UTC (rev 643) @@ -28,549 +28,619 @@ from dateutil.tz import * # for tzutc() class WindowRecord(SimpleGladeApp): - def __init__(self, data_path = None, listSport = None, parent = None, date = None, title=None, distance=None, time=None, upositive=None, unegative=None, bpm=None, calories=None, comment=None, windowTitle=None): - self.parent = parent - self.data_path = data_path - glade_path="glade/newrecord.glade" - root = "newrecord" - domain = None - self.mode = "newrecord" - self.id_record = "" - self.store = None - self.active_row = None - self.activity_data = [] - SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) - self.conf_options = [ - "rcd_date", - "rcd_sport", - "rcd_distance", - "rcd_beats", - "rcd_comments", - "rcd_average", - "rcd_calories", - "rcd_title", - "rcd_gpxfile", - "rcd_upositive", - "rcd_unegative", - "rcd_maxbeats", - "rcd_pace", - "rcd_maxpace", - "rcd_maxvel", - ] - self.listSport = {} - for i in listSport: - self.listSport[i[3]] = i[0] #Create dictionary using SportID as key (may be non sequential if sports have been deleted) - for i in self.listSport: - self.rcd_sport.insert_text(i,self.listSport[i]) - self.rcd_sport.set_active(0) + def __init__(self, data_path = None, listSport = None, parent = None, date = None, title=None, distance=None, time=None, upositive=None, unegative=None, bpm=None, calories=None, comment=None, windowTitle=None): + logging.debug(">>") + self.parent = parent + self.pytrainer_main = parent.pytrainer_main + self.data_path = data_path + glade_path="glade/newrecord.glade" + root = "newrecord" + domain = None + self.mode = "newrecord" + self.id_record = "" + self.store = None + self.active_row = None + self.activity_data = [] + SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) + self.conf_options = [ + "rcd_date", + "rcd_sport", + "rcd_distance", + "rcd_beats", + "rcd_comments", + "rcd_average", + "rcd_calories", + "rcd_title", + "rcd_gpxfile", + "rcd_upositive", + "rcd_unegative", + "rcd_maxbeats", + "rcd_pace", + "rcd_maxpace", + "rcd_maxvel", + ] + self.listSport = {} + for i in listSport: + self.listSport[i[3]] = i[0] #Create dictionary using SportID as key (may be non sequential if sports have been deleted) + for i in self.listSport: + self.rcd_sport.insert_text(i,self.listSport[i]) + self.rcd_sport.set_active(0) - if windowTitle is not None: - self.newrecord.set_title(windowTitle) - if date != None: - self.setDate(date) - if title != None: - self.rcd_title.set_text(title) - if distance != None: - self.rcd_distance.set_text(distance) - if time != None: - self.setTime(time) - if distance!=None and time!=None: - self.on_calcaverage_clicked(None) - if upositive != None: - self.rcd_upositive.set_text(upositive) - if unegative != None: - self.rcd_unegative.set_text(unegative) - if calories != None: - self.rcd_calories.set_text(calories) - - def getActivityData(self): - return self.activity_data - - def populateMultiWindow(self, activities): - self.mode = "multiple_activities" - #activities (activity_id, start_time, distance, duration, sport, gpx_file, file_id) - self.activity_data = [] - #Make treeview - self.store = self.build_tree_view() - #Add data - for activity in activities: - iter = self.store.append() - self.store.set( - iter, - 0, activity[0], - 1, activity[1], - 2, activity[2], - 3, activity[3], - 4, activity[4], - 5, activity[5] - ) - details = {} - details["complete"] = False - details["rcd_distance"] = activity[2] - duration = activity[3] - if duration.count(":") == 2: - hours, mins, secs = duration.split(":") - else: - hours = mins = secs = 0 - #details["rcd_hour"] = float(hours) - #details["rcd_min"] = float(mins) - #details["rcd_second"] = float(secs) - #details["rcd_time"] = (((float(hours) * 60) + float(mins)) * 60) + float(secs) - details["activity_id"] = activity[0] - details["rcd_time"] = (float(hours), float(mins), float(secs)) - details["rcd_sport"] = activity[4] - details["rcd_gpxfile"] = activity[5] - details["file_id"] = activity[6] - self.activity_data.append(details) - self.scrolledwindowEntries.show_all() - #Hide some of the buttons - self.button25.hide() #GPX file "Open" button - self.button24.hide() #GPX file "Calculate Values" button - self.button10.hide() #Distance "Calculate" button - self.button11.hide() #Duration "Calculate" button - #self.button12.hide() #Velocity "Calculate" button - self.button43.hide() #Pace "Calculate" button - #Make GPX file 'unsensitive' - self.rcd_gpxfile.set_sensitive(0) - while gtk.events_pending(): # This allows the GUI to update - gtk.main_iteration() # before completion of this entire action - #Select first row and display details - self.treeviewEntries.set_cursor(0) - self.show_treeviewEntries_row(0) - - def build_tree_view(self): - store = gtk.ListStore( gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING ) - column_names=["id", _("Start Time"), _("Distance"),_("Duration"),_("Sport"), _("GPX File")] - for column_index, column_name in enumerate(column_names): - #Add columns - column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) - column.set_sort_column_id(column_index) - if column_name == "id": - column.set_visible(False) - column.set_resizable(True) - self.treeviewEntries.append_column(column) - self.treeviewEntries.set_headers_clickable(True) - self.treeviewEntries.set_model(store) - return store - - def on_accept_clicked(self,widget): - if self.mode == "multiple_activities": - #Check for edited data in comments - if self.active_row is not None: - buffer = self.rcd_comments.get_buffer() - start,end = buffer.get_bounds() - comments = buffer.get_text(start,end, True).replace("\"","'") - self.activity_data[self.active_row]["rcd_comments"] = comments - #Advanced tab items - self.activity_data[self.active_row]["rcd_maxpace"] = self.rcd_maxpace.get_text() - self.activity_data[self.active_row]["rcd_pace"] = self.rcd_pace.get_text() - self.activity_data[self.active_row]["rcd_upositive"] = self.rcd_upositive.get_text() - self.activity_data[self.active_row]["rcd_unegative"] = self.rcd_unegative.get_text() - self.activity_data[self.active_row]["rcd_maxbeats"] = self.rcd_maxbeats.get_text() - self.activity_data[self.active_row]["rcd_beats"] = self.rcd_beats.get_text() - self.activity_data[self.active_row]["rcd_calories"] = self.rcd_calories.get_text() - row = 0 - for activity in self.activity_data: - index = self.activity_data.index(activity) - if activity["complete"] is False: - #Did not view or modify this record - need to get all the details - print "Activity incomplete.. " + activity["rcd_gpxfile"] - self.update_activity_data(row, activity["rcd_gpxfile"], activity["rcd_sport"]) - activity["rcd_title"] = activity["rcd_title"].replace("\"","'") - #Add activity to DB etc - laps = activity.pop("laps", ()) - self.activity_data[index]["db_id"] = self.parent.insertRecord(activity, laps) - row += 1 - logging.debug("Processed %d rows of activity data" % row) - else: - list_options = {} - trackSummary = {} - for i in self.conf_options: - var = getattr(self,i) - if i == "rcd_title": - list_options[i] = var.get_text().replace("\"","'") - elif i != "rcd_sport" and i != "rcd_comments": - list_options[i] = var.get_text() - elif i == "rcd_sport": - list_options[i] = var.get_active_text() - elif i == "rcd_comments": - buffer = var.get_buffer() - start,end = buffer.get_bounds() - list_options[i] = buffer.get_text(start,end, True) - list_options[i] = list_options[i].replace("\"","'") - list_options["rcd_time"] = [self.rcd_hour.get_value_as_int(),self.rcd_min.get_value_as_int(),self.rcd_second.get_value_as_int()] - if self.mode == "newrecord": - logging.debug('Track data: '+str(list_options)) - if list_options["rcd_gpxfile"] != "": - logging.info('Adding new activity based on GPX file') - trackSummary=(list_options["rcd_sport"],"","") - self.parent.insertNewRecord(list_options["rcd_gpxfile"], trackSummary) - else: - logging.info('Adding new activity based on provided data') - #Manual entry, calculate time info - record_time = self.rcd_starttime.get_text() - record_date = self.rcd_date.get_text() - localtz = Date().getLocalTZ() - date = dateutil.parser.parse(record_date+" "+record_time+" "+localtz) - local_date = str(date) - utc_date = date.astimezone(tzutc()).strftime("%Y-%m-%dT%H:%M:%SZ") - list_options["date_time_utc"] = utc_date - list_options["date_time_local"] = local_date - self.parent.insertRecord(list_options) - elif self.mode == "editrecord": - self.parent.updateRecord(list_options, self.id_record) - self.close_window() - - def on_cancel_clicked(self,widget): - self.close_window() + if windowTitle is not None: + self.newrecord.set_title(windowTitle) + if date != None: + self.setDate(date) + if title != None: + self.rcd_title.set_text(title) + if distance != None: + self.rcd_distance.set_text(distance) + if time != None: + self.setTime(time) + if distance!=None and time!=None: + self.on_calcaverage_clicked(None) + if upositive != None: + self.rcd_upositive.set_text(upositive) + if unegative != None: + self.rcd_unegative.set_text(unegative) + if calories != None: + self.rcd_calories.set_text(calories) + logging.debug("<<") + + def getActivityData(self): + return self.activity_data + + def populateMultiWindow(self, activities): + logging.debug(">>") + self.mode = "multiple_activities" + #activities (activity_id, start_time, distance, duration, sport, gpx_file, file_id) + self.activity_data = [] + #Make treeview + self.store = self.build_tree_view() + #Add data + for activity in activities: + iter = self.store.append() + self.store.set( + iter, + 0, activity[0], + 1, activity[1], + 2, activity[2], + 3, activity[3], + 4, activity[4], + 5, activity[5] + ) + details = {} + details["complete"] = False + details["rcd_distance"] = activity[2] + duration = activity[3] + if duration.count(":") == 2: + hours, mins, secs = duration.split(":") + else: + hours = mins = secs = 0 + #details["rcd_hour"] = float(hours) + #details["rcd_min"] = float(mins) + #details["rcd_second"] = float(secs) + #details["rcd_time"] = (((float(hours) * 60) + float(mins)) * 60) + float(secs) + details["activity_id"] = activity[0] + details["rcd_time"] = (float(hours), float(mins), float(secs)) + details["rcd_sport"] = activity[4] + details["rcd_gpxfile"] = activity[5] + details["file_id"] = activity[6] + self.activity_data.append(details) + self.scrolledwindowEntries.show_all() + #Hide some of the buttons + self.button25.hide() #GPX file "Open" button + self.button24.hide() #GPX file "Calculate Values" button + self.button10.hide() #Distance "Calculate" button + self.button11.hide() #Duration "Calculate" button + #self.button12.hide() #Velocity "Calculate" button + self.button43.hide() #Pace "Calculate" button + #Make GPX file 'unsensitive' + self.rcd_gpxfile.set_sensitive(0) + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + #Select first row and display details + self.treeviewEntries.set_cursor(0) + self.show_treeviewEntries_row(0) + logging.debug("<<") + + def build_tree_view(self): + store = gtk.ListStore( gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING ) + column_names=["id", _("Start Time"), _("Distance"),_("Duration"),_("Sport"), _("GPX File")] + for column_index, column_name in enumerate(column_names): + #Add columns + column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) + column.set_sort_column_id(column_index) + if column_name == "id": + column.set_visible(False) + column.set_resizable(True) + self.treeviewEntries.append_column(column) + self.treeviewEntries.set_headers_clickable(True) + self.treeviewEntries.set_model(store) + return store + + def on_accept_clicked(self,widget): + logging.debug(">>") + if self.mode == "multiple_activities": + logging.debug("multiple_activities") + #Check for edited data in comments + if self.active_row is not None: + buffer = self.rcd_comments.get_buffer() + start,end = buffer.get_bounds() + comments = buffer.get_text(start,end, True).replace("\"","'") + self.activity_data[self.active_row]["rcd_comments"] = comments + #Advanced tab items + self.activity_data[self.active_row]["rcd_maxpace"] = self.rcd_maxpace.get_text() + self.activity_data[self.active_row]["rcd_pace"] = self.rcd_pace.get_text() + self.activity_data[self.active_row]["rcd_upositive"] = self.rcd_upositive.get_text() + self.activity_data[self.active_row]["rcd_unegative"] = self.rcd_unegative.get_text() + self.activity_data[self.active_row]["rcd_maxbeats"] = self.rcd_maxbeats.get_text() + self.activity_data[self.active_row]["rcd_beats"] = self.rcd_beats.get_text() + self.activity_data[self.active_row]["rcd_calories"] = self.rcd_calories.get_text() + row = 0 + for activity in self.activity_data: + index = self.activity_data.index(activity) + if activity["complete"] is False: + #Did not view or modify this record - need to get all the details + print "Activity incomplete.. " + activity["rcd_gpxfile"] + self.update_activity_data(row, activity["rcd_gpxfile"], activity["rcd_sport"]) + activity["rcd_title"] = activity["rcd_title"].replace("\"","'") + #Add activity to DB etc + laps = activity.pop("laps", ()) + self.activity_data[index]["db_id"] = self.parent.insertRecord(activity, laps) + row += 1 + logging.debug("Processed %d rows of activity data" % row) + else: + logging.debug("Single activity") + list_options = {} + trackSummary = {} + list_options["rcd_date"] = self.rcd_date.get_text() + list_options["rcd_sport"] = self.rcd_sport.get_active_text() + list_options["rcd_distance"] = self.rcd_distance.get_text() + list_options["rcd_beats"] = self.rcd_beats.get_text() + list_options["rcd_average"] = self.rcd_average.get_text() + list_options["rcd_calories"] = self.rcd_calories.get_text() + list_options["rcd_title"] = self.rcd_title.get_text().replace("\"","'") + list_options["rcd_gpxfile"] = self.rcd_gpxfile.get_text() + list_options["rcd_upositive"] = self.rcd_upositive.get_text() + list_options["rcd_unegative"] = self.rcd_unegative.get_text() + list_options["rcd_maxbeats"] = self.rcd_maxbeats.get_text() + list_options["rcd_pace"] = self.rcd_pace.get_text() + list_options["rcd_maxpace"] = self.rcd_maxpace.get_text() + list_options["rcd_maxvel"] = self.rcd_maxvel.get_text() + list_options["rcd_time"] = [self.rcd_hour.get_value_as_int(),self.rcd_min.get_value_as_int(),self.rcd_second.get_value_as_int()] + buffer = self.rcd_comments.get_buffer() + start,end = buffer.get_bounds() + comment = buffer.get_text(start,end, True) + list_options["rcd_comments"] = comment.replace("\"","'") - def close_window(self, widget=None): - self.newrecord.hide() - #self.newrecord = None - self.quit() + if self.mode == "newrecord": + logging.debug('Track data: '+str(list_options)) + if list_options["rcd_gpxfile"] != "": + logging.info('Adding new activity based on GPX file') + trackSummary=(list_options["rcd_sport"],"","") + self.parent.insertNewRecord(list_options["rcd_gpxfile"], trackSummary) + else: + logging.info('Adding new activity based on provided data') + #Manual entry, calculate time info + record_time = self.rcd_starttime.get_text() + record_date = self.rcd_date.get_text() + localtz = Date().getLocalTZ() + date = dateutil.parser.parse(record_date+" "+record_time+" "+localtz) + local_date = str(date) + utc_date = date.astimezone(tzutc()).strftime("%Y-%m-%dT%H:%M:%SZ") + list_options["date_time_utc"] = utc_date + list_options["date_time_local"] = local_date + self.parent.insertRecord(list_options) + elif self.mode == "editrecord": + self.parent.updateRecord(list_options, self.id_record) + logging.debug("<<") + self.close_window() + + def on_cancel_clicked(self,widget): + self.close_window() - def on_calendar_clicked(self,widget): - calendardialog = WindowCalendar(self.data_path,self, date=self.rcd_date.get_text()) - calendardialog.run() + def close_window(self, widget=None): + self.newrecord.hide() + #self.newrecord = None + self.quit() - def setDate(self,date): - self.rcd_date.set_text(date) + def on_calendar_clicked(self,widget): + calendardialog = WindowCalendar(self.data_path,self, date=self.rcd_date.get_text()) + calendardialog.run() - def setTime(self,timeInSeconds): - time_in_hour = int(timeInSeconds)/3600.0 - hour = int(time_in_hour) - min = int((time_in_hour-hour)*60) - sec = (((time_in_hour-hour)*60)-min)*60 - self.rcd_hour.set_value(hour) - self.rcd_min.set_value(min) - self.rcd_second.set_value(sec) + def setDate(self,date): + self.rcd_date.set_text(date) - def setValue(self,var_name,value, format="%0.2f"): - var = getattr(self,var_name) - try: - valueString = format % value - var.set_text(valueString) - except Exception as e: - print var_name, value, e - pass - - def setValues(self,values): - #(24, u'2009-12-26', 4, 23.48, u'9979', 0.0, 8.4716666232200009, 2210, u'', None, u'', 573.0, 562.0, 11.802745244400001, 5.0499999999999998, 7.04, 0.0, u'2009-12-25T19:41:48Z', u'2009-12-26 08:41:48+13:00') - #(50, u'2006-10-13', 1, 25.0, u'5625', 0.0, 16.0, 0, u'', gpsfile, title,upositive,unegative,maxspeed|maxpace|pace|maxbeats - self.mode = "editrecord" - self.id_record = values[0] - self.setTime(values[4]) - self.rcd_date.set_text(str(values[1])) - self.setValue("rcd_distance",values[3]) - self.setValue("rcd_average",values[6]) - self.setValue("rcd_calories",values[7], "%0.0f") - self.setValue("rcd_beats",values[5], "%0.0f") - self.setValue("rcd_upositive",values[11]) - self.setValue("rcd_unegative",values[12]) - self.setValue("rcd_maxvel",values[13]) - self.setValue("rcd_maxpace",values[14]) - self.setValue("rcd_pace",values[15]) - self.setValue("rcd_maxbeats",values[16], "%0.0f") - self.rcd_title.set_text("%s"%values[10]) - - local_time = values[18] - if local_time is not None: - dateTime = dateutil.parser.parse(local_time) - sTime = dateTime.strftime("%X") - self.rcd_starttime.set_text("%s" % sTime) - sportID = values[2] - sportPosition = self.getSportPosition(sportID) - self.rcd_sport.set_active(sportPosition) - buffer = self.rcd_comments.get_buffer() - start,end = buffer.get_bounds() - buffer.set_text(values[8]) + def setTime(self,timeInSeconds): + time_in_hour = int(timeInSeconds)/3600.0 + hour = int(time_in_hour) + min = int((time_in_hour-hour)*60) + sec = (((time_in_hour-hour)*60)-min)*60 + self.rcd_hour.set_value(hour) + self.rcd_min.set_value(min) + self.rcd_second.set_value(sec) - def getSportPosition(self, sportID): - """ - Function to determine the position in the sport array for a given sport ID - Needed as once sports are deleted there are gaps in the list... - """ - count = 0 - for key, value in self.listSport.iteritems(): - if key == sportID: - return count - count +=1 - return 0 - - def getSportPositionByName(self, sport): - """ - Function to determine the position in the sport array for a given sport - Needed as once sports are deleted there are gaps in the list... - """ - count = 0 - for key, value in self.listSport.iteritems(): - if value == sport: - return count - count +=1 - return None - - def on_calctime_clicked(self,widget): - try: - distance = self.rcd_distance.get_text() - average = self.rcd_average.get_text() - time_in_hour = float(distance)/float(average) - self.set_recordtime(time_in_hour) - except: - pass + def setValue(self,var_name,value, format="%0.2f"): + var = getattr(self,var_name) + try: + valueString = format % value + var.set_text(valueString) + except Exception as e: + print var_name, value, e + pass + + def setValuesFromActivity(self, activity): + logging.debug(">>") + self.mode = "editrecord" + if activity is None: + logging.debug("activity is None") + logging.debug("<<") + return + self.id_record = activity.id_record + (h, m, s) = activity.time_tuple + self.rcd_hour.set_value(h) + self.rcd_min.set_value(m) + self.rcd_second.set_value(s) + self.rcd_date.set_text(activity.date) + self.rcd_distance.set_text("%.2f"%activity.distance) + self.rcd_average.set_text("%.2f"%activity.average) + self.rcd_calories.set_text("%s"%activity.calories) + self.rcd_beats.set_text("%s"%activity.beats) + self.rcd_upositive.set_text("%.2f"%activity.upositive) + self.rcd_unegative.set_text("%.2f"%activity.unegative) + self.rcd_maxvel.set_text("%.2f"%activity.maxspeed) + self.rcd_maxpace.set_text("%s"%self.parent.pace_from_float(activity.maxpace)) + self.rcd_pace.set_text("%s"%self.parent.pace_from_float(activity.pace)) + self.rcd_maxbeats.set_text("%s"%activity.maxbeats) + self.rcd_title.set_text(activity.title) + + if activity.starttime is not None: + self.rcd_starttime.set_text("%s" % activity.starttime) + sportPosition = self.getSportPosition(activity.sport_id) + self.rcd_sport.set_active(sportPosition) + buffer = self.rcd_comments.get_buffer() + start,end = buffer.get_bounds() + buffer.set_text(activity.comments) + if activity.gpx_file is not None: + self.rcd_gpxfile.set_text(activity.gpx_file) + self.frameGeneral.set_sensitive(0) #Currently record values not changed if a GPX file is present + self.frameVelocity.set_sensitive(0) #Greying out options to indicate this to user + logging.debug("<<") + + def setValues(self,values): + #(24, u'2009-12-26', 4, 23.48, u'9979', 0.0, 8.4716666232200009, 2210, u'', None, u'', 573.0, 562.0, 11.802745244400001, 5.0499999999999998, 7.04, 0.0, u'2009-12-25T19:41:48Z', u'2009-12-26 08:41:48+13:00') + #(50, u'2006-10-13', 1, 25.0, u'5625', 0.0, 16.0, 0, u'', gpsfile, title,upositive,unegative,maxspeed|maxpace|pace|maxbeats + print "windowrecord setValues called" + self.mode = "editrecord" + self.id_record = values[0] + self.setTime(values[4]) + self.rcd_date.set_text(str(values[1])) + self.setValue("rcd_distance",values[3]) + self.setValue("rcd_average",values[6]) + self.setValue("rcd_calories",values[7], "%0.0f") + self.setValue("rcd_beats",values[5], "%0.0f") + self.setValue("rcd_upositive",values[11]) + self.setValue("rcd_unegative",values[12]) + self.setValue("rcd_maxvel",values[13]) + self.setValue("rcd_maxpace",values[14]) + self.setValue("rcd_pace",values[15]) + self.setValue("rcd_maxbeats",values[16], "%0.0f") + self.rcd_title.set_text("%s"%values[10]) + + local_time = values[18] + if local_time is not None: + dateTime = dateutil.parser.parse(local_time) + sTime = dateTime.strftime("%X") + self.rcd_starttime.set_text("%s" % sTime) + sportID = values[2] + sportPosition = self.getSportPosition(sportID) + self.rcd_sport.set_active(sportPosition) + buffer = self.rcd_comments.get_buffer() + start,end = buffer.get_bounds() + buffer.set_text(values[8]) - def update_activity_data(self, row, gpx_file, sport): - self.activity_data[row]["rcd_comments"] = "" - gpx_summary, laps = self.parent.summaryFromGPX(gpx_file, (sport,"")) - local_time = gpx_summary['date_time_local'] - start_date = local_time.strftime("%Y-%m-%d") - start_time = local_time.strftime("%H:%M:%S") - self.activity_data[row]["rcd_date"] = start_date - self.activity_data[row]["rcd_starttime"] = start_time - self.activity_data[row]["date_time_local"] = gpx_summary['date_time_local'] - self.activity_data[row]["date_time_utc"] = gpx_summary['date_time_utc'] - self.activity_data[row]["rcd_average"] = gpx_summary["rcd_average"] - self.activity_data[row]["rcd_calories"] = gpx_summary["rcd_calories"] - self.activity_data[row]["rcd_beats"] = gpx_summary["rcd_beats"] - self.activity_data[row]["rcd_upositive"] = gpx_summary["rcd_upositive"] - self.activity_data[row]["rcd_unegative"] = gpx_summary["rcd_unegative"] - self.activity_data[row]["rcd_maxvel"] = gpx_summary["rcd_maxvel"] - self.activity_data[row]["rcd_maxpace"] = gpx_summary["rcd_maxpace"] - self.activity_data[row]["rcd_pace"] = gpx_summary["rcd_pace"] - self.activity_data[row]["rcd_maxbeats"] = gpx_summary["rcd_maxbeats"] - self.activity_data[row]["rcd_title"] = "" - self.activity_data[row]["laps"] = laps - self.activity_data[row]["complete"] = True + def getSportPosition(self, sportID): + """ + Function to determine the position in the sport array for a given sport ID + Needed as once sports are deleted there are gaps in the list... + """ + count = 0 + for key, value in self.listSport.iteritems(): + if key == sportID: + return count + count +=1 + return 0 + + def getSportPositionByName(self, sport): + """ + Function to determine the position in the sport array for a given sport + Needed as once sports are deleted there are gaps in the list... + """ + count = 0 + for key, value in self.listSport.iteritems(): + if value == sport: + return count + count +=1 + return None + + def on_calctime_clicked(self,widget): + try: + distance = self.rcd_distance.get_text() + average = self.rcd_average.get_text() + time_in_hour = float(distance)/float(average) + self.set_recordtime(time_in_hour) + except: + pass - - def show_treeviewEntries_row(self, row): - ''' - Show details of treeview entry - TODO need to maintain any changes and display those.... - ''' - self.active_row = row - #Get details from stored data - #set sport - sport = self.activity_data[row]["rcd_sport"] - sportPosition = self.getSportPositionByName(sport) - if sportPosition is not None: - self.rcd_sport.set_active(sportPosition) - #Set gpx file name - gpx_file = self.activity_data[row]["rcd_gpxfile"] - self.setValue("rcd_gpxfile", gpx_file, "%s") - #set duration - time = Date().time2second(self.activity_data[row]["rcd_time"]) #TODO Fix to use timeinseconds!! - self.setTime(time) #TODO Fix to use timeinseconds!! - #Set distance - self.setValue("rcd_distance",self.activity_data[row]["rcd_distance"], "%s") - #Set comments - buffer = self.rcd_comments.get_buffer() - start,end = buffer.get_bounds() - if "rcd_comments" not in self.activity_data[row]: - self.activity_data[row]["rcd_comments"] = "" - buffer.set_text(self.activity_data[row]["rcd_comments"]) - while gtk.events_pending(): # This allows the GUI to update - gtk.main_iteration() # before completion of this entire action - if self.activity_data[row]["complete"] is False: - #Haven't processed GPX file yet - #Blank values not yet known - self.setValue("rcd_date", "", "%s") - self.setValue("rcd_starttime", "", "%s") - self.setValue("rcd_average", "", "%s") - self.setValue("rcd_calories","", "%s") - self.setValue("rcd_beats", "", "%s") - self.setValue("rcd_upositive", "", "%s") - self.setValue("rcd_unegative", "", "%s") - self.setValue("rcd_maxvel", "", "%s") - self.rcd_maxpace.set_text("") - self.rcd_pace.set_text("") - self.setValue("rcd_maxbeats", "", "%s") - while gtk.events_pending(): # This allows the GUI to update - gtk.main_iteration() # before completion of this entire action - #Get some info from gpx file - self.update_activity_data(row, gpx_file, sport) - - self.setValue("rcd_date", self.activity_data[row]["rcd_date"], "%s") - self.setValue("rcd_starttime", self.activity_data[row]["rcd_starttime"], "%s") - self.setValue("rcd_average",self.activity_data[row]["rcd_average"]) - self.setValue("rcd_calories",self.activity_data[row]["rcd_calories"], "%s") - self.setValue("rcd_beats",self.activity_data[row]["rcd_beats"], "%s") - self.setValue("rcd_upositive",self.activity_data[row]["rcd_upositive"], "%s") - self.setValue("rcd_unegative",self.activity_data[row]["rcd_unegative"], "%s") - self.setValue("rcd_maxvel",self.activity_data[row]["rcd_maxvel"]) - self.rcd_maxpace.set_text(self.activity_data[row]["rcd_maxpace"]) - self.rcd_pace.set_text(self.activity_data[row]["rcd_pace"]) - self.setValue("rcd_maxbeats",self.activity_data[row]["rcd_maxbeats"], "%s") - self.rcd_title.set_text(self.activity_data[row]["rcd_title"]) - - - def on_rcd_title_changed(self, widget): - if self.mode == "multiple_activities" and self.active_row is not None: - self.activity_data[self.active_row]["rcd_title"] = self.rcd_title.get_text() - - def on_rcd_sport_changed(self, widget): - if self.mode == "multiple_activities" and self.active_row is not None: - sport = self.rcd_sport.get_active_text() - #Update sport in data store - self.activity_data[self.active_row]["rcd_sport"] = sport - #Update sport in treeview - self.store[self.active_row][4] = sport - - def on_rcd_distance_changed(self, widget): - if self.mode == "multiple_activities" and self.active_row is not None: - distance = self.rcd_distance.get_text() - #Update distance in data store - self.activity_data[self.active_row]["rcd_distance"] = distance - #Update distance in treeview - self.store[self.active_row][2] = distance - - def on_rcd_duration_value_changed(self, widget): - if self.mode == "multiple_activities" and self.active_row is not None: - hour = self.rcd_hour.get_value() - min = self.rcd_min.get_value() - sec = self.rcd_second.get_value() - #print hour, min, sec - #Update duration in data store - self.activity_data[self.active_row]["rcd_time"] = (hour, min, sec) - #Update duration in treeview - self.store[self.active_row][3] = "%d:%.2d:%.2d" % (int(hour), int(min), int(sec)) - - def on_rcd_date_changed(self, widget): - if self.mode == "multiple_activities" and self.active_row is not None: - #Update date in data store - self.activity_data[self.active_row]["rcd_date"] = self.rcd_date.get_text() - - def on_rcd_starttime_changed(self, widget): - if self.mode == "multiple_activities" and self.active_row is not None: - #Update start time in data store - self.activity_data[self.active_row]["rcd_starttime"] = self.rcd_starttime.get_text() - - def on_treeviewEntries_row_activated(self, treeview, event): - ''' - Callback to display details of different activity - ''' - #Check for edited data in previous row - if self.active_row is not None: - #Check for edited data in comments - buffer = self.rcd_comments.get_buffer() - start,end = buffer.get_bounds() - comments = buffer.get_text(start,end, True).replace("\"","'") - self.activity_data[self.active_row]["rcd_comments"] = comments - #Advanced tab items - self.activity_data[self.active_row]["rcd_maxpace"] = self.rcd_maxpace.get_text() - self.activity_data[self.active_row]["rcd_pace"] = self.rcd_pace.get_text() - self.activity_data[self.active_row]["rcd_upositive"] = self.rcd_upositive.get_text() - self.activity_data[self.active_row]["rcd_unegative"] = self.rcd_unegative.get_text() - self.activity_data[self.active_row]["rcd_maxbeats"] = self.rcd_maxbeats.get_text() - self.activity_data[self.active_row]["rcd_beats"] = self.rcd_beats.get_text() - self.activity_data[self.active_row]["rcd_calories"] = self.rcd_calories.get_text() - #Get row that was selected - x = int(event.x) - y = int(event.y) - time = event.time - pthinfo = treeview.get_path_at_pos(x, y) - if pthinfo is not None: - path, col, cellx, celly = pthinfo - treeview.grab_focus() - treeview.set_cursor(path, col, 0) - while gtk.events_pending(): # This allows the GUI to update - gtk.main_iteration() # before completion of this entire action - self.show_treeviewEntries_row(path[0]) - - def on_calcaverage_clicked(self,widget): - try: - hour = self.rcd_hour.get_value_as_int() - min = self.rcd_min.get_value_as_int() - sec = self.rcd_second.get_value_as_int() - time = sec + (min*60) + (hour*3600) - time_in_hour = time/3600.0 - distance = float(self.rcd_distance.get_text()) - average = distance/time_in_hour - self.rcd_average.set_text("%0.2f" %average) - except: - pass - - def on_calcpace_clicked(self,widget): - hour = self.rcd_hour.get_value_as_int() - min = self.rcd_min.get_value_as_int() - sec = self.rcd_second.get_value_as_int() - time = sec + (min*60) + (hour*3600) - if time<1: - return False - time_in_min = time/60.0 - distance = float(self.rcd_distance.get_text()) - if distance<1: - return False - #Calc Pace - average = time_in_min/distance - #Tranform pace to mm.ss - min = int(average) - per_min = average - min - sec = float(per_min) * 60 / 100 - dec_pace = min + sec - #Transform pace to mm:ss - pace = self.parent.pace_from_float(dec_pace) - self.rcd_pace.set_text(pace) - - def on_calccalories_clicked(self,widget): - sport = self.rcd_sport.get_active_text() - hour = self.rcd_hour.get_value_as_int() - min = self.rcd_min.get_value_as_int() - sec = self.rcd_second.get_value_as_int() - hour += min/60 + sec/60/60 - weight = float("0%s"%self.parent.configuration.getValue("pytraining","prf_weight")) - met = self.parent.getSportMet(sport) - extraweight = self.parent.getSportWeight(sport) - if met: - calories = met*(weight+extraweight)*hour - self.rcd_calories.set_text(str(calories)) + def update_activity_data(self, row, gpx_file, sport): + self.activity_data[row]["rcd_comments"] = "" + gpx_summary, laps = self.parent.summaryFromGPX(gpx_file, (sport,"")) + local_time = gpx_summary['date_time_local'] + start_date = local_time.strftime("%Y-%m-%d") + start_time = local_time.strftime("%H:%M:%S") + self.activity_data[row]["rcd_date"] = start_date + self.activity_data[row]["rcd_starttime"] = start_time + self.activity_data[row]["date_time_local"] = gpx_summary['date_time_local'] + self.activity_data[row]["date_time_utc"] = gpx_summary['date_time_utc'] + self.activity_data[row]["rcd_average"] = gpx_summary["rcd_average"] + self.activity_data[row]["rcd_calories"] = gpx_summary["rcd_calories"] + self.activity_data[row]["rcd_beats"] = gpx_summary["rcd_beats"] + self.activity_data[row]["rcd_upositive"] = gpx_summary["rcd_upositive"] + self.activity_data[row]["rcd_unegative"] = gpx_summary["rcd_unegative"] + self.activity_data[row]["rcd_maxvel"] = gpx_summary["rcd_maxvel"] + self.activity_data[row]["rcd_maxpace"] = gpx_summary["rcd_maxpace"] + self.activity_data[row]["rcd_pace"] = gpx_summary["rcd_pace"] + self.activity_data[row]["rcd_maxbeats"] = gpx_summary["rcd_maxbeats"] + self.activity_data[row]["rcd_title"] = "" + self.activity_data[row]["laps"] = laps + self.activity_data[row]["complete"] = True - def on_calcdistance_clicked(self,widget): - try: - hour = self.rcd_hour.get_value_as_int() - min = self.rcd_min.get_value_as_int() - sec = self.rcd_second.get_value_as_int() - time = sec + (min*60) + (hour*3600) - time_in_hour = time/3600.0 - average = float(self.rcd_average.get_text()) - distance = average*time_in_hour - self.set_distance(distance) - except: - pass - - def set_distance(self,distance): - self.rcd_distance.set_text("%0.2f" %distance) - - def set_maxspeed(self,vel): - self.rcd_maxvel.set_text("%0.2f" %vel) - - def set_maxhr(self,hr): - self.rcd_maxbeats.set_text("%0.2f" %hr) - - def set_recordtime (self,time_in_hour): - hour = int(time_in_hour) - min = int((time_in_hour-hour)*60) - sec = (((time_in_hour-hour)*60)-min)*60 - self.rcd_hour.set_value(hour) - self.rcd_min.set_value(min) - self.rcd_second.set_value(sec) + + def show_treeviewEntries_row(self, row): + ''' + Show details of treeview entry + TODO need to maintain any changes and display those.... + ''' + self.active_row = row + #Get details from stored data + #set sport + sport = self.activity_data[row]["rcd_sport"] + sportPosition = self.getSportPositionByName(sport) + if sportPosition is not None: + self.rcd_sport.set_active(sportPosition) + #Set gpx file name + gpx_file = self.activity_data[row]["rcd_gpxfile"] + self.setValue("rcd_gpxfile", gpx_file, "%s") + #set duration + time = Date().time2second(self.activity_data[row]["rcd_time"]) #TODO Fix to use timeinseconds!! + self.setTime(time) #TODO Fix to use timeinseconds!! + #Set distance + self.setValue("rcd_distance",self.activity_data[row]["rcd_distance"], "%s") + #Set comments + buffer = self.rcd_comments.get_buffer() + start,end = buffer.get_bounds() + if "rcd_comments" not in self.activity_data[row]: + self.activity_data[row]["rcd_comments"] = "" + buffer.set_text(self.activity_data[row]["rcd_comments"]) + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + if self.activity_data[row]["complete"] is False: + #Haven't processed GPX file yet + #Blank values not yet known + self.setValue("rcd_date", "", "%s") + self.setValue("rcd_starttime", "", "%s") + self.setValue("rcd_average", "", "%s") + self.setValue("rcd_calories","", "%s") + self.setValue("rcd_beats", "", "%s") + self.setValue("rcd_upositive", "", "%s") + self.setValue("rcd_unegative", "", "%s") + self.setValue("rcd_maxvel", "", "%s") + self.rcd_maxpace.set_text("") + self.rcd_pace.set_text("") + self.setValue("rcd_maxbeats", "", "%s") + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + #Get some info from gpx file + self.update_activity_data(row, gpx_file, sport) + + self.setValue("rcd_date", self.activity_data[row]["rcd_date"], "%s") + self.setValue("rcd_starttime", self.activity_data[row]["rcd_starttime"], "%s") + self.setValue("rcd_average",self.activity_data[row]["rcd_average"]) + self.setValue("rcd_calories",self.activity_data[row]["rcd_calories"], "%s") + self.setValue("rcd_beats",self.activity_data[row]["rcd_beats"], "%s") + self.setValue("rcd_upositive",self.activity_data[row]["rcd_upositive"], "%s") + self.setValue("rcd_unegative",self.activity_data[row]["rcd_unegative"], "%s") + self.setValue("rcd_maxvel",self.activity_data[row]["rcd_maxvel"]) + self.rcd_maxpace.set_text(self.activity_data[row]["rcd_maxpace"]) + self.rcd_pace.set_text(self.activity_data[row]["rcd_pace"]) + self.setValue("rcd_maxbeats",self.activity_data[row]["rcd_maxbeats"], "%s") + self.rcd_title.set_text(self.activity_data[row]["rcd_title"]) + + + def on_rcd_title_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + self.activity_data[self.active_row]["rcd_title"] = self.rcd_title.get_text() + + def on_rcd_sport_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + sport = self.rcd_sport.get_active_text() + #Update sport in data store + self.activity_data[self.active_row]["rcd_sport"] = sport + #Update sport in treeview + self.store[self.active_row][4] = sport + + def on_rcd_distance_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + distance = self.rcd_distance.get_text() + #Update distance in data store + self.activity_data[self.active_row]["rcd_distance"] = distance + #Update distance in treeview + self.store[self.active_row][2] = distance + + def on_rcd_duration_value_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + hour = self.rcd_hour.get_value() + min = self.rcd_min.get_value() + sec = self.rcd_second.get_value() + #print hour, min, sec + #Update duration in data store + self.activity_data[self.active_row]["rcd_time"] = (hour, min, sec) + #Update duration in treeview + self.store[self.active_row][3] = "%d:%.2d:%.2d" % (int(hour), int(min), int(sec)) + + def on_rcd_date_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + #Update date in data store + self.activity_data[self.active_row]["rcd_date"] = self.rcd_date.get_text() + + def on_rcd_starttime_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + #Update start time in data store + self.activity_data[self.active_row]["rcd_starttime"] = self.rcd_starttime.get_text() + + def on_treeviewEntries_row_activated(self, treeview, event): + ''' + Callback to display details of different activity + ''' + #Check for edited data in previous row + if self.active_row is not None: + #Check for edited data in comments + buffer = self.rcd_comments.get_buffer() + start,end = buffer.get_bounds() + comments = buffer.get_text(start,end, True).replace("\"","'") + self.activity_data[self.active_row]["rcd_comments"] = comments + #Advanced tab items + self.activity_data[self.active_row]["rcd_maxpace"] = self.rcd_maxpace.get_text() + self.activity_data[self.active_row]["rcd_pace"] = self.rcd_pace.get_text() + self.activity_data[self.active_row]["rcd_upositive"] = self.rcd_upositive.get_text() + self.activity_data[self.active_row]["rcd_unegative"] = self.rcd_unegative.get_text() + self.activity_data[self.active_row]["rcd_maxbeats"] = self.rcd_maxbeats.get_text() + self.activity_data[self.active_row]["rcd_beats"] = self.rcd_beats.get_text() + self.activity_data[self.active_row]["rcd_calories"] = self.rcd_calories.get_text() + #Get row that was selected + x = int(event.x) + y = int(event.y) + time = event.time + pthinfo = treeview.get_path_at_pos(x, y) + if pthinfo is not None: + path, col, cellx, celly = pthinfo + treeview.grab_focus() + treeview.set_cursor(path, col, 0) + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + self.show_treeviewEntries_row(path[0]) + + def on_calcaverage_clicked(self,widget): + try: + hour = self.rcd_hour.get_value_as_int() + min = self.rcd_min.get_value_as_int() + sec = self.rcd_second.get_value_as_int() + time = sec + (min*60) + (hour*3600) + time_in_hour = time/3600.0 + distance = float(self.rcd_distance.get_text()) + average = distance/time_in_hour + self.rcd_average.set_text("%0.2f" %average) + except: + pass + + def on_calcpace_clicked(self,widget): + hour = self.rcd_hour.get_value_as_int() + min = self.rcd_min.get_value_as_int() + sec = self.rcd_second.get_value_as_int() + time = sec + (min*60) + (hour*3600) + if time<1: + return False + time_in_min = time/60.0 + distance = float(self.rcd_distance.get_text()) + if distance<1: + return False + #Calc Pace + average = time_in_min/distance + #Tranform pace to mm.ss + min = int(average) + per_min = average - min + sec = float(per_min) * 60 / 100 + dec_pace = min + sec + #Transform pace to mm:ss + pace = self.parent.pace_from_float(dec_pace) + self.rcd_pace.set_text(pace) + + def on_calccalories_clicked(self,widget): + sport = self.rcd_sport.get_active_text() + hour = self.rcd_hour.get_value_as_int() + min = self.rcd_min.get_value_as_int() + sec = self.rcd_second.get_value_as_int() + hour += min/60 + sec/60/60 + weight = self.pytrainer_main.profile.getValue("pytraining","prf_weight") + if weight is None or weight == "" or weight == "None": + weight = 0 + else: + weight = float(weight) + met = self.parent.getSportMet(sport) + extraweight = self.parent.getSportWeight(sport) + if extraweight is None or extraweight == "" or extraweight == "None": + extraweight = 0 + else: + extraweight = float(extraweight) + if met: + calories = met*(weight+extraweight)*hour + self.rcd_calories.set_text(str(calories)) - def on_selectfile_clicked(self,widget): - self.filechooser = FileChooser(self.data_path,self,"set_gpxfile","open") - self.filechooser.run() + def on_calcdistance_clicked(self,widget): + try: + hour = self.rcd_hour.get_value_as_int() + min = self.rcd_min.get_value_as_int() + sec = self.rcd_second.get_value_as_int() + time = sec + (min*60) + (hour*3600) + time_in_hour = time/3600.0 + average = float(self.rcd_average.get_text()) + distance = average*time_in_hour + self.set_distance(distance) + except: + pass + + def set_distance(self,distance): + self.rcd_distance.set_text("%0.2f" %distance) + + def set_maxspeed(self,vel): + self.rcd_maxvel.set_text("%0.2f" %vel) + + def set_maxhr(self,hr): + self.rcd_maxbeats.set_text("%0.2f" %hr) + + def set_recordtime (self,time_in_hour): + hour = int(time_in_hour) + min = int((time_in_hour-hour)*60) + sec = (((time_in_hour-hour)*60)-min)*60 + self.rcd_hour.set_value(hour) + self.rcd_min.set_value(min) + self.rcd_second.set_value(sec) - def set_gpxfile(self): - namefile = self.filechooser.filename - self.rcd_gpxfile.set_text(namefile) + def on_selectfile_clicked(self,widget): + logging.debug(">>") + #self.filechooser = FileChooser(self.data_path,self,"set_gpxfile","open") + #self.filechooser.run() + from pytrainer.gui.dialogs import fileChooserDialog + selectedFile = fileChooserDialog(title="Choose a Google Earth file (.kml) to import", multiple=False).getFiles() + if selectedFile is not None: + self.rcd_gpxfile.set_text(selectedFile[0]) + logging.debug("<<") - def on_calculatevalues_clicked(self,widget): - gpxfile = self.rcd_gpxfile.get_text() - if os.path.isfile(gpxfile): - self.frameGeneral.set_sensitive(0) - self.frameVelocity.set_sensitive(0) - self.parent.actualize_fromgpx(gpxfile) + def set_gpxfile(self): + logging.debug(">>") + #namefile = self.filechooser.filename + #self.rcd_gpxfile.set_text(namefile) + logging.debug("<<") + def on_calculatevalues_clicked(self,widget): + gpxfile = self.rcd_gpxfile.get_text() + if os.path.isfile(gpxfile): + self.frameGeneral.set_sensitive(0) + self.frameVelocity.set_sensitive(0) + self.parent.actualize_fromgpx(gpxfile) + Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-10-04 04:50:08 UTC (rev 642) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-10-05 00:14:54 UTC (rev 643) @@ -58,6 +58,7 @@ date_time_local - (string) date and time of activity in local timezone date_time_utc - (string) date and time of activity in UTC timezone date_time - (datetime) date and time of activity in local timezone + starttime - (string) distance - (float) activity distance average - (float) average speed of activity upositive - (float) height climbed during activity @@ -91,6 +92,9 @@ self.distance_data = {} self.time_data = {} self.pace_limit = None + self.starttime = None + #self.upositive = 0 + #self.unegative = 0 if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": self.us_system = True else: @@ -168,9 +172,11 @@ self.date_time_utc = dict['date_time_utc'] if self.date_time_local is not None: #Have a local time stored in DB self.date_time = dateutil.parser.parse(self.date_time_local) + self.starttime = self.date_time.strftime("%X") else: #No local time in DB tmpDateTime = dateutil.parser.parse(self.date_time_utc) self.date_time = tmpDateTime.astimezone(tzlocal()) #datetime with localtime offset (using value from OS) + self.starttime = self.date_time.strftime("%X") #Sort data that changes for the US etc if self.us_system: self.distance = km2miles(self._float(dict['distance'])) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-04 04:50:08 UTC (rev 642) +++ pytrainer/trunk/pytrainer/main.py 2010-10-05 00:14:54 UTC (rev 643) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#640" + self.version ="1.7.2_svn#643" self.DB_version = 4 #Process command line options self.startup_options = self.get_options() @@ -407,7 +407,7 @@ list_sport = self.profile.getSportList() if date == None: date = self.date.getDate() - self.record.newRecord(list_sport, date, title, distance, time, upositive, unegative, bpm, calories, comment) + self.record.newRecord(list_sport, date, title, distance, time, upositive, unegative, bpm, calories, comment) self.refreshListRecords() logging.debug('<<') Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-10-04 04:50:08 UTC (rev 642) +++ pytrainer/trunk/pytrainer/record.py 2010-10-05 00:14:54 UTC (rev 643) @@ -56,6 +56,10 @@ def editRecord(self,id_record,list_sport): logging.debug('>>') + activity = self.pytrainer_main.activitypool.get_activity(id_record) + self.recordwindow = WindowRecord(self.data_path, list_sport, self, None, windowTitle=_("Edit Entry")) + self.recordwindow.setValuesFromActivity(activity) + ''' record = self.pytrainer_main.ddbb.select("records", "id_record, date, sport, distance, time, beats, average, calories, comments, gpslog, title, upositive, unegative, maxspeed, maxpace, pace, maxbeats, date_time_utc, date_time_local", "id_record=\"%s\"" %id_record) logging.debug('retrieving data from DB: '+str(record)) gpxfile = self.pytrainer_main.profile.gpxdir+"/%d.gpx"%int(id_record) @@ -67,6 +71,7 @@ self.recordwindow.frameVelocity.set_sensitive(0) #Greying out options to indicate this to user logging.debug('sending record info to window') self.recordwindow.setValues(record[0]) + ''' logging.debug('launching window') self.recordwindow.run() logging.debug('<<') @@ -106,9 +111,9 @@ self.parseFloatRecord(list_options["rcd_upositive"]), self.parseFloatRecord(list_options["rcd_unegative"]), self.parseFloatRecord(list_options["rcd_maxvel"]), - self.parseFloatRecord(list_options["rcd_maxpace"]), + self.pace_to_float(list_options["rcd_maxpace"]), self.pace_to_float(list_options["rcd_pace"]), - self.pace_to_float(list_options["rcd_maxbeats"]) + self.parseFloatRecord(list_options["rcd_maxbeats"]) ) logging.debug('<<') return cells,values @@ -190,8 +195,11 @@ if os.path.isfile(gpxOrig): gpxDest = self.pytrainer_main.profile.gpxdir gpxNew = gpxDest+"/%d.gpx"%id_record - shutil.move(gpxOrig, gpxNew) - logging.debug('Moving '+gpxOrig+' to '+gpxNew) + #Leave original file in place... + #shutil.move(gpxOrig, gpxNew) + #logging.debug('Moving '+gpxOrig+' to '+gpxNew) + shutil.copy(gpxOrig, gpxNew) + logging.debug('Copying '+gpxOrig+' to '+gpxNew) #self.parent.refreshListRecords() logging.debug('<<') return self.pytrainer_main.ddbb.lastRecord("records") Added: pytrainer/trunk/schemas/pytrainer-0.1.xsd =================================================================== --- pytrainer/trunk/schemas/pytrainer-0.1.xsd (rev 0) +++ pytrainer/trunk/schemas/pytrainer-0.1.xsd 2010-10-05 00:14:54 UTC (rev 643) @@ -0,0 +1,56 @@ +<?xml version = "1.0" encoding = "UTF-8"?> +<xsd:schema + xmlns="http://sourceforge.net.project/pytrainer/GPX/0/1" schemaLocation="http://sourceforge.net/apps/trac/pytrainer/raw-attachment/wiki/SampleGPX/pytrainer-0.1.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:gpx="http://www.topografix.com/GPX/1/1" + targetNamespace="http://sourceforge.net.project/pytrainer/GPX/0/1" + elementFormDefault="qualified"> + <xsd:annotation> + <xsd:documentation> + The pytrainer schema is an mix-in schema for use with the GPX 1.1 schema from Topografix. It holds data exclusively processed by pytrainer. + </xsd:documentation> + </xsd:annotation> + + <xsd:import namespace="http://www.topografix.com/GPX/1/1" + schemaLocation="http://www.topografix.com/GPX/1/1/gpx.xsd"/> + <xsd:element name="ele" type="eleType"> + <xsd:annotation> + <xsd:documentation> + Corrected elevation values. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:complexType name="eleType"> + <xsd:simpleContent> + <xsd:extension base="xsd:decimal"> + <xsd:attribute name="method" type="xsd:string" use="required"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + <xsd:element name="method" type="methodType"> + <xsd:annotation> + <xsd:documentation> + Method used for correction or manipulation. + </xsd:documentation> + </xsd:annotation> + </xsd:element> + + <xsd:complexType name="methodType"> + <xsd:all> + <xsd:element name="description" type="xsd:string"/> + </xsd:all> + <xsd:attribute name="name" type="xsd:string" use="required"/> + <xsd:attribute name="type" type="methtype" use="required"/> + <xsd:attribute name="version" type="xsd:string"/> + <xsd:attribute name="date" type="xsd:dateTime"/> + </xsd:complexType> + + <xsd:simpleType name="methtype"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="ele"/> + <!--<xsd:enumeration value="hr"/>--> + </xsd:restriction> + </xsd:simpleType> + +</xsd:schema> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-10-04 04:50:14
|
Revision: 642 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=642&view=rev Author: jblance Date: 2010-10-04 04:50:08 +0000 (Mon, 04 Oct 2010) Log Message: ----------- Make elevation show by default in newgraph code Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/activity.py Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-10-04 04:31:23 UTC (rev 641) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-10-04 04:50:08 UTC (rev 642) @@ -68,7 +68,7 @@ has_data - (bool) true if instance has data populated x_axis - (string) distance or time, determines what will be graphed on x axis show_laps - (bool) display laps on graphs - lap_distance - (graphdata) + lap_distance - (graphdata) lap_time - (graphdata) pace_limit - (int) maximum pace that is valid for this activity ''' @@ -201,7 +201,7 @@ laps = self._get_laps_from_gpx() self.laps = laps logging.debug("<<") - + def _generate_per_lap_graphs(self): '''Build lap based graphs...''' logging.debug(">>") @@ -280,6 +280,7 @@ ylabel="%s (%s)" % (_('Elevation'), self.height_unit) self.distance_data['elevation'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) self.distance_data['elevation'].set_color('#ff0000', '#ff0000') + self.distance_data['elevation'].show_on_y1 = True #Make graph show elevation vs distance by default xlabel=_("Time (seconds)") self.time_data['elevation'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) self.time_data['elevation'].set_color('#ff0000', '#ff0000') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-10-04 04:31:30
|
Revision: 641 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=641&view=rev Author: jblance Date: 2010-10-04 04:31:23 +0000 (Mon, 04 Oct 2010) Log Message: ----------- Update garmintools schema to allow 0 calories, fix error in checkDB code Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/ddbb.py pytrainer/trunk/schemas/garmintools.xsd Modified: pytrainer/trunk/pytrainer/lib/ddbb.py =================================================================== --- pytrainer/trunk/pytrainer/lib/ddbb.py 2010-10-04 00:59:52 UTC (rev 640) +++ pytrainer/trunk/pytrainer/lib/ddbb.py 2010-10-04 04:31:23 UTC (rev 641) @@ -28,20 +28,20 @@ def __init__(self, configuration, pytrainer_main=None): self.pytrainer_main = pytrainer_main self.configuration = configuration - self.ddbb_type = configuration.getValue("pytraining","prf_ddbb") + self.ddbb_type = self.configuration.getValue("pytraining","prf_ddbb") if self.ddbb_type == "mysql": #TODO no longer supported? from mysqlUtils import Sql else: from sqliteUtils import Sql - self.confdir = configuration.confdir + self.confdir = self.configuration.confdir self.ddbb_path = "%s/pytrainer.ddbb" %self.confdir - ddbb_host = configuration.getValue("pytraining","prf_ddbbhost") - ddbb = configuration.getValue("pytraining","prf_ddbbname") - ddbb_user = configuration.getValue("pytraining","prf_ddbbuser") - ddbb_pass = configuration.getValue("pytraining","prf_ddbbpass") - self.ddbbObject = Sql(ddbb_host,ddbb,ddbb_user,ddbb_pass,configuration) + ddbb_host = self.configuration.getValue("pytraining","prf_ddbbhost") + ddbb = self.configuration.getValue("pytraining","prf_ddbbname") + ddbb_user = self.configuration.getValue("pytraining","prf_ddbbuser") + ddbb_pass = self.configuration.getValue("pytraining","prf_ddbbpass") + self.ddbbObject = Sql(ddbb_host,ddbb,ddbb_user,ddbb_pass,self.configuration) def connect(self): #si devolvemos 1 ha ido todo con exito : return 1 if all successful @@ -220,7 +220,7 @@ logging.debug("Found %d records in DB without date_time_local field populated" % (len(listOfRecords) ) ) for record in listOfRecords: try: - gpxfile = configuration.gpxdir+"/%s.gpx"%(record[0]) + gpxfile = self.configuration.gpxdir+"/%s.gpx"%(record[0]) dateFromUTC = Date().getDateTime(record[2]) if os.path.isfile(gpxfile) : #GPX file exists for this record - probably not a manual record date_time_local = str(dateFromUTC[1]) Modified: pytrainer/trunk/schemas/garmintools.xsd =================================================================== --- pytrainer/trunk/schemas/garmintools.xsd 2010-10-04 00:59:52 UTC (rev 640) +++ pytrainer/trunk/schemas/garmintools.xsd 2010-10-04 04:31:23 UTC (rev 641) @@ -27,7 +27,7 @@ <xsd:element name="begin_pos" type="position_type" minOccurs="0" /> <xsd:element name="end_pos" type="position_type" minOccurs="0" /> <xsd:element name="max_speed" type="xsd:float" minOccurs="0" /> - <xsd:element name="calories" type="xsd:positiveInteger" minOccurs="0" /> + <xsd:element name="calories" type="xsd:integer" minOccurs="0" /> <xsd:element name="avg_hr" type="xsd:positiveInteger" minOccurs="0" /> <xsd:element name="max_hr" type="xsd:positiveInteger" minOccurs="0" /> <xsd:element name="intensity" type="xsd:string" minOccurs="0" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-10-04 00:59:58
|
Revision: 640 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=640&view=rev Author: jblance Date: 2010-10-04 00:59:52 +0000 (Mon, 04 Oct 2010) Log Message: ----------- Second axes options enabled in newgraph code Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/lib/graphdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-01 04:00:02 UTC (rev 639) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-04 00:59:52 UTC (rev 640) @@ -31,15 +31,19 @@ self.parent = parent self.pytrainer_main = pytrainer_main #self.NEARLY_ZERO = 0.0000000000000000000001 + self.ax1 = None + self.ax2 = None logging.debug('<<') - def draw(self, datalist = None, box = None, figure = None, title = None): + def draw(self, datalist = None, box = None, figure = None, title = None, y2 = False): ''' Draw a graph using supplied information into supplied gtk.box datalist = populated graphdata class (required) box = gtk.box object (required) figure = matplotlib figure (optional) if supplied will add graph to this figure + title = + y2 = return = figure ''' @@ -51,6 +55,9 @@ if figure is None: #No figure, so create figure figure = plt.figure() + self.ax1 = plt.axes() + #Reset second axis + self.ax2 = None #Remove any existing plots for child in box.get_children(): logging.debug('Removing box child: '+str(child)) @@ -59,6 +66,9 @@ if datalist is None: logging.debug("drawPlot called with no data") return + + if y2 and self.ax2 is None: + self.ax2 = plt.twinx() #Create canvas @@ -73,27 +83,38 @@ #Removed as now in legend #plt.ylabel(datalist.ylabel) - #TODO #Determine graph type.... #print "Got graphtype: %s" % datalist.graphType if datalist.graphType == "plot": #Plot data - plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor, label=datalist.ylabel ) + if not y2: + #plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor, label=datalist.ylabel ) + self.ax1.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor, label=datalist.ylabel ) + else: + self.ax2.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.y2linecolor, label=datalist.ylabel ) elif datalist.graphType == "bar": - plt.bar(datalist.x_values, datalist.y_values, datalist.bar_widths, datalist.bar_bottoms, color=datalist.linecolor, label=datalist.ylabel) - #return figure + if not y2: + self.ax1.bar(datalist.x_values, datalist.y_values, datalist.bar_widths, datalist.bar_bottoms, color=datalist.linecolor, label=datalist.ylabel, alpha=0.5) + else: + self.ax2.bar(datalist.x_values, datalist.y_values, datalist.bar_widths, datalist.bar_bottoms, color=datalist.y2linecolor, label=datalist.ylabel, alpha=0.5) elif datalist.graphType == "vspan": i = 0 while i < len(datalist.x_values): #print datalist.x_values[i] , datalist.bar_widths[i] - plt.axvspan(datalist.x_values[i], datalist.x_values[i]+datalist.bar_widths[i], alpha=0.15, facecolor=datalist.linecolor) + if not y2: + self.ax1.axvspan(datalist.x_values[i], datalist.x_values[i]+datalist.bar_widths[i], alpha=0.15, facecolor=datalist.linecolor) + else: + self.ax2.axvspan(datalist.x_values[i], datalist.x_values[i]+datalist.bar_widths[i], alpha=0.15, facecolor=datalist.y2linecolor) i += 1 else: print "Unknown/unimplemented graph type: %s" % datalist.graphType return figure #Set axis limits #plt.axis([datalist.min_x_value, datalist.max_x_value, datalist.min_y_value, datalist.max_y_value]) - plt.legend(loc=0) + if self.ax1 is not None: + self.ax1.legend(loc = 'upper left', bbox_to_anchor = (0, 1)) + if self.ax2 is not None: + self.ax2.legend(loc = 'upper right', bbox_to_anchor = (1, 1)) #axis.set_xlim(0, data.max_x_value) #axis.set_ylim(0, data.max_y_value) @@ -212,7 +233,8 @@ #TODO Check that datalist is of type dict (and contains has correct items) figure = None datalist = [] - count = 0 + y1count = 0 + y2count = 0 if activity.x_axis == "distance": if activity.title is None or activity.title == "": @@ -223,8 +245,11 @@ #Loop through data items and graph the selected ones for item in activity.distance_data: if activity.distance_data[item].show_on_y1: - count += 1 + y1count += 1 figure = self.draw(activity.distance_data[item], box=box, figure=figure, title=_title) + if activity.distance_data[item].show_on_y2: + y2count += 1 + figure = self.draw(activity.distance_data[item], box=box, figure=figure, title=_title, y2=True) #Display lap divisions if required if activity.show_laps: figure = self.draw(activity.lap_distance, box=box, figure=figure) @@ -237,12 +262,20 @@ _title = "%s: %s of %s on %s" % (activity.title, _time, activity.sport_name, activity.date) for item in activity.time_data: if activity.time_data[item].show_on_y1: - count += 1 + y1count += 1 figure = self.draw(activity.time_data[item], box=box, figure=figure, title=_title) + if activity.time_data[item].show_on_y2: + y2count += 1 + figure = self.draw(activity.time_data[item], box=box, figure=figure, title=_title, y2=True) #Display lap divisions if required if activity.show_laps: figure = self.draw(activity.lap_time, box=box, figure=figure) - if count == 0: + + #Sort out graph errors... + if y1count == 0 and y2count == 0: logging.debug("No items to graph.. Removing graph") figure = self.draw(None, box=box, figure=figure) + elif y1count == 0: + logging.debug("No items on y1 axis... ") + #TODO Sort logging.debug('<<') Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-01 04:00:02 UTC (rev 639) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-04 00:59:52 UTC (rev 640) @@ -366,9 +366,9 @@ y2button.connect("toggled", self.on_y2change, y2box, graphdata, activity) y2box.attach(y2button, 0, 1, row, row+1, xoptions=gtk.EXPAND|gtk.FILL) y2color = gtk.ColorButton() - _color = gtk.gdk.color_parse(data[graphdata].linecolor) + _color = gtk.gdk.color_parse(data[graphdata].y2linecolor) y2color.set_color(_color) - y2color.connect("color-set", self.on_y1colorchange, y2box, graphdata, activity) + y2color.connect("color-set", self.on_y2colorchange, y2box, graphdata, activity) #Attach to container y2box.attach(y2color, 1, 2, row, row+1) row += 1 @@ -1066,6 +1066,16 @@ #Replot the activity self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + def on_y2colorchange(self, widget, box, graphdata, activity): + '''Hander for changes to y2 color selection''' + logging.debug("Setting %s to color %s" % (graphdata, widget.get_color() ) ) + if activity.x_axis == "distance": + activity.distance_data[graphdata].set_color(None, str(widget.get_color())) + elif activity.x_axis == "time": + activity.time_data[graphdata].set_color(None, str(widget.get_color())) + #Replot the activity + self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + def on_y1change(self, widget, box, graphdata, activity): '''Hander for changes to y1 selection''' logging.debug("Y1 selection toggled: %s" % graphdata) @@ -1086,11 +1096,21 @@ def on_y2change(self, widget, box, graphdata, activity): '''Hander for changes to y2 selection''' - print "Y2 selected: ", - #for child in box.get_children(): - # if child.get_active(): - # print child.get_label(), - #print + logging.debug("Y2 selection toggled: %s" % graphdata) + #Loop through all options at set data correctly + for child in box.get_children(): + if activity.x_axis == "distance": + for item in activity.distance_data: + if activity.distance_data[item].title == child.get_label(): + logging.debug( "Setting %s to %s" % (item, str(child.get_active()) ) ) + activity.distance_data[item].show_on_y2 = child.get_active() + elif activity.x_axis == "time": + for item in activity.time_data: + if activity.time_data[item].title == child.get_label(): + logging.debug( "Setting %s to %s" % (item, str(child.get_active()) ) ) + activity.time_data[item].show_on_y2 = child.get_active() + #Replot the activity + self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) def on_athleteTreeView_button_press_event(self, treeview, event): x = int(event.x) Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-10-01 04:00:02 UTC (rev 639) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-10-04 00:59:52 UTC (rev 640) @@ -211,21 +211,21 @@ return #Lap columns self.lap_distance = GraphData() - self.lap_distance.set_color('#CCFF00') + self.lap_distance.set_color('#CCFF00', '#CCFF00') self.lap_distance.graphType = "vspan" self.lap_time = GraphData() - self.lap_time.set_color('#CCFF00') + self.lap_time.set_color('#CCFF00', '#CCFF00') self.lap_time.graphType = "vspan" #Pace title=_("Pace by Lap") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Pace'), self.pace_unit) self.distance_data['pace_lap'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - self.distance_data['pace_lap'].set_color('#99CCFF') + self.distance_data['pace_lap'].set_color('#99CCFF', '#99CCFF') self.distance_data['pace_lap'].graphType = "bar" xlabel=_("Time (seconds)") self.time_data['pace_lap'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - self.time_data['pace_lap'].set_color('#99CCFF') + self.time_data['pace_lap'].set_color('#99CCFF', '#99CCFF') self.time_data['pace_lap'].graphType = "bar" for lap in self.laps: time = float( lap['elapsed_time'].decode('utf-8') ) # time in sql is a unicode string @@ -279,46 +279,46 @@ xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Elevation'), self.height_unit) self.distance_data['elevation'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - self.distance_data['elevation'].set_color('#ff0000') + self.distance_data['elevation'].set_color('#ff0000', '#ff0000') xlabel=_("Time (seconds)") self.time_data['elevation'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) - self.time_data['elevation'].set_color('#ff0000') + self.time_data['elevation'].set_color('#ff0000', '#ff0000') #Speed title=_("Speed") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Speed'), self.speed_unit) self.distance_data['speed'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - self.distance_data['speed'].set_color('#000000') + self.distance_data['speed'].set_color('#000000', '#000000') xlabel=_("Time (seconds)") self.time_data['speed'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) - self.time_data['speed'].set_color('#000000') + self.time_data['speed'].set_color('#000000', '#000000') #Pace title=_("Pace") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Pace'), self.pace_unit) self.distance_data['pace'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - self.distance_data['pace'].set_color('#0000ff') + self.distance_data['pace'].set_color('#0000ff', '#0000ff') xlabel=_("Time (seconds)") self.time_data['pace'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) - self.time_data['pace'].set_color('#0000ff') + self.time_data['pace'].set_color('#0000ff', '#0000ff') #Heartrate title=_("Heart Rate") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Heart Rate'), _('bpm')) self.distance_data['hr'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - self.distance_data['hr'].set_color('#00ff00') + self.distance_data['hr'].set_color('#00ff00', '#00ff00') xlabel=_("Time (seconds)") self.time_data['hr'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) - self.time_data['hr'].set_color('#00ff00') + self.time_data['hr'].set_color('#00ff00', '#00ff00') #Cadence title=_("Cadence") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Cadence'), _('rpm')) self.distance_data['cadence'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - self.distance_data['cadence'].set_color('#cc00ff') + self.distance_data['cadence'].set_color('#cc00ff', '#cc00ff') xlabel=_("Time (seconds)") self.time_data['cadence'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) - self.time_data['cadence'].set_color('#cc00ff') + self.time_data['cadence'].set_color('#cc00ff', '#cc00ff') for track in self.tracklist: try: pace = 60/track['velocity'] Modified: pytrainer/trunk/pytrainer/lib/graphdata.py =================================================================== --- pytrainer/trunk/pytrainer/lib/graphdata.py 2010-10-01 04:00:02 UTC (rev 639) +++ pytrainer/trunk/pytrainer/lib/graphdata.py 2010-10-04 00:59:52 UTC (rev 640) @@ -34,12 +34,14 @@ self.y_values = [] self.linewidth = 1 self.linecolor = '#ff0000' + self.y2linecolor = '#ff0000' self.max_x_value = None self.min_x_value = None self.max_y_value = None self.min_y_value = None self.graphType = "plot" self.show_on_y1 = False + self.show_on_y2 = False logging.debug('<<') def addBars(self, x=None, y=None): @@ -78,21 +80,35 @@ if self.min_y_value is None or y < self.min_y_value: self.min_y_value = y - def set_color(self, color): - ''' - Helper function to set the line color - need as some gtk.gdk color can be invalid for matplotlib + def get_color(self, color): ''' + + ''' + if color is None: + return None try: #Generate 13 digit color string from supplied color col = gtk.gdk.color_parse(color).to_string() except ValueError: logging.debug("Unable to parse color from '%s'" % color) - return + return None + #Create matplotlib color string _color = "#%s%s%s" % (col[1:3], col[5:7], col[9:11]) - logging.debug("%s color saved as: %s" % (color, _color)) - self.linecolor = _color + #logging.debug("%s color saved as: %s" % (color, _color)) + return _color + + def set_color(self, y1color, y2color = None): + ''' + Helper function to set the line color + need as some gtk.gdk color can be invalid for matplotlib + ''' + _color = self.get_color(y1color) + _color2 = self.get_color(y2color) + if _color is not None: + self.linecolor = _color + if _color2 is not None: + self.y2linecolor = _color2 def __len__(self): if self.x_values is None: @@ -108,6 +124,7 @@ linecolor: %s graphType: %s show on y1: %s +show on y2: %s x min max: %s %s y min max: %s %s x values: %s @@ -118,6 +135,7 @@ self.linecolor, self.graphType, str(self.show_on_y1), + str(self.show_on_y2), str(self.min_x_value), str(self.max_x_value), str(self.min_y_value), str(self.max_y_value), str(self.x_values), Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-01 04:00:02 UTC (rev 639) +++ pytrainer/trunk/pytrainer/main.py 2010-10-04 00:59:52 UTC (rev 640) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#638" + self.version ="1.7.2_svn#640" self.DB_version = 4 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-10-01 04:00:09
|
Revision: 639 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=639&view=rev Author: jblance Date: 2010-10-01 04:00:02 +0000 (Fri, 01 Oct 2010) Log Message: ----------- More changes to new graphing approach Modified Paths: -------------- pytrainer/trunk/glade/pytrainer.glade pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/activity.py Modified: pytrainer/trunk/glade/pytrainer.glade =================================================================== --- pytrainer/trunk/glade/pytrainer.glade 2010-09-30 22:13:29 UTC (rev 638) +++ pytrainer/trunk/glade/pytrainer.glade 2010-10-01 04:00:02 UTC (rev 639) @@ -1198,6 +1198,9 @@ <child> <placeholder/> </child> + <child> + <placeholder/> + </child> </widget> <packing> <property name="expand">False</property> Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-09-30 22:13:29 UTC (rev 638) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-01 04:00:02 UTC (rev 639) @@ -66,8 +66,10 @@ canvas.show() #Display title etc - plt.xlabel(datalist.xlabel) - plt.title(title) + if datalist.xlabel is not None: + plt.xlabel(datalist.xlabel) + if title is not None: + plt.title(title) #Removed as now in legend #plt.ylabel(datalist.ylabel) @@ -80,6 +82,12 @@ elif datalist.graphType == "bar": plt.bar(datalist.x_values, datalist.y_values, datalist.bar_widths, datalist.bar_bottoms, color=datalist.linecolor, label=datalist.ylabel) #return figure + elif datalist.graphType == "vspan": + i = 0 + while i < len(datalist.x_values): + #print datalist.x_values[i] , datalist.bar_widths[i] + plt.axvspan(datalist.x_values[i], datalist.x_values[i]+datalist.bar_widths[i], alpha=0.15, facecolor=datalist.linecolor) + i += 1 else: print "Unknown/unimplemented graph type: %s" % datalist.graphType return figure @@ -205,6 +213,7 @@ figure = None datalist = [] count = 0 + if activity.x_axis == "distance": if activity.title is None or activity.title == "": _title = "%s%s of %s on %s" % (str(activity.distance), activity.distance_unit, activity.sport_name, activity.date) @@ -212,11 +221,13 @@ _title = "%s: %s%s of %s on %s" % (activity.title, str(activity.distance), activity.distance_unit, activity.sport_name, activity.date) #Loop through data items and graph the selected ones - #TODO sort for x = time.... for item in activity.distance_data: if activity.distance_data[item].show_on_y1: count += 1 figure = self.draw(activity.distance_data[item], box=box, figure=figure, title=_title) + #Display lap divisions if required + if activity.show_laps: + figure = self.draw(activity.lap_distance, box=box, figure=figure) elif activity.x_axis == "time": _time = "%d:%02d:%02d" % (activity.time_tuple) @@ -228,6 +239,9 @@ if activity.time_data[item].show_on_y1: count += 1 figure = self.draw(activity.time_data[item], box=box, figure=figure, title=_title) + #Display lap divisions if required + if activity.show_laps: + figure = self.draw(activity.lap_time, box=box, figure=figure) if count == 0: logging.debug("No items to graph.. Removing graph") figure = self.draw(None, box=box, figure=figure) Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-30 22:13:29 UTC (rev 638) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-01 04:00:02 UTC (rev 639) @@ -311,18 +311,26 @@ y2Frame = gtk.Frame(label="Show on Y2 Axis") xvbox = gtk.VBox() y1box = gtk.Table() - y2vbox = gtk.VBox() + y2box = gtk.Table() #Populate X axis data - xdistancebutton = gtk.RadioButton(label="Distance") - xtimebutton = gtk.RadioButton(group=xdistancebutton, label="Time") + #Create x axis items + xdistancebutton = gtk.RadioButton(label=_("Distance")) + xtimebutton = gtk.RadioButton(group=xdistancebutton, label=_("Time")) + xlapsbutton = gtk.CheckButton(label=_("Laps")) + #Set state of buttons if activity.x_axis == "distance": xdistancebutton.set_active(True) elif activity.x_axis == "time": xtimebutton.set_active(True) + xlapsbutton.set_active(activity.show_laps) + #Connect handlers to buttons xdistancebutton.connect("toggled", self.on_xaxischange, "distance", activity) + xtimebutton.connect("toggled", self.on_xaxischange, "time", activity) + xlapsbutton.connect("toggled", self.on_xlapschange, activity) + #Add buttons to frame xvbox.add(xdistancebutton) - xtimebutton.connect("toggled", self.on_xaxischange, "time", activity) xvbox.add(xtimebutton) + xvbox.add(xlapsbutton) xFrame.add(xvbox) row = 0 @@ -355,19 +363,24 @@ #Second Y axis y2button = gtk.CheckButton(label=data[graphdata].title) - y2button.connect("toggled", self.on_y2change, y2vbox) - y2vbox.add(y2button) - + y2button.connect("toggled", self.on_y2change, y2box, graphdata, activity) + y2box.attach(y2button, 0, 1, row, row+1, xoptions=gtk.EXPAND|gtk.FILL) + y2color = gtk.ColorButton() + _color = gtk.gdk.color_parse(data[graphdata].linecolor) + y2color.set_color(_color) + y2color.connect("color-set", self.on_y1colorchange, y2box, graphdata, activity) + #Attach to container + y2box.attach(y2color, 1, 2, row, row+1) row += 1 y1Frame.add(y1box) - y2Frame.add(y2vbox) - self.graph_data_hbox.pack_start(xFrame, expand=False, fill=True, padding=0) + y2Frame.add(y2box) + self.graph_data_hbox.pack_start(xFrame, expand=False, fill=False, padding=0) self.graph_data_hbox.pack_start(y1Frame, expand=False, fill=True, padding=0) self.graph_data_hbox.pack_start(y2Frame, expand=False, fill=True, padding=0) + #expandbutton = gtk.Button(label=_("Hide")) + #self.graph_data_hbox.pack_start(expandbutton, expand=False, fill=False, padding=0) self.graph_data_hbox.show_all() - - self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) else: @@ -1035,8 +1048,14 @@ if widget.get_active(): activity.x_axis = data self.actualize_recordgraph(activity) - + def on_xlapschange(self, widget, activity=None): + if widget.get_active(): + activity.show_laps = True + else: + activity.show_laps = False + self.actualize_recordgraph(activity) + def on_y1colorchange(self, widget, box, graphdata, activity): '''Hander for changes to y1 color selection''' logging.debug("Setting %s to color %s" % (graphdata, widget.get_color() ) ) @@ -1049,7 +1068,6 @@ def on_y1change(self, widget, box, graphdata, activity): '''Hander for changes to y1 selection''' - #TODO Need to deal with different x options, ie distance and time... logging.debug("Y1 selection toggled: %s" % graphdata) #Loop through all options at set data correctly for child in box.get_children(): @@ -1065,14 +1083,14 @@ activity.time_data[item].show_on_y1 = child.get_active() #Replot the activity self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) - - def on_y2change(self, widget, box): + + def on_y2change(self, widget, box, graphdata, activity): '''Hander for changes to y2 selection''' print "Y2 selected: ", - for child in box.get_children(): - if child.get_active(): - print child.get_label(), - print + #for child in box.get_children(): + # if child.get_active(): + # print child.get_label(), + #print def on_athleteTreeView_button_press_event(self, treeview, event): x = int(event.x) Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-09-30 22:13:29 UTC (rev 638) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-10-01 04:00:02 UTC (rev 639) @@ -67,6 +67,9 @@ pace - (float) average pace for activity has_data - (bool) true if instance has data populated x_axis - (string) distance or time, determines what will be graphed on x axis + show_laps - (bool) display laps on graphs + lap_distance - (graphdata) + lap_time - (graphdata) pace_limit - (int) maximum pace that is valid for this activity ''' def __init__(self, pytrainer_main = None, id = None): @@ -104,6 +107,7 @@ self._init_graph_data() self._generate_per_lap_graphs() self.x_axis = "distance" + self.show_laps = False logging.debug("<<") def _set_units(self): @@ -205,6 +209,13 @@ logging.debug("No laps to generate graphs from") logging.debug("<<") return + #Lap columns + self.lap_distance = GraphData() + self.lap_distance.set_color('#CCFF00') + self.lap_distance.graphType = "vspan" + self.lap_time = GraphData() + self.lap_time.set_color('#CCFF00') + self.lap_time.graphType = "vspan" #Pace title=_("Pace by Lap") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) @@ -212,15 +223,24 @@ self.distance_data['pace_lap'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) self.distance_data['pace_lap'].set_color('#99CCFF') self.distance_data['pace_lap'].graphType = "bar" + xlabel=_("Time (seconds)") + self.time_data['pace_lap'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) + self.time_data['pace_lap'].set_color('#99CCFF') + self.time_data['pace_lap'].graphType = "bar" for lap in self.laps: time = float( lap['elapsed_time'].decode('utf-8') ) # time in sql is a unicode string dist = lap['distance']/1000 #distance in km pace = time/(60*dist) #min/km logging.debug("Time: %f, Dist: %f, Pace: %f" % (time, dist, pace) ) + self.lap_time.addBars(x=time, y=10) if self.us_system: + self.lap_distance.addBars(x=km2miles(dist), y=10) self.distance_data['pace_lap'].addBars(x=km2miles(dist), y=pacekm2miles(pace)) + self.time_data['pace_lap'].addBars(x=time, y=pacekm2miles(pace)) else: + self.lap_distance.addBars(x=dist, y=10) self.distance_data['pace_lap'].addBars(x=dist, y=pace) + self.time_data['pace_lap'].addBars(x=time, y=pace) logging.debug("<<") def _get_laps_from_gpx(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 22:13:39
|
Revision: 638 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=638&view=rev Author: jblance Date: 2010-09-30 22:13:29 +0000 (Thu, 30 Sep 2010) Log Message: ----------- Implement per sport pace limits - display only in newgraph Modified Paths: -------------- pytrainer/trunk/glade/profile.glade pytrainer/trunk/pytrainer/gui/windowprofile.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/lib/ddbb.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/profile.py Modified: pytrainer/trunk/glade/profile.glade =================================================================== --- pytrainer/trunk/glade/profile.glade 2010-09-30 21:13:08 UTC (rev 637) +++ pytrainer/trunk/glade/profile.glade 2010-09-30 22:13:29 UTC (rev 638) @@ -780,7 +780,7 @@ <child> <widget class="GtkTable" id="table18"> <property name="visible">True</property> - <property name="n_rows">4</property> + <property name="n_rows">5</property> <property name="n_columns">3</property> <property name="column_spacing">5</property> <property name="row_spacing">5</property> @@ -884,8 +884,8 @@ </widget> <packing> <property name="right_attach">3</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> @@ -896,6 +896,36 @@ <child> <placeholder/> </child> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkLabel" id="label-10"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Maximum Pace:</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="newmaxpace"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> </widget> <packing> <property name="position">0</property> @@ -1141,7 +1171,7 @@ <child> <widget class="GtkTable" id="table17"> <property name="visible">True</property> - <property name="n_rows">4</property> + <property name="n_rows">5</property> <property name="n_columns">2</property> <property name="column_spacing">5</property> <property name="row_spacing">5</property> @@ -1234,12 +1264,39 @@ </widget> <packing> <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label-9"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Maxiumum Pace</property> + </widget> + <packing> <property name="top_attach">3</property> <property name="bottom_attach">4</property> <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> </child> + <child> + <widget class="GtkEntry" id="editmaxpace"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> </widget> <packing> <property name="position">0</property> Modified: pytrainer/trunk/pytrainer/gui/windowprofile.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowprofile.py 2010-09-30 21:13:08 UTC (rev 637) +++ pytrainer/trunk/pytrainer/gui/windowprofile.py 2010-09-30 22:13:29 UTC (rev 638) @@ -53,7 +53,7 @@ self.prf_ddbb.insert_text(i,self.ddbb_type[i]) #preparamos la lista sports: - column_names=[_("Sport"),_("MET"),_("Extra Weight")] + column_names=[_("Sport"),_("MET"),_("Extra Weight"), _("Maximum Pace")] for column_index, column_name in enumerate(column_names): column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) column.set_resizable(True) @@ -141,6 +141,7 @@ gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, object) for i in sport_list: if not i[1]: @@ -151,12 +152,22 @@ weight = i[2] else: weight = 0 + try: + max_pace = int(i[4]) + if max_pace is None or max_pace == 0: + max_pace = "" + except Exception as e: + #print type(e), e + max_pace = "" + + iter = store.append() store.set ( iter, 0, str(i[0]), - 1, i[1], - 2, i[2] + 1, met, + 2, weight, + 3, max_pace, ) self.sportTreeView.set_model(store) #self.sportlistbutton.hide() @@ -334,7 +345,8 @@ sport = self.newsportentry.get_text() met = self.newmetentry.get_text() weight = self.newweightentry.get_text() - self.parent.addNewSport(sport,met,weight) + maxpace = self.newmaxpace.get_text() + self.parent.addNewSport(sport,met,weight,maxpace) self.parent.actualize_mainsportlist() self.on_switch_page(None,None,2) self.hidesportsteps() @@ -364,11 +376,12 @@ selected,iter = self.sportTreeView.get_selection().get_selected() if iter: sport = selected.get_value(iter,0) - name,met,weight = self.parent.getSportInfo(sport) + name,met,weight,maxpace = self.parent.getSportInfo(sport) self.editsportentry.set_text(sport) self.sportnameedit.set_text(sport) self.editweightentry.set_text(str(weight)) self.editmetentry.set_text(str(met)) + self.editmaxpace.set_text(str(maxpace)) self.hidesportsteps() self.editsport.show() @@ -377,7 +390,8 @@ newnamesport = self.editsportentry.get_text() newmetsport = self.editmetentry.get_text() newweightsport = self.editweightentry.get_text() - self.parent.updateSport(oldnamesport,newnamesport,newmetsport,newweightsport) + newmaxpace = self.editmaxpace.get_text() + self.parent.updateSport(oldnamesport,newnamesport,newmetsport,newweightsport, newmaxpace) self.parent.actualize_mainsportlist() self.on_switch_page(None,None,2) self.hidesportsteps() Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-09-30 21:13:08 UTC (rev 637) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-09-30 22:13:29 UTC (rev 638) @@ -67,6 +67,7 @@ pace - (float) average pace for activity has_data - (bool) true if instance has data populated x_axis - (string) distance or time, determines what will be graphed on x axis + pace_limit - (int) maximum pace that is valid for this activity ''' def __init__(self, pytrainer_main = None, id = None): logging.debug(">>") @@ -86,6 +87,7 @@ self.has_data = False self.distance_data = {} self.time_data = {} + self.pace_limit = None if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": self.us_system = True else: @@ -138,12 +140,15 @@ db_result = self.pytrainer_main.ddbb.select_dict("records,sports", ("sports.name","id_sports", "date","distance","time","beats","comments", "average","calories","id_record","title","upositive","unegative", - "maxspeed","maxpace","pace","maxbeats","date_time_utc","date_time_local"), + "maxspeed","maxpace","pace","maxbeats","date_time_utc","date_time_local", "sports.max_pace"), "id_record=\"%s\" and records.sport=sports.id_sports" %self.id) if len(db_result) == 1: dict = db_result[0] self.sport_name = dict['sports.name'] self.sport_id = dict['id_sports'] + self.pace_limit = dict['sports.max_pace'] + if self.pace_limit == 0 or self.pace_limit == "": + self.pace_limit = None self.title = dict['title'] self.date = dict['date'] self.time = self._int(dict['time']) @@ -297,8 +302,11 @@ for track in self.tracklist: try: pace = 60/track['velocity'] - #pace = 0 if pace > 90 else pace - except: + if self.pace_limit is not None and pace > self.pace_limit: + logging.debug("Pace (%s) exceeds limit (%s). Setting to 0" % (str(pace), str(self.pace_limit))) + pace = 0 #TODO this should be None when we move to newgraph... + except Exception as e: + #print type(e), e pace = 0 if self.us_system: self.distance_data['elevation'].addPoints(x=km2miles(track['elapsed_distance']), y=m2feet(track['ele'])) Modified: pytrainer/trunk/pytrainer/lib/ddbb.py =================================================================== --- pytrainer/trunk/pytrainer/lib/ddbb.py 2010-09-30 21:13:08 UTC (rev 637) +++ pytrainer/trunk/pytrainer/lib/ddbb.py 2010-09-30 22:13:29 UTC (rev 638) @@ -140,6 +140,7 @@ "name":"varchar(100)", "weight":"float", "met":"float", + "max_pace":"integer", }, "waypoints":{ "id_waypoint":"integer primary key autoincrement", "lat":"float", Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-30 21:13:08 UTC (rev 637) +++ pytrainer/trunk/pytrainer/main.py 2010-09-30 22:13:29 UTC (rev 638) @@ -49,8 +49,8 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#635" - self.DB_version = 3 + self.version ="1.7.2_svn#638" + self.DB_version = 4 #Process command line options self.startup_options = self.get_options() #Setup logging Modified: pytrainer/trunk/pytrainer/profile.py =================================================================== --- pytrainer/trunk/pytrainer/profile.py 2010-09-30 21:13:08 UTC (rev 637) +++ pytrainer/trunk/pytrainer/profile.py 2010-09-30 22:13:29 UTC (rev 638) @@ -276,11 +276,11 @@ connection = self.pytrainer_main.ddbb.connect() if (connection == 1): logging.debug("retrieving sports info") - return self.pytrainer_main.ddbb.select("sports","name,met,weight,id_sports",None) + return self.pytrainer_main.ddbb.select("sports","name,met,weight,id_sports,max_pace",None) else: return connection - def addNewSport(self,sport,met,weight): + def addNewSport(self,sport,met,weight,maxpace): """31.08.2008 - dgranda It adds a new sport. arguments: @@ -289,9 +289,9 @@ weight: returns: id_sports from new sport""" logging.debug(">>") - logging.debug("Adding new sport: "+sport+"|"+weight+"|"+met) - sport = [sport,met,weight] - self.pytrainer_main.ddbb.insert("sports","name,met,weight",sport) + logging.debug("Adding new sport: "+sport+"|"+weight+"|"+met+"|"+maxpace) + sport = [sport,met,weight,maxpace] + self.pytrainer_main.ddbb.insert("sports","name,met,weight,max_pace",sport) sport_id = self.pytrainer_main.ddbb.select("sports","id_sports","name=\"%s\"" %(sport)) logging.debug("<<") return sport_id @@ -305,13 +305,13 @@ self.pytrainer_main.ddbb.delete("sports","id_sports=\"%d\""%id_sport) logging.debug("<<") - def updateSport(self,oldnamesport,newnamesport,newmetsport,newweightsport): + def updateSport(self,oldnamesport,newnamesport,newmetsport,newweightsport,newmaxpace=None): logging.debug("--") - self.pytrainer_main.ddbb.update("sports","name,met,weight",[newnamesport,newmetsport,newweightsport],"name=\"%s\""%oldnamesport) + self.pytrainer_main.ddbb.update("sports","name,met,weight,max_pace",[newnamesport,newmetsport,newweightsport, newmaxpace],"name=\"%s\""%oldnamesport) def getSportInfo(self,namesport): logging.debug("--") - return self.pytrainer_main.ddbb.select("sports","name,met,weight","name=\"%s\""%namesport)[0] + return self.pytrainer_main.ddbb.select("sports","name,met,weight,max_pace","name=\"%s\""%namesport)[0] def build_ddbb(self): logging.debug("--") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 21:13:14
|
Revision: 637 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=637&view=rev Author: jblance Date: 2010-09-30 21:13:08 +0000 (Thu, 30 Sep 2010) Log Message: ----------- Fix to startup script to correctly deal with more than one xulrunner Modified Paths: -------------- pytrainer/trunk/bin/pytrainer Modified: pytrainer/trunk/bin/pytrainer =================================================================== --- pytrainer/trunk/bin/pytrainer 2010-09-30 20:59:26 UTC (rev 636) +++ pytrainer/trunk/bin/pytrainer 2010-09-30 21:13:08 UTC (rev 637) @@ -34,8 +34,17 @@ return two elif two is None: return one - one_v = os.path.basename(one).split('-')[1] - two_v = os.path.basename(two).split('-')[1] + try: + one_v = os.path.basename(one).split('-')[1] + two_v = os.path.basename(two).split('-')[1] + except IndexError: + #Got format that doesnt fit what we expect + #Do simple comparison + if os.path.basename(one) > os.path.basename(two): + return one + else: + return two + one_v_nos = one_v.split('.') two_v_nos = two_v.split('.') @@ -51,8 +60,7 @@ pass if len(one_v_nos) >= len(two_v_nos): return one - else: - return two + return two bin_path = os.path.realpath(os.path.dirname(__file__)) # directory that the pytrainer script executes from e.g. /usr/bin or /usr/local/bin @@ -88,7 +96,8 @@ #Found more than one - need to choose one... max_version = None for item in xulrunners: - max_version = _max(max_version, item) + xul_dir = os.path.dirname(item) + max_version = _max(max_version, xul_dir) xul_env = max_version print "Using xulrunner dir: %s" % xul_env This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 20:59:32
|
Revision: 636 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=636&view=rev Author: jblance Date: 2010-09-30 20:59:26 +0000 (Thu, 30 Sep 2010) Log Message: ----------- More drawArea debug Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawArea.py Modified: pytrainer/trunk/pytrainer/gui/drawArea.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawArea.py 2010-09-30 03:45:53 UTC (rev 635) +++ pytrainer/trunk/pytrainer/gui/drawArea.py 2010-09-30 20:59:26 UTC (rev 636) @@ -308,6 +308,7 @@ i = 0 for value in xvalues: if i<1: + logging.debug("i: %d, value: (%s) %s %s" % (i, str(value), str(xvalues), str(yvalues)) ) axis = figure.add_subplot(111) logging.debug("Axis: %s" % str(axis) ) line = axis.plot(xvalues[i],yvalues[i], color=color[i]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 03:45:59
|
Revision: 635 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=635&view=rev Author: jblance Date: 2010-09-30 03:45:53 +0000 (Thu, 30 Sep 2010) Log Message: ----------- Removal of un-needed print statements Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/lib/gpx.py pytrainer/trunk/pytrainer/lib/graphdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-09-30 03:28:54 UTC (rev 634) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-09-30 03:45:53 UTC (rev 635) @@ -122,7 +122,7 @@ ''' logging.debug(">>") #Parse GPX file - print "Activity initing GPX.. ", + #print "Activity initing GPX.. ", self.gpx = Gpx(filename = self.gpx_file) #TODO change GPX code to do less.... self.tree = self.gpx.tree self.tracks = self.gpx.getTrackList() #TODO fix - this should removed and replaced with self.tracklist functionality @@ -208,11 +208,10 @@ self.distance_data['pace_lap'].set_color('#99CCFF') self.distance_data['pace_lap'].graphType = "bar" for lap in self.laps: - #print lap time = float( lap['elapsed_time'].decode('utf-8') ) # time in sql is a unicode string dist = lap['distance']/1000 #distance in km pace = time/(60*dist) #min/km - print "Time: %f, Dist: %f, Pace: %f" % (time, dist, pace) + logging.debug("Time: %f, Dist: %f, Pace: %f" % (time, dist, pace) ) if self.us_system: self.distance_data['pace_lap'].addBars(x=km2miles(dist), y=pacekm2miles(pace)) else: Modified: pytrainer/trunk/pytrainer/lib/gpx.py =================================================================== --- pytrainer/trunk/pytrainer/lib/gpx.py 2010-09-30 03:28:54 UTC (rev 634) +++ pytrainer/trunk/pytrainer/lib/gpx.py 2010-09-30 03:45:53 UTC (rev 635) @@ -51,7 +51,7 @@ class Gpx: def __init__(self, data_path = None, filename = None, trkname = None): logging.debug(">>") - print("GPX init-ing") + #print("GPX init-ing") global mainNS, timeTag, trackTag, trackPointTag, trackPointTagLast, trackSegTag, elevationTag, nameTag self.data_path = data_path self.filename = filename Modified: pytrainer/trunk/pytrainer/lib/graphdata.py =================================================================== --- pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-30 03:28:54 UTC (rev 634) +++ pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-30 03:45:53 UTC (rev 635) @@ -57,7 +57,6 @@ last_left = self.x_values[items-1] last_width = self.bar_widths[items-1] new_left = last_left+last_width - print new_left self.x_values.append(new_left) self.bar_widths.append(x) self.y_values.append(y) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-30 03:28:54 UTC (rev 634) +++ pytrainer/trunk/pytrainer/main.py 2010-09-30 03:45:53 UTC (rev 635) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#634" + self.version ="1.7.2_svn#635" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 03:29:03
|
Revision: 634 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=634&view=rev Author: jblance Date: 2010-09-30 03:28:54 +0000 (Thu, 30 Sep 2010) Log Message: ----------- Updates to wordpress extension - removed separate googlemaps Modified Paths: -------------- pytrainer/trunk/extensions/wordpress/wordpress.py pytrainer/trunk/pytrainer/extensions/googlemaps.py pytrainer/trunk/pytrainer/main.py Removed Paths: ------------- pytrainer/trunk/extensions/wordpress/googlemaps.py Deleted: pytrainer/trunk/extensions/wordpress/googlemaps.py =================================================================== --- pytrainer/trunk/extensions/wordpress/googlemaps.py 2010-09-30 01:32:14 UTC (rev 633) +++ pytrainer/trunk/extensions/wordpress/googlemaps.py 2010-09-30 03:28:54 UTC (rev 634) @@ -1,98 +0,0 @@ -# -*- coding: iso-8859-1 -*- - -#Copyright (C) Fiz Vazquez vu...@si... - -#This program is free software; you can redistribute it and/or -#modify it under the terms of the GNU General Public License -#as published by the Free Software Foundation; either version 2 -#of the License, or (at your option) any later version. - -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -#GNU General Public License for more details. - -#You should have received a copy of the GNU General Public License -#along with this program; if not, write to the Free Software -#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -import os -import re -import sys -import fileinput -import shutil - -import pytrainer.lib.points as Points -from pytrainer.lib.gpx import Gpx -from pytrainer.lib.fileUtils import fileUtils - - -def drawMap(gpxfile,key,htmlpath): - #Not sure why need to process gpx file - cachefile = "/tmp/gpx.txt" - #trackdistance = 100 - #os.system("gpsbabel -t -i gpx -f %s -x position,distance=%sm -o gpx -F %s" %(gpxfile,trackdistance,cachefile)) - shutil.copy2(gpxfile, cachefile) - - # Test if file already contains gpxdata attribute - found = False - for line in fileinput.FileInput(cachefile,inplace=1): - if "xmlns:gpxdata" in line: - found = True - print line.rstrip('\n'); - # If file don't has gpxdata attribute: add namespace - if not found: - for line in fileinput.FileInput(cachefile,inplace=1): - if "xmlns:xsi" in line: - line=line.replace('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"','xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0"') - print line.rstrip('\n'); - gpx = Gpx("",cachefile) - list_values = gpx.getTrackList() - pointlist = [] - for i in list_values: - pointlist.append((i[4],i[5])) - points,levels = Points.encodePoints(pointlist) - points = points.replace("\\","\\\\") - - createHtml(points,levels,pointlist[0],htmlpath,key) - -def createHtml(points,levels,init_point,htmlpath,key): - content = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \n" - content += " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" - content += " <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\">\n" - content += " <head>\n" - content += " <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/>\n" - content += " <title>Google Maps JavaScript API Example</title>\n" - content += " <script id=\"googleapiimport\" src=\"http://maps.google.com/maps?file=api&v=2&key=%s\"\n" %key - content += " type=\"text/javascript\"></script>\n" - content += " <script type=\"text/javascript\">\n" - content += " //<![CDATA[\n" - content += " function load() {\n" - content += " if (GBrowserIsCompatible()) {\n" - content += " var map = new GMap2(document.getElementById(\"map\"));\n" - content += " map.addControl(new GLargeMapControl());\n" - content += " map.addControl(new GMapTypeControl());\n" - content += " map.setCenter(new GLatLng(%s,%s), 11);\n" %(init_point[0],init_point[1]) - content += " // Add an encoded polyline.\n" - content += " var encodedPolyline = new GPolyline.fromEncoded({\n" - content += " color: \"#3333cc\",\n" - content += " weight: 10,\n" - content += " points: \"%s\",\n" %points - content += " levels: \"%s\",\n" %levels - content += " zoomFactor: 32,\n" - content += " numLevels: 4\n" - content += " });\n" - content += " map.addOverlay(encodedPolyline);\n" - content += " }\n" - content += " }\n " - content += " //]]>\n" - content += " </script>\n" - content += " </head>\n" - content += " <body onload=\"load()\" onunload=\"GUnload()\">\n" - content += " <div id=\"map\" style=\"width: 460px; height: 460px\"></div>\n" - content += " </body>\n" - content += "</html>\n" - file = fileUtils(htmlpath,content) - file.run() - - Modified: pytrainer/trunk/extensions/wordpress/wordpress.py =================================================================== --- pytrainer/trunk/extensions/wordpress/wordpress.py 2010-09-30 01:32:14 UTC (rev 633) +++ pytrainer/trunk/extensions/wordpress/wordpress.py 2010-09-30 03:28:54 UTC (rev 634) @@ -24,59 +24,64 @@ import gtk import httplib2 -import wordpresslib #TODO remove need for this library -import googlemaps #TODO remove this separate googlemaps class +import wordpresslib #TODO remove need for this library +from pytrainer.extensions.googlemaps import Googlemaps import pytrainer.lib.points as Points from pytrainer.lib.date import Date class wordpress: - def __init__(self, parent = None, pytrainer_main = None, conf_dir = None, options = None): - #TODO could use some logging - self.parent = parent - self.pytrainer_main = pytrainer_main - self.options = options - self.conf_dir = conf_dir + def __init__(self, parent = None, pytrainer_main = None, conf_dir = None, options = None): + #TODO could use some logging + self.parent = parent + self.pytrainer_main = pytrainer_main + self.options = options + self.conf_dir = conf_dir + self.tmpdir = self.pytrainer_main.profile.tmpdir + self.data_path = self.pytrainer_main.profile.data_path + self.googlemaps = Googlemaps(data_path=self.data_path, pytrainer_main=pytrainer_main) + self.wp = None - def run(self, id, activity=None): - #Show user something is happening - msg = _("Posting to Wordpress blog") - md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) - md.set_title(_("Wordpress Extension Processing")) - md.set_modal(True) - md.show() - while gtk.events_pending(): # This allows the GUI to update - gtk.main_iteration() # before completion of this entire action - logging.debug("before request posting") - options = self.options - self.wordpressurl = options["wordpressurl"] - self.user = options["wordpressuser"] - self.password = options["wordpresspass"] - self.gpxfile = "%s/gpx/%s.gpx" %(self.conf_dir,id) - self.googlekey = options["googlekey"] - self.idrecord = id - self.activity = activity - self.wordpresscategory = options["wordpresscategory"] - debug_msg = "%s, %s, %s, %s, %s, %s" % (self.wordpressurl, self.user, self.gpxfile, self.googlekey, self.idrecord, self.wordpresscategory) - logging.debug(debug_msg) - try: - self.wp = wordpresslib.WordPressClient(self.wordpressurl, self.user, self.password) #TODO remove need for wordpresslib?? - self.error = False - except: - self.error = True - self.log = "Url, user or pass are incorrect. Please, check your configuration" - self.loadRecordInfo() - if self.title is None: - self.title = "No Title" - blog_table = self.createTable() - blog_route = self.createRoute() - blog_body = self.createBody() + def run(self, id, activity=None): + #Show user something is happening + msg = _("Posting to Wordpress blog") + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) + md.set_title(_("Wordpress Extension Processing")) + md.set_modal(True) + md.show() + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + logging.debug("before request posting") + options = self.options + self.wordpressurl = options["wordpressurl"] + self.user = options["wordpressuser"] + self.password = options["wordpresspass"] + self.gpxfile = "%s/gpx/%s.gpx" %(self.conf_dir,id) + self.googlekey = options["googlekey"] + self.idrecord = id + self.activity = activity + self.wordpresscategory = options["wordpresscategory"] + debug_msg = "%s, %s, %s, %s, %s, %s" % (self.wordpressurl, self.user, self.gpxfile, self.googlekey, self.idrecord, self.wordpresscategory) + logging.debug(debug_msg) + try: + self.wp = wordpresslib.WordPressClient(self.wordpressurl, self.user, self.password) #TODO remove need for wordpresslib?? + self.error = False + except Exception as e: + print e + self.error = True + self.log = "Url, user or pass are incorrect. Please, check your configuration" + self.loadRecordInfo() + if self.title is None or self.title == "": + self.title = "Untitled Activity" + blog_table = self.createTable() + blog_route = self.createRoute() + blog_body = self.createBody() - blog_figureHR = self.createFigureHR() - blog_figureStage = self.createFigureStage() - blog_foot = self.createFoot() + blog_figureHR = self.createFigureHR() + blog_figureStage = self.createFigureStage() + blog_foot = self.createFoot() - self.description = "<![CDATA["+blog_body+blog_table+blog_route+blog_figureHR+blog_figureStage+blog_foot+"]]>" - xmlstuff = '''<methodCall> + self.description = "<![CDATA["+blog_body+blog_table+blog_route+blog_figureHR+blog_figureStage+blog_foot+"]]>" + xmlstuff = '''<methodCall> <methodName>metaWeblog.newPost</methodName> <params> <param> @@ -123,153 +128,156 @@ </methodCall> ''' % (self.user, self.password, self.wordpresscategory, self.description, self.title) - #POST request to Wordpress blog - h = httplib2.Http() - res, content = h.request(self.wordpressurl, 'POST', body=xmlstuff) - logging.debug("after request posting") - logging.debug("Got response status: %s, reason: %s, content: %s" % (res.status, res.reason, content)) - if res.reason == 'OK': - res_msg = "Successfully posted to Wordpress." - else: - res_msg = "Some error occured\nGot a status %s, reason %s\nContent was: %s" % (res.status, res.reason, content) - #Close 'Please wait' dialog - md.destroy() - #Show the user the result - md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, res_msg) - md.set_title(_("Wordpress Extension Upload Complete")) - md.set_modal(False) - md.run() - md.destroy() + #POST request to Wordpress blog + h = httplib2.Http() + res, content = h.request(self.wordpressurl, 'POST', body=xmlstuff) + logging.debug("after request posting") + logging.debug("Got response status: %s, reason: %s, content: %s" % (res.status, res.reason, content)) + if res.reason == 'OK': + res_msg = "Successfully posted to Wordpress." + else: + res_msg = "Some error occured\nGot a status %s, reason %s\nContent was: %s" % (res.status, res.reason, content) + #Close 'Please wait' dialog + md.destroy() + #Show the user the result + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, res_msg) + md.set_title(_("Wordpress Extension Upload Complete")) + md.set_modal(False) + md.run() + md.destroy() - def createRoute(self): - gpxpath = "/tmp/gpstrace.gpx.txt" - htmlpath = "/tmp/index.html" #TODO fix to use correct tmp dir - kmlpath = "/tmp/gps.kml.txt" #TODO fix to use correct tmp dir - description_route = '' - if os.path.isfile(self.gpxfile): - #copy gpx file to new name - shutil.copy(self.gpxfile, gpxpath) - #create the html file - googlemaps.drawMap(self.gpxfile,self.googlekey,htmlpath) #TODO fix to use main googlemaps and remove extensions copy - #create the kml file - os.system("gpsbabel -t -i gpx -f %s -o kml,points=0,line_color=ff0000ff -F %s" %(self.gpxfile,kmlpath)) #TODO fix to remove gpsbabel + def createRoute(self): + gpxpath = "%s/gpstrace.gpx.txt" % self.tmpdir + #htmlpath = "%s/index.html" % self.tmpdir + kmlpath = "%s/gps.kml.txt" % self.tmpdir + description_route = '' + if os.path.isfile(self.gpxfile): + #copy gpx file to new name + shutil.copy(self.gpxfile, gpxpath) + #create the html file + #htmlpath = googlemaps.drawMap(self.gpxfile,self.googlekey,htmlpath) #TODO fix to use main googlemaps and remove extensions copy + htmlpath = self.googlemaps.drawMap(self.activity) + #create the kml file + os.system("gpsbabel -t -i gpx -f %s -o kml,points=0,line_color=ff0000ff -F %s" %(self.gpxfile,kmlpath)) #TODO fix to remove gpsbabel - #gfile = self.wp.newMediaObject(self.gpxfile) - gfile = self.wp.newMediaObject(gpxpath) - hfile = self.wp.newMediaObject(htmlpath) - kfile = self.wp.newMediaObject(kmlpath) + #gfile = self.wp.newMediaObject(self.gpxfile) + gfile = self.wp.newMediaObject(gpxpath) + hfile = self.wp.newMediaObject(htmlpath) + kfile = self.wp.newMediaObject(kmlpath) - description_route = '''<strong>Map: </strong> <br/> - <iframe width='480' height='480' src='%s'> Need frame support </iframe><br/> - <a href='%s'>Gpx-format</a> <a href='%s'>Kml-format (GoogleEarth)</a><br/><br/>''' %(hfile,gfile,kfile) - return description_route + description_route = '''<strong>Map: </strong> <br/> + <iframe width='480' height='480' src='%s'> Need frame support </iframe><br/> + <a href='%s'>Gpx-format</a> <a href='%s'>Kml-format (GoogleEarth)</a><br/><br/>''' %(hfile,gfile,kfile) + return description_route - def loadRecordInfo(self): - #date = Date() - #record = self.pytrainer_main.record.getrecordInfo(self.idrecord)[0] - #"sports.name,date,distance,time,beats,comments,average,calories,id_record,title,upositive,unegative,maxspeed,maxpace,pace,maxbeats,date_time_utc,date_time_local", - self.sport = self.activity.sport_name - self.date = self.activity.date - self.distance = self.activity.distance - self.time = "%d:%02d:%02d" % (self.activity.time_tuple) - print self.time - self.beats = self.activity.beats - self.comments = self.activity.comments - self.average = self.activity.average - self.calories = self.activity.calories - self.title = self.activity.title - self.upositive = self.activity.upositive - self.unegative = self.activity.unegative - self.maxspeed = self.activity.maxspeed - self.maxpace = self.activity.maxpace - self.pace = self.activity.pace - self.maxbeats = self.activity.maxbeats - self.distance_unit = self.activity.distance_unit - self.speed_unit = self.activity.speed_unit - self.pace_unit = self.activity.pace_unit - self.height_unit = self.activity.height_unit + def loadRecordInfo(self): + #date = Date() + #record = self.pytrainer_main.record.getrecordInfo(self.idrecord)[0] + #"sports.name,date,distance,time,beats,comments,average,calories,id_record,title,upositive,unegative,maxspeed,maxpace,pace,maxbeats,date_time_utc,date_time_local", + self.sport = self.activity.sport_name + self.date = self.activity.date + self.distance = self.activity.distance + self.time = "%d:%02d:%02d" % (self.activity.time_tuple) + self.beats = self.activity.beats + self.comments = self.activity.comments + self.average = self.activity.average + self.calories = self.activity.calories + self.title = self.activity.title + self.upositive = self.activity.upositive + self.unegative = self.activity.unegative + self.maxspeed = self.activity.maxspeed + self.maxpace = self.activity.maxpace + self.pace = self.activity.pace + self.maxbeats = self.activity.maxbeats + self.distance_unit = self.activity.distance_unit + self.speed_unit = self.activity.speed_unit + self.pace_unit = self.activity.pace_unit + self.height_unit = self.activity.height_unit - def createBody(self): - return '''<b> Description: </b><br/>%s<br/>''' %self.activity.comments + def createBody(self): + if self.comments is None or self.comments == "": + return "" + else: + return '''<b> Description: </b><br/>%s<br/>''' %self.comments - def createTable(self): - description_table = ''' - <br/> - <table border=0> - <tr> - <td><strong>Activity:</strong></td> - <td>%s</td> - <td><strong>Date:</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Distance (%s):</strong></td> - <td>%.2f</td> - <td><strong>Time (hh:mm:ss):</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Max speed (%s):</strong></td> - <td>%.2f</td> - <td><strong>Avg speed (%s):</strong></td> - <td>%.2f</td> - </tr> - <tr> - <td><strong>Max pace (%s):</strong></td> - <td>%.2f</td> - <td><strong>Avg pace (%s):</strong></td> - <td>%.2f</td> - </tr> - <tr> - <td><strong>Max pulse:</strong></td> - <td>%s</td> - <td><strong>Avg pulse:</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Acc elevation (+%s):</strong></td> - <td>%.2f</td> - <td><strong>Acc elevation (-%s):</strong></td> - <td>%.2f</td> - </tr> - </table> - ''' %( self.sport, self.date, self.distance_unit, self.distance, self.time, self.speed_unit, self.maxspeed, - self.speed_unit, self.average, self.pace_unit, self.maxpace,self.pace_unit, self.pace, - self.maxbeats, self.beats, self.height_unit, self.upositive, self.height_unit, self.unegative) - return description_table + def createTable(self): + description_table = ''' + <br/> + <table border=0> + <tr> + <td><strong>Activity:</strong></td> + <td>%s</td> + <td><strong>Date:</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Distance (%s):</strong></td> + <td>%.2f</td> + <td><strong>Time (hh:mm:ss):</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Max speed (%s):</strong></td> + <td>%.2f</td> + <td><strong>Avg speed (%s):</strong></td> + <td>%.2f</td> + </tr> + <tr> + <td><strong>Max pace (%s):</strong></td> + <td>%.2f</td> + <td><strong>Avg pace (%s):</strong></td> + <td>%.2f</td> + </tr> + <tr> + <td><strong>Max pulse:</strong></td> + <td>%s</td> + <td><strong>Avg pulse:</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Acc elevation (+%s):</strong></td> + <td>%.2f</td> + <td><strong>Acc elevation (-%s):</strong></td> + <td>%.2f</td> + </tr> + </table> + ''' %( self.sport, self.date, self.distance_unit, self.distance, self.time, self.speed_unit, self.maxspeed, + self.speed_unit, self.average, self.pace_unit, self.maxpace,self.pace_unit, self.pace, + self.maxbeats, self.beats, self.height_unit, self.upositive, self.height_unit, self.unegative) + return description_table - def createFigureHR(self): - hr_fig_path = "/tmp/hr.png" #TODO fix, correct tmp dir and ensure png exists - blog_figures = '' - # If there are no graphs, return empty string. - if os.path.isfile(hr_fig_path): - #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) - hrfile = self.wp.newMediaObject(hr_fig_path) - blog_figures = '''<br/> <img src='%s' /> ''' %hrfile - return blog_figures + def createFigureHR(self): + hr_fig_path = "%s/hr.png" % self.tmpdir #TODO ensure png exists + blog_figures = '' + # If there are no graphs, return empty string. + if os.path.isfile(hr_fig_path): + #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) + hrfile = self.wp.newMediaObject(hr_fig_path) + blog_figures = '''<br/> <img src='%s' /> ''' %hrfile + return blog_figures - def createFigureStage(self): - stage_fig_path = "/tmp/stage.png" #TODO fix, correct tmp dir and ensure png exists - blog_figures = '' - # If there are no graphs, return empty string. - if os.path.isfile(stage_fig_path): - #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) - stagefile = self.wp.newMediaObject(stage_fig_path) - blog_figures = '''<br/> <img src='%s' /> ''' %stagefile - return blog_figures + def createFigureStage(self): + stage_fig_path = "/tmp/stage.png" #TODO fix, correct tmp dir and ensure png exists + blog_figures = '' + # If there are no graphs, return empty string. + if os.path.isfile(stage_fig_path): + #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) + stagefile = self.wp.newMediaObject(stage_fig_path) + blog_figures = '''<br/> <img src='%s' /> ''' %stagefile + return blog_figures - def createFoot(self): - return ''' <br/><center>Powered by <a href='http://sourceforge.net/projects/pytrainer/'>Pytrainer</a></center>''' + def createFoot(self): + return ''' <br/><center>Powered by <a href='http://sourceforge.net/projects/pytrainer/'>Pytrainer</a></center>''' - def createTitle(self): - if self.title==None: - self.error = True - self.log = "A Title must be defined. Please, configure the record properly" - return self.title + def createTitle(self): + if self.title==None: + self.error = True + self.log = "A Title must be defined. Please, configure the record properly" + return self.title - def createCategory(self): - if self.wordpresscategory==None: - self.error = True - self.log = "A wordpress category must be defined. Please, configure the wordpress extension" - else: - return ([self.wordpresscategory]) + def createCategory(self): + if self.wordpresscategory==None: + self.error = True + self.log = "A wordpress category must be defined. Please, configure the wordpress extension" + else: + return ([self.wordpresscategory]) Modified: pytrainer/trunk/pytrainer/extensions/googlemaps.py =================================================================== --- pytrainer/trunk/pytrainer/extensions/googlemaps.py 2010-09-30 01:32:14 UTC (rev 633) +++ pytrainer/trunk/pytrainer/extensions/googlemaps.py 2010-09-30 03:28:54 UTC (rev 634) @@ -27,310 +27,314 @@ #from pytrainer.record import Record class Googlemaps: - def __init__(self, data_path = None, waypoint = None, pytrainer_main=None): - logging.debug(">>") - self.data_path = data_path - self.waypoint=waypoint - self.pytrainer_main = pytrainer_main - self.htmlfile = "%s/googlemaps.html" % (self.pytrainer_main.profile.tmpdir) - logging.debug("<<") + def __init__(self, data_path = None, waypoint = None, pytrainer_main=None): + logging.debug(">>") + self.data_path = data_path + self.waypoint=waypoint + self.pytrainer_main = pytrainer_main + self.htmlfile = "%s/googlemaps.html" % (self.pytrainer_main.profile.tmpdir) + logging.debug("<<") - def drawMap(self,activity): - '''Draw google map - create html file using Google API version?? - render using embedded Mozilla + def drawMap(self,activity): + '''Draw google map + create html file using Google API version?? + render using embedded Mozilla - info at http://www.pygtk.org/pygtkmozembed/class-gtkmozembed.html - ''' - logging.debug(">>") - points = [] - levels = [] - pointlist = [] - polyline = [] + info at http://www.pygtk.org/pygtkmozembed/class-gtkmozembed.html + ''' + logging.debug(">>") + points = [] + levels = [] + pointlist = [] + polyline = [] - list_values = activity.tracks - if list_values is not None and list_values != [] and len(list_values) > 0: - minlat, minlon = float(list_values[0][4]),float(list_values[0][5]) - maxlat=minlat - maxlon=minlon - for i in list_values: - lat, lon = float(i[4]), float(i[5]) - minlat = min(minlat, lat) - maxlat = max(maxlat, lat) - minlon = min(minlon, lon) - maxlon = max(maxlon, lon) - pointlist.append((lat,lon)) - polyline.append("new google.maps.LatLng(%s, %s)" % (lat, lon)) - logging.debug("minlat: %s, maxlat: %s" % (minlat, maxlat)) - logging.debug("minlon: %s, maxlon: %s" % (minlon, maxlon)) - points,levels = Points.encodePoints(pointlist) - points = points.replace("\\","\\\\") - if self.pytrainer_main.startup_options.gm3: - logging.debug("Using Google Maps version 3 API") - laps = activity.laps - timeHours = int(activity.time) / 3600 - timeMin = (float(activity.time) / 3600.0 - timeHours) * 60 - time = "%d%s %02d%s" % (timeHours, _("h"), timeMin, _("min")) - startinfo = "<div class='info_content'>%s: %s</div>" % (activity.sport_name, activity.title) - finishinfo = "<div class='info_content'>%s: %s<br>%s: %s%s</div>" % (_("Time"), time, _("Distance"), activity.distance, activity.distance_unit) - startinfo = startinfo.encode('ascii', 'xmlcharrefreplace') #Encode for html - finishinfo = finishinfo.encode('ascii', 'xmlcharrefreplace') #Encode for html - self.createHtml_api3(polyline, minlat, minlon, maxlat, maxlon, startinfo, finishinfo, laps) - else: - logging.debug("Using Google Maps version 2 API") - self.createHtml(points,levels,pointlist[0]) - else: - self.createErrorHtml() - return self.htmlfile - logging.debug("<<") + list_values = activity.tracks + if list_values is not None and list_values != [] and len(list_values) > 0: + minlat, minlon = float(list_values[0][4]),float(list_values[0][5]) + maxlat=minlat + maxlon=minlon + for i in list_values: + lat, lon = float(i[4]), float(i[5]) + minlat = min(minlat, lat) + maxlat = max(maxlat, lat) + minlon = min(minlon, lon) + maxlon = max(maxlon, lon) + pointlist.append((lat,lon)) + polyline.append("new google.maps.LatLng(%s, %s)" % (lat, lon)) + logging.debug("minlat: %s, maxlat: %s" % (minlat, maxlat)) + logging.debug("minlon: %s, maxlon: %s" % (minlon, maxlon)) + points,levels = Points.encodePoints(pointlist) + points = points.replace("\\","\\\\") + if self.pytrainer_main.startup_options.gm3: + logging.debug("Using Google Maps version 3 API") + laps = activity.laps + timeHours = int(activity.time) / 3600 + timeMin = (float(activity.time) / 3600.0 - timeHours) * 60 + time = "%d%s %02d%s" % (timeHours, _("h"), timeMin, _("min")) + startinfo = "<div class='info_content'>%s: %s</div>" % (activity.sport_name, activity.title) + finishinfo = "<div class='info_content'>%s: %s<br>%s: %s%s</div>" % (_("Time"), time, _("Distance"), activity.distance, activity.distance_unit) + startinfo = startinfo.encode('ascii', 'xmlcharrefreplace') #Encode for html + finishinfo = finishinfo.encode('ascii', 'xmlcharrefreplace') #Encode for html + self.createHtml_api3(polyline, minlat, minlon, maxlat, maxlon, startinfo, finishinfo, laps) + else: + logging.debug("Using Google Maps version 2 API") + self.createHtml(points,levels,pointlist[0]) + else: + self.createErrorHtml() + return self.htmlfile + logging.debug("<<") - def createHtml_api3(self,polyline, minlat, minlon, maxlat, maxlon, startinfo, finishinfo, laps): - ''' - Generate a Google maps html file using the v3 api - documentation at http://code.google.com/apis/maps/documentation/v3 - ''' - logging.debug(">>") - waypoints = self.waypoint.getAllWaypoints() - #TODO waypoints not supported in this function yet - #TODO sort polyline encoding (not supported in v3?) - #TODO check http://code.google.com/apis/maps/documentation/v3/overlays.html#Polylines for MVArray?? - content = ''' - <html> - <head> - <style type="text/css"> - div.info_content { font-family: sans-serif; font-size: 10px; } - </style> - <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> - <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> - <script type="text/javascript"> - function initialize() {\n''' - content += " var startlatlng = %s ;\n" % (polyline[0]) - content += " var centerlatlng = new google.maps.LatLng(%f, %f);\n" % ((minlat+maxlat)/2., (minlon+maxlon)/2.) - content += " var endlatlng = %s;\n" % (polyline[-1]) - content += " var swlatlng = new google.maps.LatLng(%f, %f);\n" % (minlat,minlon) - content += " var nelatlng = new google.maps.LatLng(%f, %f);\n" % (maxlat,maxlon) - content += " var startcontent = \"%s\";\n" % (startinfo) - content += " var finishcontent = \"%s\";\n" % (finishinfo) - content += " var startimageloc = \"%s/glade/start.png\";\n" % (os.path.abspath(self.data_path)) - content += " var finishimageloc = \"%s/glade/finish.png\";\n" % (os.path.abspath(self.data_path)) - content += " var lapimageloc = \"%s/glade/waypoint.png\";\n" % (os.path.abspath(self.data_path)) - content +=''' - var myOptions = { - zoom: 8, - center: centerlatlng, - scaleControl: true, - mapTypeId: google.maps.MapTypeId.ROADMAP - }; + def createHtml_api3(self,polyline, minlat, minlon, maxlat, maxlon, startinfo, finishinfo, laps): + ''' + Generate a Google maps html file using the v3 api + documentation at http://code.google.com/apis/maps/documentation/v3 + ''' + logging.debug(">>") + if self.waypoint is not None: + waypoints = self.waypoint.getAllWaypoints() + #TODO waypoints not supported in this function yet + #TODO sort polyline encoding (not supported in v3?) + #TODO check http://code.google.com/apis/maps/documentation/v3/overlays.html#Polylines for MVArray?? + content = ''' + <html> + <head> + <style type="text/css"> + div.info_content { font-family: sans-serif; font-size: 10px; } + </style> + <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> + <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> + <script type="text/javascript"> + function initialize() {\n''' + content += " var startlatlng = %s ;\n" % (polyline[0]) + content += " var centerlatlng = new google.maps.LatLng(%f, %f);\n" % ((minlat+maxlat)/2., (minlon+maxlon)/2.) + content += " var endlatlng = %s;\n" % (polyline[-1]) + content += " var swlatlng = new google.maps.LatLng(%f, %f);\n" % (minlat,minlon) + content += " var nelatlng = new google.maps.LatLng(%f, %f);\n" % (maxlat,maxlon) + content += " var startcontent = \"%s\";\n" % (startinfo) + content += " var finishcontent = \"%s\";\n" % (finishinfo) + content += " var startimageloc = \"%s/glade/start.png\";\n" % (os.path.abspath(self.data_path)) + content += " var finishimageloc = \"%s/glade/finish.png\";\n" % (os.path.abspath(self.data_path)) + content += " var lapimageloc = \"%s/glade/waypoint.png\";\n" % (os.path.abspath(self.data_path)) + content +=''' + var myOptions = { + zoom: 8, + center: centerlatlng, + scaleControl: true, + mapTypeId: google.maps.MapTypeId.ROADMAP + }; - var startimage = new google.maps.MarkerImage(startimageloc,\n - // This marker is 32 pixels wide by 32 pixels tall. - new google.maps.Size(32, 32), - // The origin for this image is 0,0. - new google.maps.Point(0,0), - // The anchor for this image is the base of the flagpole - new google.maps.Point(16, 32));\n\n - var finishimage = new google.maps.MarkerImage(finishimageloc,\n - // This marker is 32 pixels wide by 32 pixels tall. - new google.maps.Size(32, 32), - // The origin for this image is 0,0. - new google.maps.Point(0,0), - // The anchor for this image is the base of the flagpole - new google.maps.Point(16, 32));\n + var startimage = new google.maps.MarkerImage(startimageloc,\n + // This marker is 32 pixels wide by 32 pixels tall. + new google.maps.Size(32, 32), + // The origin for this image is 0,0. + new google.maps.Point(0,0), + // The anchor for this image is the base of the flagpole + new google.maps.Point(16, 32));\n\n + var finishimage = new google.maps.MarkerImage(finishimageloc,\n + // This marker is 32 pixels wide by 32 pixels tall. + new google.maps.Size(32, 32), + // The origin for this image is 0,0. + new google.maps.Point(0,0), + // The anchor for this image is the base of the flagpole + new google.maps.Point(16, 32));\n - var lapimage = new google.maps.MarkerImage(lapimageloc,\n - // This marker is 32 pixels wide by 32 pixels tall. - new google.maps.Size(32, 32), - // The origin for this image is 0,0. - new google.maps.Point(0,0), - // The anchor for this image is the base of the flagpole - new google.maps.Point(16, 32));\n + var lapimage = new google.maps.MarkerImage(lapimageloc,\n + // This marker is 32 pixels wide by 32 pixels tall. + new google.maps.Size(32, 32), + // The origin for this image is 0,0. + new google.maps.Point(0,0), + // The anchor for this image is the base of the flagpole + new google.maps.Point(16, 32));\n - var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); - var startmarker = new google.maps.Marker({ - position: startlatlng, - map: map, - icon: startimage, - title:"Start"}); + var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); + var startmarker = new google.maps.Marker({ + position: startlatlng, + map: map, + icon: startimage, + title:"Start"}); - var finishmarker = new google.maps.Marker({ - position: endlatlng, - icon: finishimage, - map: map, - title:"End"}); \n + var finishmarker = new google.maps.Marker({ + position: endlatlng, + icon: finishimage, + map: map, + title:"End"}); \n - //Add an infowindows - var startinfo = new google.maps.InfoWindow({ - content: startcontent - }); + //Add an infowindows + var startinfo = new google.maps.InfoWindow({ + content: startcontent + }); - var finishinfo = new google.maps.InfoWindow({ - content: finishcontent - }); + var finishinfo = new google.maps.InfoWindow({ + content: finishcontent + }); - google.maps.event.addListener(startmarker, 'click', function() { - startinfo.open(map,startmarker); - }); + google.maps.event.addListener(startmarker, 'click', function() { + startinfo.open(map,startmarker); + }); - google.maps.event.addListener(finishmarker, 'click', function() { - finishinfo.open(map,finishmarker); - });\n''' + google.maps.event.addListener(finishmarker, 'click', function() { + finishinfo.open(map,finishmarker); + });\n''' - #"id_lap, record, elapsed_time, distance, start_lat, start_lon, end_lat, end_lon, calories, lap_number", - for lap in laps: - lapNumber = int(lap['lap_number'])+1 - elapsedTime = float(lap['elapsed_time']) - elapsedTimeHours = int(elapsedTime/3600) - elapsedTimeMins = int((elapsedTime - (elapsedTimeHours * 3600)) / 60) - elapsedTimeSecs = elapsedTime - (elapsedTimeHours * 3600) - (elapsedTimeMins * 60) - if elapsedTimeHours > 0: - strElapsedTime = "%0.0dh:%0.2dm:%0.2fs" % (elapsedTimeHours, elapsedTimeMins, elapsedTimeSecs) - elif elapsedTimeMins > 0: - strElapsedTime = "%0.0dm:%0.2fs" % (elapsedTimeMins, elapsedTimeSecs) - else: - strElapsedTime = "%0.0fs" % (elapsedTimeSecs) - #process lat and lon for this lap - try: - lapLat = float(lap['end_lat']) - lapLon = float(lap['end_lon']) - content += "var lap%dmarker = new google.maps.Marker({position: new google.maps.LatLng(%f, %f), icon: lapimage, map: map, title:\"Lap%d\"}); \n " % (lapNumber, lapLat, lapLon, lapNumber) - content += "var lap%d = new google.maps.InfoWindow({content: \"<div class='info_content'>End of lap:%s<br>Elapsed time:%s<br>Distance:%0.2f km<br>Calories:%s</div>\" });\n" % (lapNumber, lapNumber, strElapsedTime, float(lap['distance'])/1000, lap['calories']) - content += "google.maps.event.addListener(lap%dmarker, 'click', function() { lap%d.open(map,lap%dmarker); });\n" % (lapNumber,lapNumber,lapNumber) - except Exception as e: - #Error processing lap lat or lon - #dont show this lap - logging.debug( "Error processing lap "+ str(lap) ) - logging.debug(str(e)) + #"id_lap, record, elapsed_time, distance, start_lat, start_lon, end_lat, end_lon, calories, lap_number", + for lap in laps: + lapNumber = int(lap['lap_number'])+1 + elapsedTime = float(lap['elapsed_time']) + elapsedTimeHours = int(elapsedTime/3600) + elapsedTimeMins = int((elapsedTime - (elapsedTimeHours * 3600)) / 60) + elapsedTimeSecs = elapsedTime - (elapsedTimeHours * 3600) - (elapsedTimeMins * 60) + if elapsedTimeHours > 0: + strElapsedTime = "%0.0dh:%0.2dm:%0.2fs" % (elapsedTimeHours, elapsedTimeMins, elapsedTimeSecs) + elif elapsedTimeMins > 0: + strElapsedTime = "%0.0dm:%0.2fs" % (elapsedTimeMins, elapsedTimeSecs) + else: + strElapsedTime = "%0.0fs" % (elapsedTimeSecs) + #process lat and lon for this lap + try: + lapLat = float(lap['end_lat']) + lapLon = float(lap['end_lon']) + content += "var lap%dmarker = new google.maps.Marker({position: new google.maps.LatLng(%f, %f), icon: lapimage, map: map, title:\"Lap%d\"}); \n " % (lapNumber, lapLat, lapLon, lapNumber) + content += "var lap%d = new google.maps.InfoWindow({content: \"<div class='info_content'>End of lap:%s<br>Elapsed time:%s<br>Distance:%0.2f km<br>Calories:%s</div>\" });\n" % (lapNumber, lapNumber, strElapsedTime, float(lap['distance'])/1000, lap['calories']) + content += "google.maps.event.addListener(lap%dmarker, 'click', function() { lap%d.open(map,lap%dmarker); });\n" % (lapNumber,lapNumber,lapNumber) + except Exception as e: + #Error processing lap lat or lon + #dont show this lap + logging.debug( "Error processing lap "+ str(lap) ) + logging.debug(str(e)) - content += ''' + content += ''' - var boundsBox = new google.maps.LatLngBounds(swlatlng, nelatlng );\n - map.fitBounds(boundsBox);\n - var polylineCoordinates = [\n''' - for point in polyline: - content += " %s,\n" % (point) - content += ''' ];\n - // Add a polyline.\n - var polyline = new google.maps.Polyline({\n - path: polylineCoordinates,\n - strokeColor: \"#3333cc\",\n - strokeOpacity: 0.6,\n - strokeWeight: 5,\n - });\n - polyline.setMap(map);\n - } + var boundsBox = new google.maps.LatLngBounds(swlatlng, nelatlng );\n + map.fitBounds(boundsBox);\n + var polylineCoordinates = [\n''' + for point in polyline: + content += " %s,\n" % (point) + content += ''' ];\n + // Add a polyline.\n + var polyline = new google.maps.Polyline({\n + path: polylineCoordinates,\n + strokeColor: \"#3333cc\",\n + strokeOpacity: 0.6,\n + strokeWeight: 5,\n + });\n + polyline.setMap(map);\n + } - </script> - </head> - <body onload="initialize()"> - <div id="map_canvas" style="width:100%; height:100%"></div> - </body> - </html>''' - file = fileUtils(self.htmlfile,content) - file.run() - logging.debug("<<") + </script> + </head> + <body onload="initialize()"> + <div id="map_canvas" style="width:100%; height:100%"></div> + </body> + </html>''' + file = fileUtils(self.htmlfile,content) + file.run() + logging.debug("<<") - def createHtml(self,points,levels,init_point): - logging.debug(">>") - waypoints = self.waypoint.getAllWaypoints() - content = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \n" - content += " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" - content += " <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\">\n" - content += " <head>\n" - content += " <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/>\n" - content += " <title>Google Maps JavaScript API Example</title>\n" - content += " <script id=\"googleapiimport\" src=\"http://maps.google.com/maps?file=api&v=2\"\n" - content += " type=\"text/javascript\"></script>\n" - content += " <script type=\"text/javascript\">\n" - content += " //<![CDATA[\n" - i = 0 - arrayjs = "" - for point in waypoints: - content += "lon = '%f';\n"%point[2] - content += "lat = '%f';\n"%point[1] - content += "name = '%s';\n"%point[6] - content += "description = '%s';\n"%point[4] - content += "sym = '%s';\n"%point[7] - content += "id = '%d';\n"%point[0] - content += """waypoint%d = Array (lon,lat,name,description,sym,id);\n"""%i - if i>0: - arrayjs+="," - arrayjs +="waypoint%d"%i - i = i+1 - content += """waypointList = Array (%s);\n""" %arrayjs - content += """ - function createMarker(waypoint,map) { - var lon = waypoint[0]; - var lat = waypoint[1]; - var id = waypoint[5]; - var name = waypoint[2]; - var description = waypoint[3]; + def createHtml(self,points,levels,init_point): + logging.debug(">>") + if self.waypoint is not None: + waypoints = self.waypoint.getAllWaypoints() + else: + waypoints = [] + content = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \n" + content += " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" + content += " <html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\">\n" + content += " <head>\n" + content += " <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/>\n" + content += " <title>Google Maps JavaScript API Example</title>\n" + content += " <script id=\"googleapiimport\" src=\"http://maps.google.com/maps?file=api&v=2\"\n" + content += " type=\"text/javascript\"></script>\n" + content += " <script type=\"text/javascript\">\n" + content += " //<![CDATA[\n" + i = 0 + arrayjs = "" + for point in waypoints: + content += "lon = '%f';\n"%point[2] + content += "lat = '%f';\n"%point[1] + content += "name = '%s';\n"%point[6] + content += "description = '%s';\n"%point[4] + content += "sym = '%s';\n"%point[7] + content += "id = '%d';\n"%point[0] + content += """waypoint%d = Array (lon,lat,name,description,sym,id);\n"""%i + if i>0: + arrayjs+="," + arrayjs +="waypoint%d"%i + i = i+1 + content += """waypointList = Array (%s);\n""" %arrayjs + content += """ + function createMarker(waypoint,map) { + var lon = waypoint[0]; + var lat = waypoint[1]; + var id = waypoint[5]; + var name = waypoint[2]; + var description = waypoint[3]; - var point = new GLatLng(lat,lon); - var text = "<b>"+waypoint[2]+"</b><br/>"+waypoint[3]; + var point = new GLatLng(lat,lon); + var text = "<b>"+waypoint[2]+"</b><br/>"+waypoint[3]; - var icon = new GIcon(); - if (sym=="Summit") { - icon.image = \""""+os.path.abspath(self.data_path)+"""/glade/summit.png\"; - } - else { - icon.image = \""""+os.path.abspath(self.data_path)+"""/glade/waypoint.png\"; - } - icon.iconSize = new GSize(32, 32); - icon.iconAnchor = new GPoint(16, 16); - icon.infoWindowAnchor = new GPoint(5, 1); + var icon = new GIcon(); + if (sym=="Summit") { + icon.image = \""""+os.path.abspath(self.data_path)+"""/glade/summit.png\"; + } + else { + icon.image = \""""+os.path.abspath(self.data_path)+"""/glade/waypoint.png\"; + } + icon.iconSize = new GSize(32, 32); + icon.iconAnchor = new GPoint(16, 16); + icon.infoWindowAnchor = new GPoint(5, 1); - var markerD = new GMarker(point, {icon:icon, draggable: false}); - GEvent.addListener(markerD, "click", function() { - markerD.openInfoWindowHtml("<b>" + name + "</b><br/>"+description); - }); - map.addOverlay(markerD); + var markerD = new GMarker(point, {icon:icon, draggable: false}); + GEvent.addListener(markerD, "click", function() { + markerD.openInfoWindowHtml("<b>" + name + "</b><br/>"+description); + }); + map.addOverlay(markerD); - }""" + }""" - content += " function load() {\n" - content += " if (GBrowserIsCompatible()) {\n" - content += " var map = new GMap2(document.getElementById(\"map\"));\n" - content += " map.addControl(new GLargeMapControl());\n" - content += " map.addControl(new GMapTypeControl());\n" - content += " map.addControl(new GScaleControl());\n" - content += " map.setCenter(new GLatLng(%f,%f), 11);\n" %(float(init_point[0]),float(init_point[1])) - content += " ovMap=new GOverviewMapControl();\n" - content += " map.addControl(ovMap);\n" - content += " mini=ovMap.getOverviewMap();\n" - content += " //Dibujamos los waypoints\n" - content += " for (i=0; i<waypointList.length; i++){\n" - content += " createMarker(waypointList[i],map);\n" - content += " map.enableDragging();\n" - content += " }\n" - content += " document.getElementById('map').style.top='0px';\n" - content += " document.getElementById('map').style.left='0px';\n" - content += " document.getElementById('map').style.width='100%';\n" - content += " // Add an encoded polyline.\n" - content += " var encodedPolyline = new GPolyline.fromEncoded({\n" - content += " color: \"#3333cc\",\n" - content += " weight: 10,\n" - content += " points: \"%s\",\n" %points - content += " levels: \"%s\",\n" %levels - content += " zoomFactor: 32,\n" - content += " numLevels: 4\n" - content += " });\n" - content += " map.addOverlay(encodedPolyline);\n" - content += " }\n" - content += " }\n " - content += " //]]>\n" - content += " </script>\n" - content += " </head>\n" - content += " <body onload=\"load()\" onunload=\"GUnload()\">\n" - content += " <div id=\"map\" style=\"width: 520px; height: 480px\"></div>\n" - content += " </body>\n" - content += "</html>\n" - file = fileUtils(self.htmlfile,content) - file.run() - logging.debug("<<") + content += " function load() {\n" + content += " if (GBrowserIsCompatible()) {\n" + content += " var map = new GMap2(document.getElementById(\"map\"));\n" + content += " map.addControl(new GLargeMapControl());\n" + content += " map.addControl(new GMapTypeControl());\n" + content += " map.addControl(new GScaleControl());\n" + content += " map.setCenter(new GLatLng(%f,%f), 11);\n" %(float(init_point[0]),float(init_point[1])) + content += " ovMap=new GOverviewMapControl();\n" + content += " map.addControl(ovMap);\n" + content += " mini=ovMap.getOverviewMap();\n" + content += " //Dibujamos los waypoints\n" + content += " for (i=0; i<waypointList.length; i++){\n" + content += " createMarker(waypointList[i],map);\n" + content += " map.enableDragging();\n" + content += " }\n" + content += " document.getElementById('map').style.top='0px';\n" + content += " document.getElementById('map').style.left='0px';\n" + content += " document.getElementById('map').style.width='100%';\n" + content += " // Add an encoded polyline.\n" + content += " var encodedPolyline = new GPolyline.fromEncoded({\n" + content += " color: \"#3333cc\",\n" + content += " weight: 10,\n" + content += " points: \"%s\",\n" %points + content += " levels: \"%s\",\n" %levels + content += " zoomFactor: 32,\n" + content += " numLevels: 4\n" + content += " });\n" + content += " map.addOverlay(encodedPolyline);\n" + content += " }\n" + content += " }\n " + content += " //]]>\n" + content += " </script>\n" + content += " </head>\n" + content += " <body onload=\"load()\" onunload=\"GUnload()\">\n" + content += " <div id=\"map\" style=\"width: 520px; height: 480px\"></div>\n" + content += " </body>\n" + content += "</html>\n" + file = fileUtils(self.htmlfile,content) + file.run() + logging.debug("<<") - def createErrorHtml(self): - logging.debug(">>") - content = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + def createErrorHtml(self): + logging.debug(">>") + content = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"> <head> </head> @@ -338,7 +342,7 @@ No Gpx Data </body> </html> - ''' - file = fileUtils(self.htmlfile,content) - file.run() - logging.debug("<<") + ''' + file = fileUtils(self.htmlfile,content) + file.run() + logging.debug("<<") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-30 01:32:14 UTC (rev 633) +++ pytrainer/trunk/pytrainer/main.py 2010-09-30 03:28:54 UTC (rev 634) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#632" + self.version ="1.7.2_svn#634" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() @@ -191,7 +191,7 @@ def runExtension(self,extension,id): logging.debug('>>') - print("Extension id: %s" % str(id)) + #print("Extension id: %s" % str(id)) activity = self.activitypool.get_activity(id) txtbutton,pathExtension,type = extension self.extensionClass = self.extension.importClass(pathExtension) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 01:32:22
|
Revision: 633 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=633&view=rev Author: jblance Date: 2010-09-30 01:32:14 +0000 (Thu, 30 Sep 2010) Log Message: ----------- Fix mistake in lap graph Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/graphdata.py Modified: pytrainer/trunk/pytrainer/lib/graphdata.py =================================================================== --- pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-30 01:17:56 UTC (rev 632) +++ pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-30 01:32:14 UTC (rev 633) @@ -54,8 +54,8 @@ #Second or subsequent bar, so start at last point #Which is previous left+width items = len(self.x_values) - last_left = self.x_values(items-1) - last_width = self.bar_widths(items-1) + last_left = self.x_values[items-1] + last_width = self.bar_widths[items-1] new_left = last_left+last_width print new_left self.x_values.append(new_left) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 01:18:02
|
Revision: 632 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=632&view=rev Author: jblance Date: 2010-09-30 01:17:56 +0000 (Thu, 30 Sep 2010) Log Message: ----------- Some pace by lap work... Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/lib/graphdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-09-30 00:14:04 UTC (rev 631) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-09-30 01:17:56 UTC (rev 632) @@ -74,8 +74,15 @@ #TODO #Determine graph type.... #print "Got graphtype: %s" % datalist.graphType - #Plot data - plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor, label=datalist.ylabel ) + if datalist.graphType == "plot": + #Plot data + plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor, label=datalist.ylabel ) + elif datalist.graphType == "bar": + plt.bar(datalist.x_values, datalist.y_values, datalist.bar_widths, datalist.bar_bottoms, color=datalist.linecolor, label=datalist.ylabel) + #return figure + else: + print "Unknown/unimplemented graph type: %s" % datalist.graphType + return figure #Set axis limits #plt.axis([datalist.min_x_value, datalist.max_x_value, datalist.min_y_value, datalist.max_y_value]) plt.legend(loc=0) Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-09-30 00:14:04 UTC (rev 631) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-09-30 01:17:56 UTC (rev 632) @@ -84,6 +84,8 @@ self.laps = None self.tree = None self.has_data = False + self.distance_data = {} + self.time_data = {} if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": self.us_system = True else: @@ -98,6 +100,7 @@ self._init_from_gpx_file() self._init_from_db() self._init_graph_data() + self._generate_per_lap_graphs() self.x_axis = "distance" logging.debug("<<") @@ -189,6 +192,32 @@ laps = self._get_laps_from_gpx() self.laps = laps logging.debug("<<") + + def _generate_per_lap_graphs(self): + '''Build lap based graphs...''' + logging.debug(">>") + if self.laps is None: + logging.debug("No laps to generate graphs from") + logging.debug("<<") + return + #Pace + title=_("Pace by Lap") + xlabel="%s (%s)" % (_('Distance'), self.distance_unit) + ylabel="%s (%s)" % (_('Pace'), self.pace_unit) + self.distance_data['pace_lap'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) + self.distance_data['pace_lap'].set_color('#99CCFF') + self.distance_data['pace_lap'].graphType = "bar" + for lap in self.laps: + #print lap + time = float( lap['elapsed_time'].decode('utf-8') ) # time in sql is a unicode string + dist = lap['distance']/1000 #distance in km + pace = time/(60*dist) #min/km + print "Time: %f, Dist: %f, Pace: %f" % (time, dist, pace) + if self.us_system: + self.distance_data['pace_lap'].addBars(x=km2miles(dist), y=pacekm2miles(pace)) + else: + self.distance_data['pace_lap'].addBars(x=dist, y=pace) + logging.debug("<<") def _get_laps_from_gpx(self): logging.debug(">>") @@ -217,8 +246,6 @@ def _init_graph_data(self): logging.debug(">>") - self.distance_data = {} - self.time_data = {} if self.tracklist is None: logging.debug("No tracklist in activity") logging.debug("<<") Modified: pytrainer/trunk/pytrainer/lib/graphdata.py =================================================================== --- pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-30 00:14:04 UTC (rev 631) +++ pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-30 01:17:56 UTC (rev 632) @@ -29,6 +29,8 @@ self.ylabel = ylabel self.xlabel = xlabel self.x_values = [] + self.bar_bottoms = [] + self.bar_widths = [] self.y_values = [] self.linewidth = 1 self.linecolor = '#ff0000' @@ -36,10 +38,47 @@ self.min_x_value = None self.max_y_value = None self.min_y_value = None - self.graphType = "Plot" + self.graphType = "plot" self.show_on_y1 = False logging.debug('<<') + def addBars(self, x=None, y=None): + if x is None or y is None: + #logging.debug("Must supply both x and y data points, got x:'%s' y:'%s'" % (str(x), str(y))) + return + #print('Adding point: %s %s' % (str(x), str(y))) + if len(self.x_values) == 0: + #First bar, so start a 0 + self.x_values.append(0) + else: + #Second or subsequent bar, so start at last point + #Which is previous left+width + items = len(self.x_values) + last_left = self.x_values(items-1) + last_width = self.bar_widths(items-1) + new_left = last_left+last_width + print new_left + self.x_values.append(new_left) + self.bar_widths.append(x) + self.y_values.append(y) + self.bar_bottoms.append(0) + + def addPoints(self, x=None, y=None): + if x is None or y is None: + #logging.debug("Must supply both x and y data points, got x:'%s' y:'%s'" % (str(x), str(y))) + return + #print('Adding point: %s %s' % (str(x), str(y))) + self.x_values.append(x) + self.y_values.append(y) + if self.max_x_value is None or x > self.max_x_value: + self.max_x_value = x + if self.min_x_value is None or x < self.min_x_value: + self.min_x_value = x + if self.max_y_value is None or y > self.max_y_value: + self.max_y_value = y + if self.min_y_value is None or y < self.min_y_value: + self.min_y_value = y + def set_color(self, color): ''' Helper function to set the line color @@ -86,22 +125,7 @@ str(self.y_values) ) - def addPoints(self, x=None, y=None): - if x is None or y is None: - #logging.debug("Must supply both x and y data points, got x:'%s' y:'%s'" % (str(x), str(y))) - return - #print('Adding point: %s %s' % (str(x), str(y))) - self.x_values.append(x) - self.y_values.append(y) - if self.max_x_value is None or x > self.max_x_value: - self.max_x_value = x - if self.min_x_value is None or x < self.min_x_value: - self.min_x_value = x - if self.max_y_value is None or y > self.max_y_value: - self.max_y_value = y - if self.min_y_value is None or y < self.min_y_value: - self.min_y_value = y + - Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-30 00:14:04 UTC (rev 631) +++ pytrainer/trunk/pytrainer/main.py 2010-09-30 01:17:56 UTC (rev 632) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#631" + self.version ="1.7.2_svn#632" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-30 00:14:12
|
Revision: 631 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=631&view=rev Author: jblance Date: 2010-09-30 00:14:04 +0000 (Thu, 30 Sep 2010) Log Message: ----------- Change to startup script to _hopefully_ resolve the issue with multiple installs of xulrunner Modified Paths: -------------- pytrainer/trunk/bin/pytrainer pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/bin/pytrainer =================================================================== --- pytrainer/trunk/bin/pytrainer 2010-09-29 21:57:45 UTC (rev 630) +++ pytrainer/trunk/bin/pytrainer 2010-09-30 00:14:04 UTC (rev 631) @@ -25,9 +25,36 @@ import gtk import gtk.glade import os +import glob import commands +def _max(one, two): + '''Function to determine the max of two versions of format /xx/xxx/????-1.2.3 ''' + if one is None: + return two + elif two is None: + return one + one_v = os.path.basename(one).split('-')[1] + two_v = os.path.basename(two).split('-')[1] + one_v_nos = one_v.split('.') + two_v_nos = two_v.split('.') + + for index, no in enumerate(one_v_nos): + if index >= len(two_v_nos): + return one + elif no > two_v_nos[index]: + return one + elif no < two_v_nos[index]: + return two + else: + pass + if len(one_v_nos) >= len(two_v_nos): + return one + else: + return two + + bin_path = os.path.realpath(os.path.dirname(__file__)) # directory that the pytrainer script executes from e.g. /usr/bin or /usr/local/bin base_path = os.path.dirname(bin_path) @@ -47,13 +74,28 @@ #ensure pytrainer directory is included in import path sys.path.insert(0, site_path) - from pytrainer.main import pyTrainer -os.environ['MOZILLA_FIVE_HOME']=commands.getstatusoutput("find /usr/li* -name xulrunner -exec dirname {} \; 2>/dev/null")[1] +#Determine xulrunner location +xulrunners = glob.glob("/usr/li*/xulrunner*/xulrunner") +if len(xulrunners) == 0: + #Didnt find any - fall back to old approach + xul_env = commands.getstatusoutput("find /usr/li* -name xulrunner -exec dirname {} \; 2>/dev/null")[1] +elif len(xulrunners) == 1: + #Found just one location - use that + xul_env = os.path.dirname(xulrunners[0]) +else: + #Found more than one - need to choose one... + max_version = None + for item in xulrunners: + max_version = _max(max_version, item) + xul_env = max_version +print "Using xulrunner dir: %s" % xul_env +os.environ['MOZILLA_FIVE_HOME']=xul_env + def main(argv): - pytrainer = pyTrainer(None, data_path) + pytrainer = pyTrainer(None, data_path) if __name__ == "__main__": main(sys.argv[1:]) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-29 21:57:45 UTC (rev 630) +++ pytrainer/trunk/pytrainer/main.py 2010-09-30 00:14:04 UTC (rev 631) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#630" + self.version ="1.7.2_svn#631" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-29 21:57:51
|
Revision: 630 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=630&view=rev Author: jblance Date: 2010-09-29 21:57:45 +0000 (Wed, 29 Sep 2010) Log Message: ----------- Export to csv fixes from Arnd Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/filechooser.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/save.py Modified: pytrainer/trunk/pytrainer/gui/filechooser.py =================================================================== --- pytrainer/trunk/pytrainer/gui/filechooser.py 2010-09-29 21:05:14 UTC (rev 629) +++ pytrainer/trunk/pytrainer/gui/filechooser.py 2010-09-29 21:57:45 UTC (rev 630) @@ -22,33 +22,40 @@ import gtk class FileChooser(SimpleGladeApp): - def __init__(self,data_path = None, parent = None, method = None, action = None): - self.data_path = data_path - self.filename = None - self.parent = parent - self.method = method - root="filechooserdialog" - SimpleGladeApp.__init__(self, data_path+"glade/filechooserdialog.glade", root, None) - if (action == "open"): - self.filechooserdialog.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) - filter = gtk.FileFilter() - filter.set_name("gpx files") - filter.add_pattern("*.gpx") - self.filechooserdialog.set_filter(filter) - else: - self.filechooserdialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE) - self.filechooserdialog.set_current_name("*.csv") + def __init__(self,data_path = None, parent = None, method = None, action = None): + self.data_path = data_path + self.filename = None + self.parent = parent + self.method = method + root="filechooserdialog" + SimpleGladeApp.__init__(self, data_path+"glade/filechooserdialog.glade", root, None) + if (action == "open"): + self.filechooserdialog.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) + filter = gtk.FileFilter() + filter.set_name("gpx files") + filter.add_pattern("*.gpx") + self.filechooserdialog.set_filter(filter) + else: + self.button14.set_label("Save") + self.filechooserdialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE) + print self.filechooserdialog.get_action() + self.filechooserdialog.set_current_name("*.csv") - def on_accept_clicked(self,widget): - self.filename = self.filechooserdialog.get_filename() - parentmethod = getattr(self.parent,self.method) - parentmethod() - self.closewindow() - - def on_cancel_clicked(self,widget): - self.closewindow() + def on_accept_clicked(self,widget): + try: + self.filename = self.filechooserdialog.get_filename() + except AttributeError: + if self.filename is None: + self.quit() + return + parentmethod = getattr(self.parent,self.method) + parentmethod() + self.closewindow() + + def on_cancel_clicked(self,widget): + self.closewindow() - def closewindow(self): - self.filechooserdialog.hide() - self.filechooserdialog = None - self.quit() + def closewindow(self): + #self.filechooserdialog.hide() + self.filechooserdialog = None + self.quit() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-29 21:05:14 UTC (rev 629) +++ pytrainer/trunk/pytrainer/main.py 2010-09-29 21:57:45 UTC (rev 630) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#629" + self.version ="1.7.2_svn#630" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() Modified: pytrainer/trunk/pytrainer/save.py =================================================================== --- pytrainer/trunk/pytrainer/save.py 2010-09-29 21:05:14 UTC (rev 629) +++ pytrainer/trunk/pytrainer/save.py 2010-09-29 21:57:45 UTC (rev 630) @@ -20,27 +20,38 @@ from gui.filechooser import FileChooser class Save: - def __init__(self, data_path = None, record = None): - self.record = record - self.data_path = data_path + def __init__(self, data_path = None, record = None): + self.record = record + self.data_path = data_path - def run(self): - self.filewindow = FileChooser(self.data_path, self, "savecsvfile") - self.filewindow.run() - - def savecsvfile(self): - filename = self.filewindow.filename - records = self.record.getAllrecord() - content = "" - for record in records: - line = "" - for data in record: - data = "%s" %data - data.replace(",", " ") - line += ", %s" %data - content += "%s \n" %line - file = fileUtils(filename,content) - file.run() - + def run(self): + self.filewindow = FileChooser(self.data_path, self, "savecsvfile") + self.filewindow.run() + + def savecsvfile(self): + filename = self.filewindow.filename + records = self.record.getAllrecord() + # CSV Header + content = "date,distance,time,beats,comments,average,calories\n" + for record in records: + line = "" + for i, data in enumerate(record): + if i in [1, 3, 5]: + try: + data = round(data, 2) + except: + pass + data = "%s" %data + data = data.replace(",", " ") + data = data.replace("\n", " ") + data = data.replace("\r", " ") + if i>0: + line += ",%s" %data + else: + line += "%s" %data + content += "%s\n" %line + file = fileUtils(filename,content) + file.run() + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-29 21:05:20
|
Revision: 629 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=629&view=rev Author: jblance Date: 2010-09-29 21:05:14 +0000 (Wed, 29 Sep 2010) Log Message: ----------- Extra debug and small changes for matplotlib crashes Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawArea.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawArea.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawArea.py 2010-09-29 04:01:29 UTC (rev 628) +++ pytrainer/trunk/pytrainer/gui/drawArea.py 2010-09-29 21:05:14 UTC (rev 629) @@ -57,7 +57,8 @@ logging.debug('>>') logging.debug("Type: bars | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) self.removeVboxChildren() - figure = Figure(figsize=(6,4), dpi=72) + #figure = Figure(figsize=(6,4), dpi=72) + figure = plt.figure() logging.debug("Figure: %s" % str(figure) ) numCols=len(xvalues[0]) xmod = 0.4 @@ -198,7 +199,9 @@ if numRows == 0: return width = .8 - figure = plt.figure(figsize=(6,4), dpi=72) + #figure = plt.figure(figsize=(6,4), dpi=72) + figure = plt.figure() + logging.debug("Figure: %s" % str(figure) ) axis = plt.subplot(111) ybottoms = [0] * numCols @@ -299,22 +302,28 @@ logging.debug("Type: plot | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) logging.debug('xlabel: '+str(xlabel)+' | ylabel: '+str(ylabel)+' | title: '+str(title)) self.removeVboxChildren() - figure = Figure() - figure.clf() + figure = plt.Figure() + logging.debug("Figure: %s" % str(figure) ) + #figure.clf() i = 0 for value in xvalues: if i<1: axis = figure.add_subplot(111) + logging.debug("Axis: %s" % str(axis) ) line = axis.plot(xvalues[i],yvalues[i], color=color[i]) + logging.debug("Axis plotted, Line: %s" % str(line) ) if y1_linewidth is not None: line[0].set_linewidth(y1_linewidth) linewidth = line[0].get_linewidth() axis.grid(True) + logging.debug("Axis grid on" ) for tl in axis.get_yticklabels(): tl.set_color('%s' %color[i]) + logging.debug("Ticklabels color set" ) #Draw zones on graph, eg for each lap if xzones is not None: + logging.debug("Setting xzones" ) for xzone in xzones: if xzones.index(xzone) % 2: zonecolor='b' @@ -324,13 +333,17 @@ maxX = max(xvalues[i]) if i>=1: ax2 = axis.twinx() + logging.debug("Axis2: Axis: %s" % str(ax2) ) ax2.plot(xvalues[i], yvalues[i], color=color[i]) + logging.debug("Axis2: plotted" ) for tl in ax2.get_yticklabels(): tl.set_color('%s' %color[i]) + logging.debug("Axis2: Ticklabels color set" ) maxXt = max(xvalues[i]) if maxXt > maxX: maxX = maxXt axis.set_xlabel(xlabel[i]) + logging.debug("X label set" ) i+=1 axis.set_xlim(0, maxX) @@ -349,6 +362,7 @@ axis.set_ylim(ylim_min, ylim_max) canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + logging.debug("Canvas: %s" % str(canvas)) canvas.show() self.vbox.pack_start(canvas, True, True) toolbar = NavigationToolbar(canvas, self.window) @@ -364,7 +378,9 @@ logging.debug('>>') logging.debug("Type: pie | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) self.removeVboxChildren() - figure = Figure(figsize=(6,4), dpi=72) + #figure = Figure(figsize=(6,4), dpi=72) + figure = Figure() + logging.debug("Figure: %s" % str(figure) ) axis = figure.add_subplot(111) labels = ["rest"] Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-29 04:01:29 UTC (rev 628) +++ pytrainer/trunk/pytrainer/main.py 2010-09-29 21:05:14 UTC (rev 629) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#628" + self.version ="1.7.2_svn#629" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-29 04:01:36
|
Revision: 628 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=628&view=rev Author: jblance Date: 2010-09-29 04:01:29 +0000 (Wed, 29 Sep 2010) Log Message: ----------- Additional functionality in newgraph.... Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/lib/graphdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-09-28 22:30:27 UTC (rev 627) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-09-29 04:01:29 UTC (rev 628) @@ -32,7 +32,62 @@ self.pytrainer_main = pytrainer_main #self.NEARLY_ZERO = 0.0000000000000000000001 logging.debug('<<') + + def draw(self, datalist = None, box = None, figure = None, title = None): + ''' + Draw a graph using supplied information into supplied gtk.box + + datalist = populated graphdata class (required) + box = gtk.box object (required) + figure = matplotlib figure (optional) if supplied will add graph to this figure + + return = figure + ''' + logging.debug('>>') + if box is None: + logging.error("Must supply a vbox or hbox to display the graph") + return + #Check if have a graph object + if figure is None: + #No figure, so create figure + figure = plt.figure() + #Remove any existing plots + for child in box.get_children(): + logging.debug('Removing box child: '+str(child)) + box.remove(child) + + if datalist is None: + logging.debug("drawPlot called with no data") + return + + + #Create canvas + canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + canvas.show() + + #Display title etc + plt.xlabel(datalist.xlabel) + plt.title(title) + #Removed as now in legend + #plt.ylabel(datalist.ylabel) + #TODO + #Determine graph type.... + #print "Got graphtype: %s" % datalist.graphType + #Plot data + plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor, label=datalist.ylabel ) + #Set axis limits + #plt.axis([datalist.min_x_value, datalist.max_x_value, datalist.min_y_value, datalist.max_y_value]) + plt.legend(loc=0) + #axis.set_xlim(0, data.max_x_value) + #axis.set_ylim(0, data.max_y_value) + + #Display plot + box.pack_start(canvas, True, True) + + logging.debug("<<") + return figure + def drawPlot(self, datalist = None, box = None): ''' Draw a plot style graph @@ -142,44 +197,31 @@ #TODO Check that datalist is of type dict (and contains has correct items) figure = None datalist = [] - #Loop through data items and graph the selected ones - #TODO sort for x = time.... - for item in activity.distance_data: - if activity.distance_data[item].show_on_y1: - figure = self._drawPlotTrace(activity.distance_data[item], box=box, figure=figure) + count = 0 + if activity.x_axis == "distance": + if activity.title is None or activity.title == "": + _title = "%s%s of %s on %s" % (str(activity.distance), activity.distance_unit, activity.sport_name, activity.date) + else: + _title = "%s: %s%s of %s on %s" % (activity.title, str(activity.distance), activity.distance_unit, activity.sport_name, activity.date) + + #Loop through data items and graph the selected ones + #TODO sort for x = time.... + for item in activity.distance_data: + if activity.distance_data[item].show_on_y1: + count += 1 + figure = self.draw(activity.distance_data[item], box=box, figure=figure, title=_title) + + elif activity.x_axis == "time": + _time = "%d:%02d:%02d" % (activity.time_tuple) + if activity.title is None or activity.title == "": + _title = "%s of %s on %s" % (_time, activity.sport_name, activity.date) + else: + _title = "%s: %s of %s on %s" % (activity.title, _time, activity.sport_name, activity.date) + for item in activity.time_data: + if activity.time_data[item].show_on_y1: + count += 1 + figure = self.draw(activity.time_data[item], box=box, figure=figure, title=_title) + if count == 0: + logging.debug("No items to graph.. Removing graph") + figure = self.draw(None, box=box, figure=figure) logging.debug('<<') - - def _drawPlotTrace(self, datalist = None, box = None, figure = None): - logging.debug(">>") - #Check we got required data - if box is None: - logging.error("Must supply a vbox or hbox to display the graph") - return - #Check if have gotten a graph object - if figure is None: - #No figure, so create figure - figure = plt.figure() - #Remove any existing plots - for child in box.get_children(): - logging.debug('Removing box child: '+str(child)) - box.remove(child) - #Create canvas - canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea - canvas.show() - #Display title etc - plt.xlabel(datalist.xlabel) - plt.ylabel(datalist.ylabel) - plt.title(datalist.title) - #Plot data - plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor ) - #Set axis limits - #plt.axis([datalist.min_x_value, datalist.max_x_value, datalist.min_y_value, datalist.max_y_value]) - - #axis.set_xlim(0, data.max_x_value) - #axis.set_ylim(0, data.max_y_value) - - #Display plot - box.pack_start(canvas, True, True) - - logging.debug("<<") - return figure Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-28 22:30:27 UTC (rev 627) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-29 04:01:29 UTC (rev 628) @@ -310,34 +310,66 @@ y1Frame = gtk.Frame(label="Show on Y1 Axis") y2Frame = gtk.Frame(label="Show on Y2 Axis") xvbox = gtk.VBox() - y1vbox = gtk.VBox() + y1box = gtk.Table() y2vbox = gtk.VBox() #Populate X axis data xdistancebutton = gtk.RadioButton(label="Distance") - xdistancebutton.connect("toggled", self.on_xaxischange, "distance") - xdistancebutton.set_active(True) + xtimebutton = gtk.RadioButton(group=xdistancebutton, label="Time") + if activity.x_axis == "distance": + xdistancebutton.set_active(True) + elif activity.x_axis == "time": + xtimebutton.set_active(True) + xdistancebutton.connect("toggled", self.on_xaxischange, "distance", activity) xvbox.add(xdistancebutton) - xtimebutton = gtk.RadioButton(group=xdistancebutton, label="Time") - xtimebutton.connect("toggled", self.on_xaxischange, "time") + xtimebutton.connect("toggled", self.on_xaxischange, "time", activity) xvbox.add(xtimebutton) xFrame.add(xvbox) + + row = 0 + if activity.x_axis == "distance": + data = activity.distance_data + elif activity.x_axis == "time": + data = activity.time_data + else: + print "x axis is unknown" #Populate Y axis data - for graphdata in activity.distance_data: - y1button = gtk.CheckButton(label=activity.distance_data[graphdata].title) - y1button.connect("toggled", self.on_y1change, y1vbox, graphdata, activity) - y2button = gtk.CheckButton(label=activity.distance_data[graphdata].title) + for graphdata in data: + #First Y axis... + #Create button + y1button = gtk.CheckButton(label=data[graphdata].title) + #Make button active if this data is to be displayed... + y1button.set_active(data[graphdata].show_on_y1) + #Connect handler for toggle state changes + y1button.connect("toggled", self.on_y1change, y1box, graphdata, activity) + #Attach button to container + y1box.attach(y1button, 0, 1, row, row+1, xoptions=gtk.EXPAND|gtk.FILL) + #Create a color choser + y1color = gtk.ColorButton() + #Set color to current activity color + _color = gtk.gdk.color_parse(data[graphdata].linecolor) + y1color.set_color(_color) + #Connect handler for color state changes + y1color.connect("color-set", self.on_y1colorchange, y1box, graphdata, activity) + #Attach to container + y1box.attach(y1color, 1, 2, row, row+1) + + #Second Y axis + y2button = gtk.CheckButton(label=data[graphdata].title) y2button.connect("toggled", self.on_y2change, y2vbox) - y1vbox.add(y1button) y2vbox.add(y2button) - y1Frame.add(y1vbox) + + row += 1 + + y1Frame.add(y1box) y2Frame.add(y2vbox) self.graph_data_hbox.pack_start(xFrame, expand=False, fill=True, padding=0) self.graph_data_hbox.pack_start(y1Frame, expand=False, fill=True, padding=0) self.graph_data_hbox.pack_start(y2Frame, expand=False, fill=True, padding=0) self.graph_data_hbox.show_all() - #TODO Fix... - #self.drawarearecord.drawgraph(self.record_list,self.laps) + + self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + else: logging.debug("Activity has no GPX data") #Show drop down boxes @@ -998,22 +1030,40 @@ ## Lista de eventos ## ###################### - def on_xaxischange(self, widget, data=None): + def on_xaxischange(self, widget, data=None, activity=None): '''Handler for record graph axis selection changes''' if widget.get_active(): - print data + activity.x_axis = data + self.actualize_recordgraph(activity) + + def on_y1colorchange(self, widget, box, graphdata, activity): + '''Hander for changes to y1 color selection''' + logging.debug("Setting %s to color %s" % (graphdata, widget.get_color() ) ) + if activity.x_axis == "distance": + activity.distance_data[graphdata].set_color(str(widget.get_color())) + elif activity.x_axis == "time": + activity.time_data[graphdata].set_color(str(widget.get_color())) + #Replot the activity + self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + def on_y1change(self, widget, box, graphdata, activity): '''Hander for changes to y1 selection''' #TODO Need to deal with different x options, ie distance and time... logging.debug("Y1 selection toggled: %s" % graphdata) #Loop through all options at set data correctly for child in box.get_children(): - for item in activity.distance_data: - if activity.distance_data[item].title == child.get_label(): - logging.debug( "Setting %s to %s" % (item, str(child.get_active()) ) ) - activity.distance_data[item].show_on_y1 = child.get_active() - #Plot the activity + if activity.x_axis == "distance": + for item in activity.distance_data: + if activity.distance_data[item].title == child.get_label(): + logging.debug( "Setting %s to %s" % (item, str(child.get_active()) ) ) + activity.distance_data[item].show_on_y1 = child.get_active() + elif activity.x_axis == "time": + for item in activity.time_data: + if activity.time_data[item].title == child.get_label(): + logging.debug( "Setting %s to %s" % (item, str(child.get_active()) ) ) + activity.time_data[item].show_on_y1 = child.get_active() + #Replot the activity self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) def on_y2change(self, widget, box): @@ -1257,8 +1307,12 @@ #hasta aqui revisado def on_allRecordTreeView_button_press(self, treeview, event): + ''' + Handler for clicks on recordview list (list of activities for the day) + + event.button = mouse button pressed (i.e. 1 = left, 3 = right) + ''' logging.debug(">>") - #print "on_allRecordTreeView_" x = int(event.x) y = int(event.y) time = event.time Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-09-28 22:30:27 UTC (rev 627) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-09-29 04:01:29 UTC (rev 628) @@ -66,6 +66,7 @@ maxpace - (float) maxium pace obtained during activity pace - (float) average pace for activity has_data - (bool) true if instance has data populated + x_axis - (string) distance or time, determines what will be graphed on x axis ''' def __init__(self, pytrainer_main = None, id = None): logging.debug(">>") @@ -97,6 +98,7 @@ self._init_from_gpx_file() self._init_from_db() self._init_graph_data() + self.x_axis = "distance" logging.debug("<<") def _set_units(self): @@ -226,29 +228,46 @@ xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Elevation'), self.height_unit) self.distance_data['elevation'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) - title=_("Elevation") - xlabel=_("Time (hours)") + self.distance_data['elevation'].set_color('#ff0000') + xlabel=_("Time (seconds)") self.time_data['elevation'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) + self.time_data['elevation'].set_color('#ff0000') #Speed title=_("Speed") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Speed'), self.speed_unit) self.distance_data['speed'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) + self.distance_data['speed'].set_color('#000000') + xlabel=_("Time (seconds)") + self.time_data['speed'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) + self.time_data['speed'].set_color('#000000') #Pace title=_("Pace") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Pace'), self.pace_unit) self.distance_data['pace'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) + self.distance_data['pace'].set_color('#0000ff') + xlabel=_("Time (seconds)") + self.time_data['pace'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) + self.time_data['pace'].set_color('#0000ff') #Heartrate title=_("Heart Rate") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Heart Rate'), _('bpm')) self.distance_data['hr'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) + self.distance_data['hr'].set_color('#00ff00') + xlabel=_("Time (seconds)") + self.time_data['hr'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) + self.time_data['hr'].set_color('#00ff00') #Cadence title=_("Cadence") xlabel="%s (%s)" % (_('Distance'), self.distance_unit) ylabel="%s (%s)" % (_('Cadence'), _('rpm')) self.distance_data['cadence'] = GraphData(title=title, xlabel=xlabel, ylabel=ylabel) + self.distance_data['cadence'].set_color('#cc00ff') + xlabel=_("Time (seconds)") + self.time_data['cadence'] = GraphData(title=title,xlabel=xlabel, ylabel=ylabel) + self.time_data['cadence'].set_color('#cc00ff') for track in self.tracklist: try: pace = 60/track['velocity'] @@ -262,6 +281,8 @@ self.distance_data['hr'].addPoints(x=km2miles(track['elapsed_distance']), y=track['hr']) self.distance_data['cadence'].addPoints(x=km2miles(track['elapsed_distance']), y=track['cadence']) self.time_data['elevation'].addPoints(x=track['time_elapsed'], y=m2feet(track['ele'])) + self.time_data['speed'].addPoints(x=track['time_elapsed'], y=km2miles(track['velocity'])) + self.time_data['pace'].addPoints(x=track['time_elapsed'], y=pacekm2miles(pace)) else: self.distance_data['elevation'].addPoints(x=track['elapsed_distance'], y=track['ele']) self.distance_data['speed'].addPoints(x=track['elapsed_distance'], y=track['velocity']) @@ -269,6 +290,10 @@ self.distance_data['hr'].addPoints(x=track['elapsed_distance'], y=track['hr']) self.distance_data['cadence'].addPoints(x=track['elapsed_distance'], y=track['cadence']) self.time_data['elevation'].addPoints(x=track['time_elapsed'], y=track['ele']) + self.time_data['speed'].addPoints(x=track['time_elapsed'], y=track['velocity']) + self.time_data['pace'].addPoints(x=track['time_elapsed'], y=pace) + self.time_data['hr'].addPoints(x=track['time_elapsed'], y=track['hr']) + self.time_data['cadence'].addPoints(x=track['time_elapsed'], y=track['cadence']) #Remove data with no values for item in self.distance_data.keys(): if len(self.distance_data[item]) == 0: Modified: pytrainer/trunk/pytrainer/lib/graphdata.py =================================================================== --- pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-28 22:30:27 UTC (rev 627) +++ pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-29 04:01:29 UTC (rev 628) @@ -17,6 +17,7 @@ #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import logging +import gtk class GraphData: ''' @@ -35,8 +36,25 @@ self.min_x_value = None self.max_y_value = None self.min_y_value = None + self.graphType = "Plot" self.show_on_y1 = False logging.debug('<<') + + def set_color(self, color): + ''' + Helper function to set the line color + need as some gtk.gdk color can be invalid for matplotlib + ''' + try: + #Generate 13 digit color string from supplied color + col = gtk.gdk.color_parse(color).to_string() + except ValueError: + logging.debug("Unable to parse color from '%s'" % color) + return + #Create matplotlib color string + _color = "#%s%s%s" % (col[1:3], col[5:7], col[9:11]) + logging.debug("%s color saved as: %s" % (color, _color)) + self.linecolor = _color def __len__(self): if self.x_values is None: @@ -50,6 +68,8 @@ xlabel: %s linewidth: %d linecolor: %s +graphType: %s +show on y1: %s x min max: %s %s y min max: %s %s x values: %s @@ -58,6 +78,8 @@ self.xlabel, self.linewidth, self.linecolor, + self.graphType, + str(self.show_on_y1), str(self.min_x_value), str(self.max_x_value), str(self.min_y_value), str(self.max_y_value), str(self.x_values), Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-28 22:30:27 UTC (rev 627) +++ pytrainer/trunk/pytrainer/main.py 2010-09-29 04:01:29 UTC (rev 628) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#627" + self.version ="1.7.2_svn#628" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-28 22:30:37
|
Revision: 627 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=627&view=rev Author: jblance Date: 2010-09-28 22:30:27 +0000 (Tue, 28 Sep 2010) Log Message: ----------- Elevation fixes - download progress indicator, auto server switch, cancel download Modified Paths: -------------- pytrainer/trunk/extensions/fixelevation/fixelevation.py pytrainer/trunk/pytrainer/lib/srtmlayer.py pytrainer/trunk/pytrainer/main.py Added Paths: ----------- pytrainer/trunk/pytrainer/lib/srtmdownload.py Modified: pytrainer/trunk/extensions/fixelevation/fixelevation.py =================================================================== --- pytrainer/trunk/extensions/fixelevation/fixelevation.py 2010-09-28 21:31:55 UTC (rev 626) +++ pytrainer/trunk/extensions/fixelevation/fixelevation.py 2010-09-28 22:30:27 UTC (rev 627) @@ -2,11 +2,6 @@ import os #, stat, sys import logging import gtk -#import random, re, urllib2, zipfile -#from math import floor, ceil -#from cStringIO import StringIO -#from optparse import OptionParser -#from osgeo import gdal, gdalnumeric from lxml import etree from pytrainer.lib.srtmlayer import SrtmLayer @@ -23,19 +18,19 @@ def run(self, id, activity=None): #TODO Convert to use activity... logging.debug(">>") gpx_file = "%s/gpx/%s.gpx" % (self.conf_dir, id) + ele_fixed = True + if os.path.isfile(gpx_file): # Backup original raw data as *.orig.gpx - orig_file = open(gpx_file, 'r') - orig_data = orig_file.read() - orig_file.close() - backup_file = open("%s/gpx/%s.orig.gpx" % (self.conf_dir, id), 'w') - backup_file.write(orig_data) - backup_file.close() + #orig_file = open(gpx_file, 'r') + #orig_data = orig_file.read() + #orig_file.close() + #backup_file = open("%s/gpx/%s.orig.gpx" % (self.conf_dir, id), 'w') + #backup_file.write(orig_data) + #backup_file.close() #GPX file is ok and found, so open it logging.debug("ELE GPX file: %s found, size: %d" % (gpx_file, os.path.getsize(gpx_file))) - - """ Parse GPX file to ElementTree instance. """ @@ -52,23 +47,27 @@ lon = float(trkpt.attrib['lon']) ele = trkpt.find('{%s}ele' % self._xmlns) + ele_new = self._srtm.get_elevation(lat, lon) + if not ele_new: + ele_fixed = False + break + if ele is not None: - ele.text = str(self._srtm.get_elevation(lat, lon)) + ele.text = str(ele_new) else: ele = etree.Element('ele') - ele.text = str(self._srtm.get_elevation(lat, lon)) - trkpt.append(ele) - """ - write out to original *.gpx. - """ - self._data.write( gpx_file, + ele.text = str(ele_new) + trkpt.append(ele) + if ele_fixed: + # Write out to original *.gpx. + self._data.write( gpx_file, encoding=self._data.docinfo.encoding, xml_declaration=True, pretty_print=False) + res_msg = "Elevation has been fixed." + else: + res_msg = "Elevation could not be fixed!" - - #print trkpt - res_msg = "Elevation has been fixed." #Show the user the result md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, res_msg) md.set_title(_("Elevation Correction Complete")) @@ -80,7 +79,3 @@ else: logging.error("ELE GPX file: %s NOT found!!!" % (gpx_file)) logging.debug("<<") - - - - Added: pytrainer/trunk/pytrainer/lib/srtmdownload.py =================================================================== --- pytrainer/trunk/pytrainer/lib/srtmdownload.py (rev 0) +++ pytrainer/trunk/pytrainer/lib/srtmdownload.py 2010-09-28 22:30:27 UTC (rev 627) @@ -0,0 +1,151 @@ +# -*- coding: iso-8859-1 -*- + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os +import gtk +import urllib2 +import zipfile +from cStringIO import StringIO +import logging + +""" +A list of servers providing SRTM data in GeoTIFF. +""" +srtm_server_list = [ + {'url' : 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/', 'ext' : '.ZIP', 'active' : False }, \ + {'url' : 'http://droppr.org/srtm/v4.1/6_5x5_TIFs/', 'ext' : '.zip', 'active' : True }, \ + {'url' : 'ftp://xftp.jrc.it/pub/srtmV4/tiff/' , 'ext' : '.zip', 'active' : True }, \ + {'url' : 'http://srtm.csi.cgiar.org/SRT-ZIP/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ + {'url' : 'ftp://srtm.csi.cgiar.org/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ + {'url' : 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/', 'ext' : '.ZIP', 'active' : False } + ] + +global loopActive + +class DownloadLoop: + """ + Download GeoTIFF in partial chunks. Between chunks check gtk.min_iteration + and update progressbar. Threadless Implementation. + """ + srtm_dir = os.path.expanduser('~/.pytrainer/SRTM_data') + + def __init__(self, progressbar, label, tile_name): + self.progressbar = progressbar + self.label = label + self.tile_name = tile_name + + def run(self): + logging.debug(">>") + global loopActive + + #print 'Loop started', loopActive + + srtm_filename = '%s.tif' % self.tile_name + if not os.path.isdir(self.srtm_dir): + os.mkdir(self.srtm_dir) + + urlfile = self.get_urlfile() + size_total = int(urlfile.info().getheader('Content-Length').strip()) + + if size_total == 0: + loopActive = False + #print 'Total size:', size_total + + size_chunk = 4096 #8192 + size_got = 0 + zobj = StringIO() + + while loopActive: + while gtk.events_pending(): + gtk.main_iteration(block = False) + chunk = urlfile.read(size_chunk) + size_got+= size_chunk + if chunk: + zobj.write( chunk ) + size_rel = min (1.0, size_got / (1.0 * size_total)) + #print "Read %s Percent." % (round(100*size_rel, 1)) + self.progressbar.set_fraction( size_rel ) + else: + loopActive = False + if size_rel == 1.0: + print "start unzip" + z = zipfile.ZipFile(zobj) + srtm_path = os.path.join(self.srtm_dir, srtm_filename) + out_file = open(srtm_path, 'w') + out_file.write(z.read(srtm_filename)) + z.close() + zobj.close + out_file.close() + logging.debug("<<") + return True # Hooray, got file + logging.debug("<<") + return False + + def get_urlfile(self): + """ Go through SRTM Servers """ + logging.debug('--') + for server in srtm_server_list: + url = '%s%s%s' % (server['url'], self.tile_name, server['ext']) + print "Attempting to get URL: %s" % url + logging.debug("Attempting to get URL: %s" % url) + try: + urlfile = urllib2.urlopen( url ) + self.label.set_text(str(url)) + return urlfile + except: + print '%s FAILED' % url + logging.debug('%s FAILED' % url) + pass + + +def main_quit(obj): + logging.debug("--") + global loopActive + print 'main_quit entered' + loopActive = False + +def download(tile_name): + logging.debug(">>") + global loopActive + loopActive = True + result = False + window = gtk.Dialog() + window.set_title('Download GeoTIFF') + labelH = gtk.Label('<b>Downloading Tile %s</b>' % tile_name) + labelH.set_use_markup(True) + labelH.set_alignment(0, 1) + + label = gtk.Label('Searching for Server ...') + progressbar = gtk.ProgressBar() + + window.connect('destroy', main_quit) + button = gtk.Button(stock=gtk.STOCK_CANCEL) + button.connect("clicked", main_quit) + + window.vbox.pack_start(labelH, expand=False, padding=3) + window.vbox.pack_start(label, expand=False, padding=3) + window.vbox.pack_start(progressbar, expand=False, padding=3) + window.action_area.pack_start(button, expand=False) + window.show_all() + + lp = DownloadLoop(progressbar, label, tile_name) + result = lp.run() + try: + window.destroy() + except: + pass + logging.debug("<<") + return result Modified: pytrainer/trunk/pytrainer/lib/srtmlayer.py =================================================================== --- pytrainer/trunk/pytrainer/lib/srtmlayer.py 2010-09-28 21:31:55 UTC (rev 626) +++ pytrainer/trunk/pytrainer/lib/srtmlayer.py 2010-09-28 22:30:27 UTC (rev 627) @@ -8,20 +8,8 @@ from osgeo import gdal, gdalnumeric from pytrainer.lib.srtmtiff import SrtmTiff +import srtmdownload -""" -A list of servers providing SRTM data in GeoTIFF -""" -srtm_server_list = [ - {'url' : 'http://droppr.org/srtm/v4.1/6_5x5_TIFs/', 'ext' : '.zip', 'active' : True }, \ - {'url' : 'ftp://xftp.jrc.it/pub/srtmV4/tiff/' , 'ext' : '.zip', 'active' : True }, \ - {'url' : 'http://srtm.csi.cgiar.org/SRT-ZIP/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ - {'url' : 'ftp://srtm.csi.cgiar.org/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ - {'url' : 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/', 'ext' : '.ZIP', 'active' : False } - ] -srtm_server = srtm_server_list[0] - - class SrtmLayer(object): """ Provides an interface to SRTM elevation data stored in GeoTIFF files. @@ -38,39 +26,7 @@ """ _cache = {} - - def _download_srtm_tiff(self, srtm_filename): - """ - Download and unzip GeoTIFF file. - """ - #msg = _("Downloading SRTM Data from server. This might take some time...") - #md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) - #md.set_title(_("Downloading SRTM Data")) - #md.set_modal(True) - #md.show() - - srtm_dir = os.path.expanduser('~/.pytrainer/SRTM_data') - if not os.path.isdir(srtm_dir): - os.mkdir(srtm_dir) - - logging.info('Downloading SRTM data file, it may take some time ...') - #url = 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/%s.ZIP' % srtm_filename[:-4] - url = '%s%s%s' % (srtm_server['url'], srtm_filename[:-4],srtm_server['ext'] ) - print "Attempting to get URL: %s" % url - zobj = StringIO() - zobj.write(urllib2.urlopen(url).read()) - z = zipfile.ZipFile(zobj) - print "Got URL: %s" % url - - srtm_path = os.path.join(srtm_dir, srtm_filename) - out_file = open(srtm_path, 'w') - out_file.write(z.read(srtm_filename)) - - z.close() - out_file.close() - #md.destroy() - - + def get_srtm_filename(self, lat, lon): """ Filename of GeoTIFF file containing data with given coordinates. @@ -81,7 +37,6 @@ ilon = ceil(colmin / 6000.0) ilat = ceil(rowmin / 6000.0) - #return 'srtm_%02d_%02d.TIF' % (ilon, ilat) return 'srtm_%02d_%02d.tif' % (ilon, ilat) def get_elevation(self, lat, lon): @@ -92,7 +47,9 @@ if srtm_filename not in self._cache: srtm_path = os.path.join(os.path.expanduser('~/.pytrainer/SRTM_data'), srtm_filename) if not os.path.isfile(srtm_path): - self._download_srtm_tiff(srtm_filename) + result = srtmdownload.download( srtm_filename[:-4] ) + if not result: + return False else: print "File already downloaded (%s)" % srtm_filename Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-28 21:31:55 UTC (rev 626) +++ pytrainer/trunk/pytrainer/main.py 2010-09-28 22:30:27 UTC (rev 627) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#626" + self.version ="1.7.2_svn#627" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-28 21:32:02
|
Revision: 626 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=626&view=rev Author: jblance Date: 2010-09-28 21:31:55 +0000 (Tue, 28 Sep 2010) Log Message: ----------- Anonymise fixes for OSM extension from Arnd Modified Paths: -------------- pytrainer/trunk/extensions/openstreetmap/openstreetmap.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/extensions/openstreetmap/openstreetmap.py =================================================================== --- pytrainer/trunk/extensions/openstreetmap/openstreetmap.py 2010-09-28 21:22:07 UTC (rev 625) +++ pytrainer/trunk/extensions/openstreetmap/openstreetmap.py 2010-09-28 21:31:55 UTC (rev 626) @@ -13,277 +13,271 @@ import mimetools, mimetypes class openstreetmap: - def __init__(self, parent = None, pytrainer_main = None, conf_dir = None, options = None): - self.parent = parent - self.pytrainer_main = pytrainer_main - self.options = options - self.conf_dir = conf_dir - self.description = " " - self.tags = "" - self.visibility = "private" + def __init__(self, parent = None, pytrainer_main = None, conf_dir = None, options = None): + self.parent = parent + self.pytrainer_main = pytrainer_main + self.options = options + self.conf_dir = conf_dir + self.description = " " + self.tags = "" + self.visibility = "private" - def run(self, id, activity=None): #TODO Convert to use activity... - logging.debug(">>") - uri = "http://api.openstreetmap.org/api/0.6/gpx/create" #URI for uploading traces to OSM - if 'username' not in self.options or self.options['username'] == "" or 'password' not in self.options or self.options['password'] == "": - logging.error("Must have username and password configured") - msg = _("Must have username and password configured") - md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) - md.set_title(_("Openstreetmap Extension Error")) - md.run() - md.destroy() - return - username = self.options['username'] - password = self.options['password'] - gpx_file = "%s/gpx/%s.gpx" % (self.conf_dir, id) - if os.path.isfile(gpx_file): - #GPX file is ok and found, so open it - logging.debug("GPX file: %s found, size: %d" % (gpx_file, os.path.getsize(gpx_file))) - f = open(gpx_file, 'r') - file_contents = f.read() - #TODO Fix to use etree functionality..... - if file_contents.find("<?xml version='1.0' encoding='ASCII'?>") != -1: - logging.debug("GPX file: %s has ASCII encoding - updating to UTF-8 for OSM support" % gpx_file) - f.close() #Close readonly file - f = open(gpx_file, 'w') #and open file for writing - file_contents = file_contents.replace("<?xml version='1.0' encoding='ASCII'?>","<?xml version='1.0' encoding='UTF-8'?>", 1) - f.write(file_contents) #Write new content - f.close() #Close - f = open(gpx_file, 'r') #Reopen in readonly mode - #Get extra info from user - response=self.display_options_window() - if not response==gtk.RESPONSE_ACCEPT: - f.close() - logging.debug("User abort") - return - if self.makeanon: - logging.debug("User requested anonymising of GPX data") - f.close() #Close standard gpxfile - gpx_file = self.make_gpx_private(gpx_file) - f = open(gpx_file, 'r') #Open anonymous gpxfile in readonly mode - fields = (("description",self.description), ("tags",self.tags), ("visibility",self.visibility)) - logging.debug("Added fields: %s" % str(fields)) - #Multipart encode the request - boundary, body = self.multipart_encode(fields=fields, files=(("file", f),)) - content_type = 'multipart/form-data; boundary=%s' % boundary - #Finished with the file so close it - f.close() - #Add the http headers to the request - h = httplib2.Http() - headers = { - 'Content-Type': content_type - } - #Add basic authentication credentials to the request - h.add_credentials(username, password) - #Show user something is happening - msg = _("Posting GPX trace to Openstreetmap\n\nPlease wait this could take several minutes") - md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) - md.set_title(_("Openstreetmap Extension Processing")) - md.set_modal(True) - md.show() - while gtk.events_pending(): # This allows the GUI to update - gtk.main_iteration() # before completion of this entire action - logging.debug("before request posting") - #POST request to OSM - res, content = h.request(uri, 'POST', body=body, headers=headers) - logging.debug("after request posting") - logging.debug("Got response status: %s, reason: %s, content: %s" % (res.status, res.reason, content)) - if res.reason == 'OK': - res_msg = "Successfully posted to OSM.\nYou should get an email with the outcome of the upload soon\n\nTrace id is %s" % content - else: - res_msg = "Some error occured\nGot a status %s, reason %s\nContent was: %s" % (res.status, res.reason, content) - #Close 'Please wait' dialog - md.destroy() - #Show the user the result - md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, res_msg) - md.set_title(_("Openstreetmap Extension Upload Complete")) - md.set_modal(False) - md.run() - md.destroy() + def run(self, id, activity=None): #TODO Convert to use activity... + logging.debug(">>") + uri = "http://api.openstreetmap.org/api/0.6/gpx/create" #URI for uploading traces to OSM + if 'username' not in self.options or self.options['username'] == "" or 'password' not in self.options or self.options['password'] == "": + logging.error("Must have username and password configured") + msg = _("Must have username and password configured") + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) + md.set_title(_("Openstreetmap Extension Error")) + md.run() + md.destroy() + return + username = self.options['username'] + password = self.options['password'] + gpx_file = "%s/gpx/%s.gpx" % (self.conf_dir, id) + if os.path.isfile(gpx_file): + #GPX file is ok and found, so open it + logging.debug("GPX file: %s found, size: %d" % (gpx_file, os.path.getsize(gpx_file))) + f = open(gpx_file, 'r') + file_contents = f.read() + #TODO Fix to use etree functionality..... + if file_contents.find("<?xml version='1.0' encoding='ASCII'?>") != -1: + logging.debug("GPX file: %s has ASCII encoding - updating to UTF-8 for OSM support" % gpx_file) + f.close() #Close readonly file + f = open(gpx_file, 'w') #and open file for writing + file_contents = file_contents.replace("<?xml version='1.0' encoding='ASCII'?>","<?xml version='1.0' encoding='UTF-8'?>", 1) + f.write(file_contents) #Write new content + f.close() #Close + f = open(gpx_file, 'r') #Reopen in readonly mode + #Get extra info from user + response=self.display_options_window() + if not response==gtk.RESPONSE_ACCEPT: + f.close() + logging.debug("User abort") + return + if self.makeanon: + logging.debug("User requested anonymising of GPX data") + f.close() #Close standard gpxfile + gpx_file = self.make_gpx_private(gpx_file) + f = open(gpx_file, 'r') #Open anonymous gpxfile in readonly mode + fields = (("description",self.description), ("tags",self.tags), ("visibility",self.visibility)) + logging.debug("Added fields: %s" % str(fields)) + #Multipart encode the request + boundary, body = self.multipart_encode(fields=fields, files=(("file", f),)) + content_type = 'multipart/form-data; boundary=%s' % boundary + #Finished with the file so close it + f.close() + #Add the http headers to the request + h = httplib2.Http() + headers = { + 'Content-Type': content_type + } + #Add basic authentication credentials to the request + h.add_credentials(username, password) + #Show user something is happening + msg = _("Posting GPX trace to Openstreetmap\n\nPlease wait this could take several minutes") + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) + md.set_title(_("Openstreetmap Extension Processing")) + md.set_modal(True) + md.show() + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + logging.debug("before request posting") + #POST request to OSM + res, content = h.request(uri, 'POST', body=body, headers=headers) + logging.debug("after request posting") + logging.debug("Got response status: %s, reason: %s, content: %s" % (res.status, res.reason, content)) + if res.reason == 'OK': + res_msg = "Successfully posted to OSM.\nYou should get an email with the outcome of the upload soon\n\nTrace id is %s" % content + else: + res_msg = "Some error occured\nGot a status %s, reason %s\nContent was: %s" % (res.status, res.reason, content) + #Close 'Please wait' dialog + md.destroy() + #Show the user the result + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, res_msg) + md.set_title(_("Openstreetmap Extension Upload Complete")) + md.set_modal(False) + md.run() + md.destroy() - else: - logging.error("GPX file: %s NOT found!!!" % (gpx_file)) - logging.debug("<<") + else: + logging.error("GPX file: %s NOT found!!!" % (gpx_file)) + logging.debug("<<") - def display_options_window(self): - self.prefwindow = gtk.Dialog(title=_("Please add any additional information for this upload"), parent=None, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) - self.prefwindow.set_modal(False) - table = gtk.Table(1,2) - self.entryList = [] - #Add description - label = gtk.Label("<b>Description</b>") - label.set_use_markup(True) - entry = gtk.Entry() - self.entryList.append(entry) - table.attach(label,0,1,0,1) - table.attach(entry,1,2,0,1) - #Add tags - label = gtk.Label("<b>Tags</b>") - label.set_use_markup(True) - entry = gtk.Entry() - self.entryList.append(entry) - table.attach(label,0,1,1,2) - table.attach(entry,1,2,1,2) - #Add visibility - label = gtk.Label("<b>Visibility</b>") - label.set_use_markup(True) - combobox = gtk.combo_box_new_text() - combobox.append_text("private") - combobox.append_text("public") - combobox.append_text("trackable") - combobox.append_text("identifiable") - combobox.set_active(0) - table.attach(combobox,1,2,2,3) - self.entryList.append(combobox) - table.attach(label,0,1,2,3) - #Add anonymize GPX option - label = gtk.Label("<b>Anonymize GPX Data</b>") - label.set_use_markup(True) - table.attach(label,0,1,3,4) - checkbutton = gtk.CheckButton() - table.attach(checkbutton,1,2,3,4) - self.entryList.append(checkbutton) - #Buld dialog and show - self.prefwindow.vbox.pack_start(table) - self.prefwindow.show_all() - self.prefwindow.connect("response", self.on_options_ok_clicked) - response=self.prefwindow.run() - self.prefwindow.destroy() - return response + def display_options_window(self): + self.prefwindow = gtk.Dialog(title=_("Please add any additional information for this upload"), parent=None, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) + self.prefwindow.set_modal(False) + table = gtk.Table(1,2) + self.entryList = [] + #Add description + label = gtk.Label("<b>Description</b>") + label.set_use_markup(True) + entry = gtk.Entry() + self.entryList.append(entry) + table.attach(label,0,1,0,1) + table.attach(entry,1,2,0,1) + #Add tags + label = gtk.Label("<b>Tags</b>") + label.set_use_markup(True) + entry = gtk.Entry() + self.entryList.append(entry) + table.attach(label,0,1,1,2) + table.attach(entry,1,2,1,2) + #Add visibility + label = gtk.Label("<b>Visibility</b>") + label.set_use_markup(True) + combobox = gtk.combo_box_new_text() + combobox.append_text("private") + combobox.append_text("public") + combobox.append_text("trackable") + combobox.append_text("identifiable") + combobox.set_active(0) + table.attach(combobox,1,2,2,3) + self.entryList.append(combobox) + table.attach(label,0,1,2,3) + #Add anonymize GPX option + label = gtk.Label("<b>Anonymize GPX Data</b>") + label.set_use_markup(True) + table.attach(label,0,1,3,4) + checkbutton = gtk.CheckButton() + table.attach(checkbutton,1,2,3,4) + self.entryList.append(checkbutton) + #Buld dialog and show + self.prefwindow.vbox.pack_start(table) + self.prefwindow.show_all() + self.prefwindow.connect("response", self.on_options_ok_clicked) + response=self.prefwindow.run() + self.prefwindow.destroy() + return response - def on_options_ok_clicked(self, widget, response_id): - if not response_id == gtk.RESPONSE_ACCEPT: - return response_id - self.description = self.entryList[0].get_text() - if self.description == "": - logging.debug("A description is required - setting to default") - self.description = "Uploaded from pytrainer" - self.tags = self.entryList[1].get_text() - self.visibility = self.entryList[2].get_active_text() - self.makeanon = self.entryList[3].get_active() - logging.debug("Description: %s, tags: %s, visibility: %s, makeanon: %s" % ( self.description, self.tags, self.visibility, self.makeanon) ) + def on_options_ok_clicked(self, widget, response_id): + if not response_id == gtk.RESPONSE_ACCEPT: + return response_id + self.description = self.entryList[0].get_text() + if self.description == "": + logging.debug("A description is required - setting to default") + self.description = "Uploaded from pytrainer" + self.tags = self.entryList[1].get_text() + self.visibility = self.entryList[2].get_active_text() + self.makeanon = self.entryList[3].get_active() + logging.debug("Description: %s, tags: %s, visibility: %s, makeanon: %s" % ( self.description, self.tags, self.visibility, self.makeanon) ) - def multipart_encode(self, fields, files, boundary = None, buffer = None): - ''' - Multipart encode data for posting - from examples at from http://odin.himinbi.org/MultipartPostHandler.py & http://bitworking.org/projects/httplib2/doc/html/libhttplib2.html - ''' - if boundary is None: - boundary = mimetools.choose_boundary() - if buffer is None: - buffer = '' - for (key, value) in fields: - buffer += '--%s\r\n' % boundary - buffer += 'Content-Disposition: form-data; name="%s"' % key - buffer += '\r\n\r\n' + value + '\r\n' - print files - for (key, fd) in files: - file_size = os.fstat(fd.fileno())[stat.ST_SIZE] - filename = os.path.basename(fd.name) - contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' - buffer += '--%s\r\n' % boundary - buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename) - buffer += 'Content-Type: %s\r\n' % contenttype - # buffer += 'Content-Length: %s\r\n' % file_size - fd.seek(0) - buffer += '\r\n' + fd.read() + '\r\n' - buffer += '--%s--\r\n\r\n' % boundary - return boundary, buffer - - def make_gpx_private(self, gpx_file=None): - ''' - wipes out private data from gpx files - converts laps to waypoints - ''' - logging.debug(">>") - if gpx_file is None: - return None - - filen = os.path.basename(gpx_file) - tmpdir = self.pytrainer_main.profile.tmpdir - anon_gpx_file = "%s/%s" % (tmpdir, filen) - - # Filtered home area, example Berlin - # corners NorthEast and SouthWest - #TODO This needs to be a config item.... - NE_LAT = 52.518 - NE_LON = 13.408 - SW_LAT = 52.4 - SW_LON = 13.3 + def multipart_encode(self, fields, files, boundary = None, buffer = None): + ''' + Multipart encode data for posting + from examples at from http://odin.himinbi.org/MultipartPostHandler.py & http://bitworking.org/projects/httplib2/doc/html/libhttplib2.html + ''' + if boundary is None: + boundary = mimetools.choose_boundary() + if buffer is None: + buffer = '' + for (key, value) in fields: + buffer += '--%s\r\n' % boundary + buffer += 'Content-Disposition: form-data; name="%s"' % key + buffer += '\r\n\r\n' + value + '\r\n' + print files + for (key, fd) in files: + file_size = os.fstat(fd.fileno())[stat.ST_SIZE] + filename = os.path.basename(fd.name) + contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + buffer += '--%s\r\n' % boundary + buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename) + buffer += 'Content-Type: %s\r\n' % contenttype + # buffer += 'Content-Length: %s\r\n' % file_size + fd.seek(0) + buffer += '\r\n' + fd.read() + '\r\n' + buffer += '--%s--\r\n\r\n' % boundary + return boundary, buffer + + def make_gpx_private(self, gpx_file=None): + ''' + wipes out private data from gpx files + converts laps to waypoints + ''' + logging.debug(">>") + if gpx_file is None: + return None + + filen = os.path.basename(gpx_file) + tmpdir = self.pytrainer_main.profile.tmpdir + anon_gpx_file = "%s/%s" % (tmpdir, filen) + + # Filtered home area, example Berlin + # corners NorthEast and SouthWest + #TODO This needs to be a config item.... + NE_LAT = 52.518 + NE_LON = 13.408 + SW_LAT = 52.4 + SW_LON = 13.3 - # Config parameters, not used yet - FILTER_BOX = True - ERASE_TIME = True - LAP_TO_WAYPOINT = True + # Config parameters, not used yet + FILTER_BOX = True + ERASE_TIME = True + LAP_TO_WAYPOINT = True - tree = etree.parse(gpx_file) - _xmlns = tree.getroot().nsmap[None] - _trkpt_path = '{%s}trk/{%s}trkseg/{%s}trkpt' % (_xmlns, _xmlns, _xmlns) - # namespace of gpx files - NS = dict(ns='http://www.topografix.com/GPX/1/1') + tree = etree.parse(gpx_file) + _xmlns = tree.getroot().nsmap[None] + _trkpt_path = '{%s}trk/{%s}trkseg/{%s}trkpt' % (_xmlns, _xmlns, _xmlns) + # namespace of gpx files + NS = dict(ns='http://www.topografix.com/GPX/1/1') - myroot = tree.getroot() - gpxdataNS = string.Template(\ - ".//{http://www.cluetrust.com/XML/GPXDATA/1/0}$tag") - lapTag = gpxdataNS.substitute(tag="lap") - endPointTag = gpxdataNS.substitute(tag="endPoint") - triggerTag = gpxdataNS.substitute(tag="trigger") - laps = tree.findall(lapTag) + myroot = tree.getroot() + gpxdataNS = string.Template(\ + ".//{http://www.cluetrust.com/XML/GPXDATA/1/0}$tag") + lapTag = gpxdataNS.substitute(tag="lap") + endPointTag = gpxdataNS.substitute(tag="endPoint") + triggerTag = gpxdataNS.substitute(tag="trigger") + laps = tree.findall(lapTag) - #new_waypoints=[] - mygpx = tree.find('gpx') + mygpx = tree.find('gpx') - for lap in laps: - trigger = lap.find(triggerTag) - # Watch out for manually triggered laps - if trigger.text == 'manual': - endPoint = lap.find(endPointTag) - lat = endPoint.get("lat") - lon = endPoint.get("lon") - print lat,lon - #new_waypoints.append([lat,lon]) - #add waypoint - etree.SubElement(myroot, 'wpt', attrib= {'lat':lat, 'lon':lon}) + for lap in laps: + trigger = lap.find(triggerTag) + # Watch out for manually triggered laps + if trigger.text == 'manual': + endPoint = lap.find(endPointTag) + lat = endPoint.get("lat") + lon = endPoint.get("lon") + # Create waypt if not in home box + if not ((SW_LAT < float(lat) < NE_LAT) and (SW_LON < float(lon) < NE_LON)): + etree.SubElement(myroot, 'wpt', attrib= {'lat':lat, 'lon':lon}) + etree.strip_attributes(myroot, 'creator') - etree.strip_attributes(myroot, 'creator') + # Wipe out home box + for trkpt in tree.findall(_trkpt_path): + lat = float(trkpt.attrib['lat']) + lon = float(trkpt.attrib['lon']) + if (lat < NE_LAT) & (lon < NE_LON) & (lat > SW_LAT) & (lon > SW_LON): + par = trkpt.getparent() + par.remove(trkpt) - # Wipe out home box - for trkpt in tree.findall(_trkpt_path): - lat = float(trkpt.attrib['lat']) - lon = float(trkpt.attrib['lon']) - #print lat, lon - if (lat < NE_LAT) & (lon < NE_LON) & (lat > SW_LAT) & (lon > SW_LON): - #print lat,lon - par = trkpt.getparent() - par.remove(trkpt) + time = tree.xpath('//ns:trkpt/ns:time', namespaces=NS) + for i in time: + i.text = '1970-01-01T00:00:00+00:00' + # osm regards <time> as mandatory. gnaa. + ext = tree.xpath('//ns:gpx/ns:extensions', namespaces=NS) + for i in ext: + par = i.getparent() + par.remove(i) + meta = tree.xpath('//ns:gpx/ns:metadata', namespaces=NS) + for i in meta: + par = i.getparent() + par.remove(i) + ele = tree.xpath('//ns:trkpt/ns:ele', namespaces=NS) + for i in ele: + par = i.getparent() + par.remove(i) - time = tree.xpath('//ns:trkpt/ns:time', namespaces=NS) - for i in time: - i.text = '1970-01-01T00:00:00+00:00' - # osm regards <time> as mandatory. gnaa. + # test schema on cleaned xml-tree + # gpx.xsd from http://www.topografix.com/gpx.asp - ext = tree.xpath('//ns:gpx/ns:extensions', namespaces=NS) - for i in ext: - par = i.getparent() - par.remove(i) - meta = tree.xpath('//ns:gpx/ns:metadata', namespaces=NS) - for i in meta: - par = i.getparent() - par.remove(i) - ele = tree.xpath('//ns:trkpt/ns:ele', namespaces=NS) - for i in ele: - par = i.getparent() - par.remove(i) + #xmlschema = etree.XMLSchema(etree.parse('gpx.xsd')) + #xmlschema.validate(tree) - # test schema on cleaned xml-tree - # gpx.xsd from http://www.topografix.com/gpx.asp + # write new gpx file + tree.write(anon_gpx_file, pretty_print=False, xml_declaration=True, encoding='UTF-8') + logging.debug("<<") + return anon_gpx_file - #xmlschema = etree.XMLSchema(etree.parse('gpx.xsd')) - #xmlschema.validate(tree) - - # write new gpx file - tree.write(anon_gpx_file, pretty_print=False, xml_declaration=True, encoding='UTF-8') - logging.debug("<<") - return anon_gpx_file - Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-28 21:22:07 UTC (rev 625) +++ pytrainer/trunk/pytrainer/main.py 2010-09-28 21:31:55 UTC (rev 626) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#625" + self.version ="1.7.2_svn#626" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-28 21:22:14
|
Revision: 625 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=625&view=rev Author: jblance Date: 2010-09-28 21:22:07 +0000 (Tue, 28 Sep 2010) Log Message: ----------- Extra debug in drawArea, to attempt to determine graphing issues Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawArea.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawArea.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawArea.py 2010-09-28 03:39:34 UTC (rev 624) +++ pytrainer/trunk/pytrainer/gui/drawArea.py 2010-09-28 21:22:07 UTC (rev 625) @@ -26,415 +26,436 @@ import logging class DrawArea: - def __init__(self, vbox = None, window = None): - logging.debug('>>') - #self.figure = Figure(figsize=(6,4), dpi=72) - #self.axis = self.figure.add_subplot(111) - self.vbox = vbox - self.window = window - #self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea - #self.drawDefault() - self.NEARLY_ZERO = 0.0000000000000000000001 - logging.debug('<<') + def __init__(self, vbox = None, window = None): + logging.debug('>>') + #self.figure = Figure(figsize=(6,4), dpi=72) + #self.axis = self.figure.add_subplot(111) + self.vbox = vbox + self.window = window + #self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea + #self.drawDefault() + self.NEARLY_ZERO = 0.0000000000000000000001 + logging.debug('<<') - def stadistics(self,type,xvalues,yvalues,xlabel,ylabel,title,color=None,zones=None): - logging.debug('>>') - if len(xvalues[0]) < 1: - #self.drawDefault() - return False - #logging.debug('xvalues: '+str(xvalues)) - #logging.debug('yvalues: '+str(yvalues)) - #logging.debug("Type: "+type+" | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) - if type == "bars": - self.drawBars(xvalues,yvalues,xlabel,ylabel,title,color) - elif type == "plot": - self.drawPlot(xvalues,yvalues,xlabel,ylabel,title,color,zones) - elif type == "pie": - self.drawPie(xvalues,yvalues,xlabel,ylabel,title,color,zones) - logging.debug('<<') + def stadistics(self,type,xvalues,yvalues,xlabel,ylabel,title,color=None,zones=None): + logging.debug('>>') + if len(xvalues[0]) < 1: + #self.drawDefault() + return False + #logging.debug('xvalues: '+str(xvalues)) + #logging.debug('yvalues: '+str(yvalues)) + #logging.debug("Type: "+type+" | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) + if type == "bars": + self.drawBars(xvalues,yvalues,xlabel,ylabel,title,color) + elif type == "plot": + self.drawPlot(xvalues,yvalues,xlabel,ylabel,title,color,zones) + elif type == "pie": + self.drawPie(xvalues,yvalues,xlabel,ylabel,title,color,zones) + logging.debug('<<') - def drawBars(self,xvalues,yvalues,xlabel,ylabel,title,color): - logging.debug('>>') - logging.debug("Type: bars | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) - self.removeVboxChildren() - figure = Figure(figsize=(6,4), dpi=72) - numCols=len(xvalues[0]) - xmod = 0.4 - self.showGraph=False - axis = figure.add_subplot(111) + def drawBars(self,xvalues,yvalues,xlabel,ylabel,title,color): + logging.debug('>>') + logging.debug("Type: bars | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) + self.removeVboxChildren() + figure = Figure(figsize=(6,4), dpi=72) + logging.debug("Figure: %s" % str(figure) ) + numCols=len(xvalues[0]) + xmod = 0.4 + self.showGraph=False + axis = figure.add_subplot(111) + logging.debug("Axis: %s" % str(axis) ) - if len(xvalues) == 1: #One axis - barWidth = 0.8 - barOffset = 0.1 - elif len(xvalues) == 2: #Twin axes - barWidth = 0.4 - barOffset = 0.1 - else: #Error - return + if len(xvalues) == 1: #One axis + barWidth = 0.8 + barOffset = 0.1 + logging.debug("One axis, barWidth %f, barOffset %f" % (barWidth, barOffset) ) + elif len(xvalues) == 2: #Twin axes + barWidth = 0.4 + barOffset = 0.1 + logging.debug("Twin axes, barWidth %f, barOffset %f" % (barWidth, barOffset) ) + else: #Error + logging.debug("Error: invalid number of axes" ) + return - axis.set_xlabel(xlabel[0]) - axis.set_ylabel(ylabel[0]) - xvals = [x+barOffset for x in range(0, numCols)] - yvals = [0] * numCols - for i in range(0, numCols): - yval = yvalues[0][i] - if float(yval) > 0.0: - self.showGraph=True - else: - yval = self.NEARLY_ZERO - yvals[i] = yval - if self.showGraph: - axis.bar(xvals, yvals, barWidth, color=color[0], align='edge') - else: #Only zero results - pass + axis.set_xlabel(xlabel[0]) + axis.set_ylabel(ylabel[0]) + logging.debug("Labels set x: %s, y: %s" % (xlabel[0], ylabel[0]) ) + xvals = [x+barOffset for x in range(0, numCols)] + yvals = [0] * numCols + for i in range(0, numCols): + yval = yvalues[0][i] + if float(yval) > 0.0: + self.showGraph=True + else: + yval = self.NEARLY_ZERO + yvals[i] = yval + if self.showGraph: + logging.debug("Drawing bars") + axis.bar(xvals, yvals, barWidth, color=color[0], align='edge') + else: #Only zero results + logging.debug("No results to draw") + pass - axis.grid(True) - axis.set_title("%s" %(title[0])) - for tl in axis.get_yticklabels(): - tl.set_color('%s' %color[0]) + axis.grid(True) + axis.set_title("%s" %(title[0])) + logging.debug("Setting title to: %s" % title[0]) + for tl in axis.get_yticklabels(): + logging.debug("Setting ticklabel color %s" % color[0]) + tl.set_color('%s' %color[0]) - if len(xvalues) == 2: #Display twin axis - ax2 = axis.twinx() - xvals = [x+barOffset+barWidth for x in range(0, numCols)] - for i in range(0, numCols): - yval = yvalues[1][i] - if float(yval) > 0.0: - self.showGraph=True - else: - yval = self.NEARLY_ZERO - yvals[i] = yval - if self.showGraph: - ax2.bar(xvals, yvals, barWidth, color=color[1], align='edge') - ax2.set_ylabel(ylabel[1]) - else: #Only zero results - pass - for tl in ax2.get_yticklabels(): - tl.set_color('%s' %color[1]) - axis.set_title("%s vs %s" %(title[0],title[1])) + if len(xvalues) == 2: #Display twin axis + ax2 = axis.twinx() + logging.debug("Axis 2: Twin axis: %s " % str(ax2)) + xvals = [x+barOffset+barWidth for x in range(0, numCols)] + for i in range(0, numCols): + yval = yvalues[1][i] + if float(yval) > 0.0: + self.showGraph=True + else: + yval = self.NEARLY_ZERO + yvals[i] = yval + if self.showGraph: + logging.debug("Axis 2: Drawing bars") + ax2.bar(xvals, yvals, barWidth, color=color[1], align='edge') + logging.debug("Axis 2: Label set y: %s" % (ylabel[1]) ) + ax2.set_ylabel(ylabel[1]) + else: #Only zero results + logging.debug("Axis 2: No results to draw") + pass + for tl in ax2.get_yticklabels(): + tl.set_color('%s' %color[1]) + logging.debug("Axis 2: Setting ticklabel color %s" % color[1]) + _title = "%s vs %s" %(title[0],title[1]) + logging.debug("Axis 2: Setting title to: %s" % _title) + axis.set_title(_title) + + logging.debug("Setting x ticks") + tickLocations = [x+0.5 for x in xrange(0, numCols)] + axis.set_xticks(tickLocations) + axis.set_xticklabels(xvalues[0]) + logging.debug("Setting x limits") + axis.set_xlim(0, numCols) + + canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + logging.debug("Got canvas: %s" % (str(canvas))) + canvas.show() + logging.debug("Adding canvas to vbox") + self.vbox.pack_start(canvas, True, True) + #toolbar = NavigationToolbar(canvas, self.window) + #self.vbox.pack_start(toolbar, False, False) - tickLocations = [x+0.5 for x in xrange(0, numCols)] - axis.set_xticks(tickLocations) - axis.set_xticklabels(xvalues[0]) - axis.set_xlim(0, numCols) - - canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea - canvas.show() - self.vbox.pack_start(canvas, True, True) - #toolbar = NavigationToolbar(canvas, self.window) - #self.vbox.pack_start(toolbar, False, False) + for child in self.vbox.get_children(): + logging.debug('Child available: '+str(child)) - for child in self.vbox.get_children(): - logging.debug('Child available: '+str(child)) + logging.debug('<<') - logging.debug('<<') + def getColor(self, x): + colors=["b","g","r","c","m","y","k", "w"] + if x >= len(colors): + x = x % len(colors) + return colors[x] + + def fmtTableText(self, x, valuesAreTime): + if x <= 0.0001: + return ' ' + elif valuesAreTime: + hour = int(x) + minutes = int((x-hour)*60) + hourLabel = _("h") + minLabel = _("min") + if hour > 0: + return "%d%s %02d%s" % (hour, hourLabel, minutes, minLabel) + else: + return "%02d%s" % (minutes, minLabel) + else: + return '%1.1f' % x - def getColor(self, x): - colors=["b","g","r","c","m","y","k", "w"] - if x >= len(colors): - x = x % len(colors) - return colors[x] - - def fmtTableText(self, x, valuesAreTime): - if x <= 0.0001: - return ' ' - elif valuesAreTime: - hour = int(x) - minutes = int((x-hour)*60) - hourLabel = _("h") - minLabel = _("min") - if hour > 0: - return "%d%s %02d%s" % (hour, hourLabel, minutes, minLabel) - else: - return "%02d%s" % (minutes, minLabel) - else: - return '%1.1f' % x + def drawStackedBars(self,xvalues,yvalues,ylabel,title, valuesAreTime=False): + '''function to draw stacked bars + xvalues needs to be a list of lists of strings, e.g. [0]["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] + yvalues needs to be a list of dicts e.g. [0]{'Kayak': {'Tue': 10.08, 'Fri': 17.579999999999998, 'Thu': 15.66, 'Sat': 30.619999999999997}, {'Run': {'Mon': 9.65, 'Sun': 15.59}} + ''' + #TODO tidy + logging.debug('>>') + logging.debug("Title: %s", (title, )) + logging.debug("X values received: %s", str(xvalues)) + logging.debug("Y values received: %s", str(yvalues)) + self.removeVboxChildren() - def drawStackedBars(self,xvalues,yvalues,ylabel,title, valuesAreTime=False): - '''function to draw stacked bars - xvalues needs to be a list of lists of strings, e.g. [0]["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] - yvalues needs to be a list of dicts e.g. [0]{'Kayak': {'Tue': 10.08, 'Fri': 17.579999999999998, 'Thu': 15.66, 'Sat': 30.619999999999997}, {'Run': {'Mon': 9.65, 'Sun': 15.59}} - ''' - #TODO tidy - logging.debug('>>') - logging.debug("Title: %s", (title, )) - logging.debug("X values received: %s", str(xvalues)) - logging.debug("Y values received: %s", str(yvalues)) - self.removeVboxChildren() + #Check how many axes to draw + if len(xvalues) == 1: #One axis + barWidth = 0.8 + barOffset = 0.1 + elif len(xvalues) == 2: #Twin axes + barWidth = 0.4 + barOffset = 0.1 + else: #Error + return - #Check how many axes to draw - if len(xvalues) == 1: #One axis - barWidth = 0.8 - barOffset = 0.1 - elif len(xvalues) == 2: #Twin axes - barWidth = 0.4 - barOffset = 0.1 - else: #Error - return + keys = yvalues[0].keys() # days of the week + numRows = len(keys) + numCols = len(xvalues[0]) + if numRows == 0: + return + width = .8 + figure = plt.figure(figsize=(6,4), dpi=72) + axis = plt.subplot(111) - keys = yvalues[0].keys() # days of the week - numRows = len(keys) - numCols = len(xvalues[0]) - if numRows == 0: - return - width = .8 - figure = plt.figure(figsize=(6,4), dpi=72) - axis = plt.subplot(111) + ybottoms = [0] * numCols + yheights = [0] * numCols + inds = xrange(0, numCols) + xvals = [x+barOffset for x in range(0, numCols)] + cellText = [] + self.showGraph=False - ybottoms = [0] * numCols - yheights = [0] * numCols - inds = xrange(0, numCols) - xvals = [x+barOffset for x in range(0, numCols)] - cellText = [] - self.showGraph=False + #Display first axis + for key in keys: + logging.debug("Day of the week: %s", str(key)) + for ind in inds: + ybottoms[ind] += yheights[ind] + yheights[ind] = 0 #Zero heights + color = self.getColor(keys.index(key)) + for xvalue in xvalues[0]: + index = xvalues[0].index(xvalue) + if xvalue in yvalues[0][key]: + height = yvalues[0][key][xvalue] + if float(height) > 0.0: + self.showGraph=True + else: + height = self.NEARLY_ZERO + yheights[index] = height + cellText.append([self.fmtTableText(x, valuesAreTime[0]) for x in yheights]) + if self.showGraph: + axis.bar(xvals, yheights, bottom=ybottoms, width=barWidth, color=color, align='edge', label=key) + else: #Only zero results + pass + axis.set_xticklabels('' * len(xvalues[0])) + axis.set_ylabel(ylabel[0]) + if len(xvalues) == 1: + plt.title(title[0]) + axis.legend(loc=0) - #Display first axis - for key in keys: - logging.debug("Day of the week: %s", str(key)) - for ind in inds: - ybottoms[ind] += yheights[ind] - yheights[ind] = 0 #Zero heights - color = self.getColor(keys.index(key)) - for xvalue in xvalues[0]: - index = xvalues[0].index(xvalue) - if xvalue in yvalues[0][key]: - height = yvalues[0][key][xvalue] - if float(height) > 0.0: - self.showGraph=True - else: - height = self.NEARLY_ZERO - yheights[index] = height - cellText.append([self.fmtTableText(x, valuesAreTime[0]) for x in yheights]) - if self.showGraph: - axis.bar(xvals, yheights, bottom=ybottoms, width=barWidth, color=color, align='edge', label=key) - else: #Only zero results - pass - axis.set_xticklabels('' * len(xvalues[0])) - axis.set_ylabel(ylabel[0]) - if len(xvalues) == 1: - plt.title(title[0]) - axis.legend(loc=0) + logging.debug("X values first axis: %s", str(xvals)) + logging.debug("Y values first axis: %s", str(yheights)) - logging.debug("X values first axis: %s", str(xvals)) - logging.debug("Y values first axis: %s", str(yheights)) + #Display twin axis + if len(xvalues) == 2: + self.showGraph=False + ax2 = axis.twinx() + keys = yvalues[1].keys() + ybottoms = [0] * numCols + yheights = [self.NEARLY_ZERO] * numCols + for key in keys: + for ind in inds: + ybottoms[ind] += yheights[ind] + yheights[ind] = 0.0 #Zero heights + color = self.getColor(keys.index(key)) + for xvalue in xvalues[0]: + index = xvalues[0].index(xvalue) + if xvalue in yvalues[1][key]: + height = yvalues[1][key][xvalue] + if float(height) > 0.0: + self.showGraph=True + else: + height = self.NEARLY_ZERO + yheights[index] = height + textToAdd = self.fmtTableText(height, valuesAreTime[1]) + if textToAdd is not ' ': + row = keys.index(key) + col = index + cellText[row][col] += " | %s" % (self.fmtTableText(height, valuesAreTime[1])) + #print "Would add %s to %s %s" % (self.fmtTableText(height, valuesAreTime[1]), index, keys.index(key)) + if self.showGraph: + xvals = [x+barOffset+barWidth for x in range(0, numCols)] + #print "ax2", xvals, yheights, ybottoms + ax2.bar(xvals, yheights, bottom=ybottoms, width=barWidth, color=color, align='edge', label=key) + else: #Only zero results + ax2.bar(xvals, [0]*numCols, bottom=[0]*numCols, width=barWidth, color=color, align='edge', label=key) + pass + ax2.set_xticklabels('' * len(xvalues[1])) + ax2.set_ylabel(ylabel[1]) + ax2.legend(loc=0) + plt.title("%s vs %s" %(title[0],title[1])) - #Display twin axis - if len(xvalues) == 2: - self.showGraph=False - ax2 = axis.twinx() - keys = yvalues[1].keys() - ybottoms = [0] * numCols - yheights = [self.NEARLY_ZERO] * numCols - for key in keys: - for ind in inds: - ybottoms[ind] += yheights[ind] - yheights[ind] = 0.0 #Zero heights - color = self.getColor(keys.index(key)) - for xvalue in xvalues[0]: - index = xvalues[0].index(xvalue) - if xvalue in yvalues[1][key]: - height = yvalues[1][key][xvalue] - if float(height) > 0.0: - self.showGraph=True - else: - height = self.NEARLY_ZERO - yheights[index] = height - textToAdd = self.fmtTableText(height, valuesAreTime[1]) - if textToAdd is not ' ': - row = keys.index(key) - col = index - cellText[row][col] += " | %s" % (self.fmtTableText(height, valuesAreTime[1])) - #print "Would add %s to %s %s" % (self.fmtTableText(height, valuesAreTime[1]), index, keys.index(key)) - if self.showGraph: - xvals = [x+barOffset+barWidth for x in range(0, numCols)] - #print "ax2", xvals, yheights, ybottoms - ax2.bar(xvals, yheights, bottom=ybottoms, width=barWidth, color=color, align='edge', label=key) - else: #Only zero results - ax2.bar(xvals, [0]*numCols, bottom=[0]*numCols, width=barWidth, color=color, align='edge', label=key) - pass - ax2.set_xticklabels('' * len(xvalues[1])) - ax2.set_ylabel(ylabel[1]) - ax2.legend(loc=0) - plt.title("%s vs %s" %(title[0],title[1])) + ## try to do some table stuff + colLabels = xvalues[0] + rowLabels = keys + axis.table(cellText=cellText, cellLoc='center', rowLabels=rowLabels, colLabels=colLabels, loc='bottom') + plt.subplots_adjust(left=0.15,bottom=0.08+(0.03*numRows)) + axis.grid(True) + canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + canvas.show() + self.vbox.pack_start(canvas, True, True) + #toolbar = NavigationToolbar(canvas, self.window) + #self.vbox.pack_start(toolbar, False, False) - ## try to do some table stuff - colLabels = xvalues[0] - rowLabels = keys - axis.table(cellText=cellText, cellLoc='center', rowLabels=rowLabels, colLabels=colLabels, loc='bottom') - plt.subplots_adjust(left=0.15,bottom=0.08+(0.03*numRows)) - axis.grid(True) - canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea - canvas.show() - self.vbox.pack_start(canvas, True, True) - #toolbar = NavigationToolbar(canvas, self.window) - #self.vbox.pack_start(toolbar, False, False) + for child in self.vbox.get_children(): + logging.debug('Child available: '+str(child)) - for child in self.vbox.get_children(): - logging.debug('Child available: '+str(child)) + logging.debug('<<') - logging.debug('<<') + def drawPlot(self,xvalues,yvalues,xlabel,ylabel,title,color,zones=None,xzones=None, ylimits=None, y1_linewidth=None): + logging.debug('>>') + logging.debug("Type: plot | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) + logging.debug('xlabel: '+str(xlabel)+' | ylabel: '+str(ylabel)+' | title: '+str(title)) + self.removeVboxChildren() + figure = Figure() + figure.clf() + i = 0 + for value in xvalues: + if i<1: + axis = figure.add_subplot(111) + line = axis.plot(xvalues[i],yvalues[i], color=color[i]) + if y1_linewidth is not None: + line[0].set_linewidth(y1_linewidth) + linewidth = line[0].get_linewidth() + + axis.grid(True) + for tl in axis.get_yticklabels(): + tl.set_color('%s' %color[i]) + #Draw zones on graph, eg for each lap + if xzones is not None: + for xzone in xzones: + if xzones.index(xzone) % 2: + zonecolor='b' + else: + zonecolor='g' + axis.axvspan(xzone[0], xzone[1], alpha=0.25, facecolor=zonecolor) + maxX = max(xvalues[i]) + if i>=1: + ax2 = axis.twinx() + ax2.plot(xvalues[i], yvalues[i], color=color[i]) + for tl in ax2.get_yticklabels(): + tl.set_color('%s' %color[i]) + maxXt = max(xvalues[i]) + if maxXt > maxX: + maxX = maxXt + axis.set_xlabel(xlabel[i]) + i+=1 + axis.set_xlim(0, maxX) - def drawPlot(self,xvalues,yvalues,xlabel,ylabel,title,color,zones=None,xzones=None, ylimits=None, y1_linewidth=None): - logging.debug('>>') - logging.debug("Type: plot | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) - logging.debug('xlabel: '+str(xlabel)+' | ylabel: '+str(ylabel)+' | title: '+str(title)) - self.removeVboxChildren() - figure = Figure() - figure.clf() - i = 0 - for value in xvalues: - if i<1: - axis = figure.add_subplot(111) - line = axis.plot(xvalues[i],yvalues[i], color=color[i]) - if y1_linewidth is not None: - line[0].set_linewidth(y1_linewidth) - linewidth = line[0].get_linewidth() - - axis.grid(True) - for tl in axis.get_yticklabels(): - tl.set_color('%s' %color[i]) - #Draw zones on graph, eg for each lap - if xzones is not None: - for xzone in xzones: - if xzones.index(xzone) % 2: - zonecolor='b' - else: - zonecolor='g' - axis.axvspan(xzone[0], xzone[1], alpha=0.25, facecolor=zonecolor) - maxX = max(xvalues[i]) - if i>=1: - ax2 = axis.twinx() - ax2.plot(xvalues[i], yvalues[i], color=color[i]) - for tl in ax2.get_yticklabels(): - tl.set_color('%s' %color[i]) - maxXt = max(xvalues[i]) - if maxXt > maxX: - maxX = maxXt - axis.set_xlabel(xlabel[i]) - i+=1 - axis.set_xlim(0, maxX) + if (len(xvalues)>1): + axis.set_title("%s vs %s" %(ylabel[0],ylabel[1])) + else: + axis.set_title("%s" %(ylabel[0])) - if (len(xvalues)>1): - axis.set_title("%s vs %s" %(ylabel[0],ylabel[1])) - else: - axis.set_title("%s" %(ylabel[0])) + ylim_min, ylim_max = axis.get_ylim() + if ylimits is not None: + logging.debug("Using ylimits: %s" % str(ylimits)) + if ylimits[0] is not None: + ylim_min = ylimits[0] + if ylimits[1] is not None: + ylim_max = ylimits[1] + axis.set_ylim(ylim_min, ylim_max) - ylim_min, ylim_max = axis.get_ylim() - if ylimits is not None: - logging.debug("Using ylimits: %s" % str(ylimits)) - if ylimits[0] is not None: - ylim_min = ylimits[0] - if ylimits[1] is not None: - ylim_max = ylimits[1] - axis.set_ylim(ylim_min, ylim_max) + canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + canvas.show() + self.vbox.pack_start(canvas, True, True) + toolbar = NavigationToolbar(canvas, self.window) + self.vbox.pack_start(toolbar, False, False) + + for child in self.vbox.get_children(): + logging.debug('Child available: '+str(child)) + + logging.debug('<<') + return {'y1_min': ylim_min, 'y1_max': ylim_max, 'y1_linewidth': linewidth} + + def drawPie(self,xvalues,yvalues,xlabel,ylabel,title,color,zones=None): + logging.debug('>>') + logging.debug("Type: pie | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) + self.removeVboxChildren() + figure = Figure(figsize=(6,4), dpi=72) + axis = figure.add_subplot(111) - canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea - canvas.show() - self.vbox.pack_start(canvas, True, True) - toolbar = NavigationToolbar(canvas, self.window) - self.vbox.pack_start(toolbar, False, False) - - for child in self.vbox.get_children(): - logging.debug('Child available: '+str(child)) - - logging.debug('<<') - return {'y1_min': ylim_min, 'y1_max': ylim_max, 'y1_linewidth': linewidth} - - def drawPie(self,xvalues,yvalues,xlabel,ylabel,title,color,zones=None): - logging.debug('>>') - logging.debug("Type: pie | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) - self.removeVboxChildren() - figure = Figure(figsize=(6,4), dpi=72) - axis = figure.add_subplot(111) + labels = ["rest"] + colors = ["#ffffff"] + frac0 = 0 + frac1 = 0 + frac2 = 0 + frac3 = 0 + frac4 = 0 + frac5 = 0 + for zone in zones: + labels.append(zone[3]) + colors.append(zone[2]) + + for value in yvalues[0]: + if value < zones[4][0]: + frac0+=1 + elif value > zones[4][0] and value < zones[4][1]: + frac1+=1 + elif value > zones[3][0] and value < zones[3][1]: + frac2+=1 + elif value > zones[2][0] and value < zones[2][1]: + frac3+=1 + elif value > zones[1][0] and value < zones[1][1]: + frac4+=1 + elif value > zones[0][0] and value < zones[0][1]: + frac5+=1 + + fracs = [frac0,frac1,frac2,frac3,frac4, frac5] + explode=(0, 0, 0, 0,0,0) + axis.pie(fracs, explode=explode, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True) - labels = ["rest"] - colors = ["#ffffff"] - frac0 = 0 - frac1 = 0 - frac2 = 0 - frac3 = 0 - frac4 = 0 - frac5 = 0 - for zone in zones: - labels.append(zone[3]) - colors.append(zone[2]) - - for value in yvalues[0]: - if value < zones[4][0]: - frac0+=1 - elif value > zones[4][0] and value < zones[4][1]: - frac1+=1 - elif value > zones[3][0] and value < zones[3][1]: - frac2+=1 - elif value > zones[2][0] and value < zones[2][1]: - frac3+=1 - elif value > zones[1][0] and value < zones[1][1]: - frac4+=1 - elif value > zones[0][0] and value < zones[0][1]: - frac5+=1 - - fracs = [frac0,frac1,frac2,frac3,frac4, frac5] - explode=(0, 0, 0, 0,0,0) - axis.pie(fracs, explode=explode, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True) + canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + canvas.show() - canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea - canvas.show() + for child in self.vbox.get_children(): + logging.debug('Child available: '+str(child)) - for child in self.vbox.get_children(): - logging.debug('Child available: '+str(child)) + self.vbox.pack_start(canvas, True, True) + logging.debug('<<') - self.vbox.pack_start(canvas, True, True) - logging.debug('<<') + def drawDefault(self): + logging.debug('>>') + self.axis=self.figure.add_subplot(111) + self.axis.set_xlabel('Yepper') + self.axis.set_ylabel('Flabber') + self.axis.set_title('An Empty Graph') + self.axis.grid(True) + self.canvas.destroy() + self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea + self.canvas.show() + self.vbox.pack_start(self.canvas, True, True) + logging.debug('<<') - def drawDefault(self): - logging.debug('>>') - self.axis=self.figure.add_subplot(111) - self.axis.set_xlabel('Yepper') - self.axis.set_ylabel('Flabber') - self.axis.set_title('An Empty Graph') - self.axis.grid(True) - self.canvas.destroy() - self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea - self.canvas.show() - self.vbox.pack_start(self.canvas, True, True) - logging.debug('<<') + def fill_over(self, ax, x, y, val, color, over=True): + """ + Plot filled x,y for all y over val + if over = False, fill all areas < val + """ + logging.debug('>>') + ybase = asarray(y)-val + crossings = nonzero(less(ybase[:-1] * ybase[1:],0)) - def fill_over(self, ax, x, y, val, color, over=True): - """ - Plot filled x,y for all y over val - if over = False, fill all areas < val - """ - logging.debug('>>') - ybase = asarray(y)-val - crossings = nonzero(less(ybase[:-1] * ybase[1:],0)) + if ybase[0]>=0: + fillon = over + else: + fillon = not over + indLast = 0 + for ind in crossings: + if fillon: + thisX = x[indLast:ind+1] + thisY = y[indLast:ind+1] + thisY[0] = val + thisY[-1] = val + ax.fill(thisX, thisY, color) + fillon = not fillon + indLast = ind + logging.debug('<<') - if ybase[0]>=0: - fillon = over - else: - fillon = not over - indLast = 0 - for ind in crossings: - if fillon: - thisX = x[indLast:ind+1] - thisY = y[indLast:ind+1] - thisY[0] = val - thisY[-1] = val - ax.fill(thisX, thisY, color) - fillon = not fillon - indLast = ind - logging.debug('<<') - - def removeVboxChildren(self): - ''' function to delete vbox children so that multiple graphs do not appear - there must a better way to do this - pyplot? - ''' - logging.debug('>>') - #Tidy up draw areas - vboxChildren = self.vbox.get_children() - logging.debug('Vbox has %d children %s' % (len(vboxChildren), str(vboxChildren) )) - # ToDo: check why vertical container is shared - for child in vboxChildren: - #Remove all FigureCanvasGTK and NavigationToolbar2GTKAgg to stop double ups of graphs - if isinstance(child, matplotlib.backends.backend_gtkagg.FigureCanvasGTK) or isinstance(child, matplotlib.backends.backend_gtkagg.NavigationToolbar2GTKAgg): - logging.debug('Removing child: '+str(child)) - self.vbox.remove(child) - logging.debug('<<') + def removeVboxChildren(self): + ''' function to delete vbox children so that multiple graphs do not appear + there must a better way to do this - pyplot? + ''' + logging.debug('>>') + #Tidy up draw areas + vboxChildren = self.vbox.get_children() + logging.debug('Vbox has %d children %s' % (len(vboxChildren), str(vboxChildren) )) + # ToDo: check why vertical container is shared + for child in vboxChildren: + #Remove all FigureCanvasGTK and NavigationToolbar2GTKAgg to stop double ups of graphs + if isinstance(child, matplotlib.backends.backend_gtkagg.FigureCanvasGTK) or isinstance(child, matplotlib.backends.backend_gtkagg.NavigationToolbar2GTKAgg): + logging.debug('Removing child: '+str(child)) + self.vbox.remove(child) + logging.debug('<<') Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-28 03:39:34 UTC (rev 624) +++ pytrainer/trunk/pytrainer/main.py 2010-09-28 21:22:07 UTC (rev 625) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#624" + self.version ="1.7.2_svn#625" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-28 03:39:40
|
Revision: 624 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=624&view=rev Author: jblance Date: 2010-09-28 03:39:34 +0000 (Tue, 28 Sep 2010) Log Message: ----------- Activity graphing work - display multiple items on one graph (Incomplete) Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/graphdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-09-28 00:44:39 UTC (rev 623) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-09-28 03:39:34 UTC (rev 624) @@ -26,104 +26,160 @@ import logging class DrawGraph: - def __init__(self, parent = None, pytrainer_main = None): - logging.debug('>>') - self.parent = parent - self.pytrainer_main = pytrainer_main - #self.NEARLY_ZERO = 0.0000000000000000000001 - logging.debug('<<') + def __init__(self, parent = None, pytrainer_main = None): + logging.debug('>>') + self.parent = parent + self.pytrainer_main = pytrainer_main + #self.NEARLY_ZERO = 0.0000000000000000000001 + logging.debug('<<') - def drawPlot(self, datalist = None, box = None): - ''' - Draw a plot style graph - ''' - #data = {'linewidth':3, 'x':(1,2,3), 'y':(3,9,1)} - logging.debug('>>') - if box is None: - logging.error("Must supply a vbox or hbox to display the graph") - return - #Remove existing plot (if any) - for child in box.get_children(): - logging.debug('Removing box child: '+str(child)) - box.remove(child) - if datalist is None: # or len(datalist) == 0: - logging.debug("drawPlot called with no data") - return - #Debug info - to remove - print("drawPlot....") - #print datalist - - #Set up drawing area - figure = plt.figure() - canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea - canvas.show() - #Display title etc - plt.xlabel(datalist.xlabel) - plt.ylabel(datalist.ylabel) - plt.title(datalist.title) - #Plot data - plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor ) - #Set axis limits - plt.axis([datalist.min_x_value, datalist.max_x_value, datalist.min_y_value, datalist.max_y_value]) + def drawPlot(self, datalist = None, box = None): + ''' + Draw a plot style graph + ''' + #data = {'linewidth':3, 'x':(1,2,3), 'y':(3,9,1)} + logging.debug('>>') + if box is None: + logging.error("Must supply a vbox or hbox to display the graph") + return + #Remove existing plot (if any) + for child in box.get_children(): + logging.debug('Removing box child: '+str(child)) + box.remove(child) + if datalist is None: # or len(datalist) == 0: + logging.debug("drawPlot called with no data") + return + #Debug info - to remove + print("drawPlot....") + #print datalist + + #Set up drawing area + figure = plt.figure() + canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + canvas.show() + #Display title etc + plt.xlabel(datalist.xlabel) + plt.ylabel(datalist.ylabel) + plt.title(datalist.title) + #Plot data + plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor ) + #Set axis limits + plt.axis([datalist.min_x_value, datalist.max_x_value, datalist.min_y_value, datalist.max_y_value]) - #axis.set_xlim(0, data.max_x_value) - #axis.set_ylim(0, data.max_y_value) + #axis.set_xlim(0, data.max_x_value) + #axis.set_ylim(0, data.max_y_value) - #Display plot - box.pack_start(canvas, True, True) + #Display plot + box.pack_start(canvas, True, True) - return - #(self,xvalues,yvalues,xlabel,ylabel,title,color,zones=None,xzones=None, ylimits=None, y1_linewidth=None): - logging.debug("Type: plot | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) - logging.debug('xlabel: '+str(xlabel)+' | ylabel: '+str(ylabel)+' | title: '+str(title)) - #self.removeVboxChildren() - i = 0 - for value in xvalues: - if i<1: - axis = figure.add_subplot(111) - line = axis.plot(xvalues[i],yvalues[i], color=color[i]) - if y1_linewidth is not None: - line[0].set_linewidth(y1_linewidth) - linewidth = line[0].get_linewidth() + return + #(self,xvalues,yvalues,xlabel,ylabel,title,color,zones=None,xzones=None, ylimits=None, y1_linewidth=None): + logging.debug("Type: plot | title: "+str(title)+" | col: "+str(color)+" | xlabel: "+str(xlabel)+" | ylabel: "+str(ylabel)) + logging.debug('xlabel: '+str(xlabel)+' | ylabel: '+str(ylabel)+' | title: '+str(title)) + #self.removeVboxChildren() + i = 0 + for value in xvalues: + if i<1: + axis = figure.add_subplot(111) + line = axis.plot(xvalues[i],yvalues[i], color=color[i]) + if y1_linewidth is not None: + line[0].set_linewidth(y1_linewidth) + linewidth = line[0].get_linewidth() - axis.grid(True) - for tl in axis.get_yticklabels(): - tl.set_color('%s' %color[i]) - #Draw zones on graph, eg for each lap - if xzones is not None: - for xzone in xzones: - if xzones.index(xzone) % 2: - zonecolor='b' - else: - zonecolor='g' - axis.axvspan(xzone[0], xzone[1], alpha=0.25, facecolor=zonecolor) - maxX = max(xvalues[i]) - if i>=1: - ax2 = axis.twinx() - ax2.plot(xvalues[i], yvalues[i], color=color[i]) - for tl in ax2.get_yticklabels(): - tl.set_color('%s' %color[i]) - maxXt = max(xvalues[i]) - if maxXt > maxX: - maxX = maxXt - axis.set_xlabel(xlabel[i]) - i+=1 - axis.set_xlim(0, maxX) + axis.grid(True) + for tl in axis.get_yticklabels(): + tl.set_color('%s' %color[i]) + #Draw zones on graph, eg for each lap + if xzones is not None: + for xzone in xzones: + if xzones.index(xzone) % 2: + zonecolor='b' + else: + zonecolor='g' + axis.axvspan(xzone[0], xzone[1], alpha=0.25, facecolor=zonecolor) + maxX = max(xvalues[i]) + if i>=1: + ax2 = axis.twinx() + ax2.plot(xvalues[i], yvalues[i], color=color[i]) + for tl in ax2.get_yticklabels(): + tl.set_color('%s' %color[i]) + maxXt = max(xvalues[i]) + if maxXt > maxX: + maxX = maxXt + axis.set_xlabel(xlabel[i]) + i+=1 + axis.set_xlim(0, maxX) - if (len(xvalues)>1): - axis.set_title("%s vs %s" %(ylabel[0],ylabel[1])) - else: - axis.set_title("%s" %(ylabel[0])) + if (len(xvalues)>1): + axis.set_title("%s vs %s" %(ylabel[0],ylabel[1])) + else: + axis.set_title("%s" %(ylabel[0])) - ylim_min, ylim_max = axis.get_ylim() - if ylimits is not None: - logging.debug("Using ylimits: %s" % str(ylimits)) - if ylimits[0] is not None: - ylim_min = ylimits[0] - if ylimits[1] is not None: - ylim_max = ylimits[1] - axis.set_ylim(ylim_min, ylim_max) + ylim_min, ylim_max = axis.get_ylim() + if ylimits is not None: + logging.debug("Using ylimits: %s" % str(ylimits)) + if ylimits[0] is not None: + ylim_min = ylimits[0] + if ylimits[1] is not None: + ylim_max = ylimits[1] + axis.set_ylim(ylim_min, ylim_max) - logging.debug('<<') - return {'y1_min': ylim_min, 'y1_max': ylim_max, 'y1_linewidth': linewidth} + logging.debug('<<') + return {'y1_min': ylim_min, 'y1_max': ylim_max, 'y1_linewidth': linewidth} + + def drawMultiPlot(self, activity = None, box = None): + ''' + Draw a plot style graph with multiple traces on each axis + ''' + logging.debug('>>') + if box is None: + logging.error("Must supply a vbox or hbox to display the graph") + return + if activity is None: + logging.error("Must supply data to graph graph") + return + #TODO Check that datalist is of type dict (and contains has correct items) + figure = None + datalist = [] + #Loop through data items and graph the selected ones + #TODO sort for x = time.... + for item in activity.distance_data: + if activity.distance_data[item].show_on_y1: + figure = self._drawPlotTrace(activity.distance_data[item], box=box, figure=figure) + logging.debug('<<') + + def _drawPlotTrace(self, datalist = None, box = None, figure = None): + logging.debug(">>") + #Check we got required data + if box is None: + logging.error("Must supply a vbox or hbox to display the graph") + return + #Check if have gotten a graph object + if figure is None: + #No figure, so create figure + figure = plt.figure() + #Remove any existing plots + for child in box.get_children(): + logging.debug('Removing box child: '+str(child)) + box.remove(child) + #Create canvas + canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea + canvas.show() + #Display title etc + plt.xlabel(datalist.xlabel) + plt.ylabel(datalist.ylabel) + plt.title(datalist.title) + #Plot data + plt.plot(datalist.x_values, datalist.y_values, linewidth=datalist.linewidth, color=datalist.linecolor ) + #Set axis limits + #plt.axis([datalist.min_x_value, datalist.max_x_value, datalist.min_y_value, datalist.max_y_value]) + + #axis.set_xlim(0, data.max_x_value) + #axis.set_ylim(0, data.max_y_value) + + #Display plot + box.pack_start(canvas, True, True) + + logging.debug("<<") + return figure Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-28 00:44:39 UTC (rev 623) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-28 03:39:34 UTC (rev 624) @@ -68,6 +68,10 @@ self.gpxDir = gpxDir self.record_list = None self.laps = None + + #Setup graph + self.grapher = DrawGraph(self, self.pytrainer_main) + self.y1_limits = None self.y1_color = None self.y1_linewidth = 1 @@ -279,6 +283,7 @@ self.hbox30.show() #Hide new graph details self.graph_data_hbox.hide() + #Enable graph self.record_vbox.set_sensitive(1) self.drawarearecord.drawgraph(self.record_list,self.laps) else: @@ -286,10 +291,20 @@ logging.debug("Using the new TEST graphing approach") #Hide current drop down boxes self.hbox30.hide() + #Show new graph details + self.graph_data_hbox.hide() + #Enable graph + self.record_vbox.set_sensitive(1) #Create a frame showing data available for graphing #Remove existing frames for child in self.graph_data_hbox.get_children(): self.graph_data_hbox.remove(child) + #Remove graph + #for child in self.record_graph_vbox.get_children(): + # #Remove all FigureCanvasGTK and NavigationToolbar2GTKAgg to stop double ups of graphs + # #if isinstance(child, matplotlib.backends.backend_gtkagg.FigureCanvasGTK) or isinstance(child, matplotlib.backends.backend_gtkagg.NavigationToolbar2GTKAgg): + # print('Removing child: '+str(child)) + # self.record_graph_vbox.remove(child) #Build frames and vboxs to hold checkbuttons xFrame = gtk.Frame(label="Show on X Axis") y1Frame = gtk.Frame(label="Show on Y1 Axis") @@ -309,7 +324,7 @@ #Populate Y axis data for graphdata in activity.distance_data: y1button = gtk.CheckButton(label=activity.distance_data[graphdata].title) - y1button.connect("toggled", self.on_y1change, y1vbox, activity.distance_data[graphdata]) + y1button.connect("toggled", self.on_y1change, y1vbox, graphdata, activity) y2button = gtk.CheckButton(label=activity.distance_data[graphdata].title) y2button.connect("toggled", self.on_y2change, y2vbox) y1vbox.add(y1button) @@ -322,8 +337,7 @@ self.graph_data_hbox.show_all() #TODO Fix... - self.record_vbox.set_sensitive(1) - self.drawarearecord.drawgraph(self.record_list,self.laps) + #self.drawarearecord.drawgraph(self.record_list,self.laps) else: logging.debug("Activity has no GPX data") #Show drop down boxes @@ -713,7 +727,7 @@ self.labelDOB.set_text(athletedata["prf_age"]) self.labelHeight.set_text(athletedata["prf_height"]+" cm") #Setup graph - self.grapher = DrawGraph(self, self.pytrainer_main) + #self.grapher = DrawGraph(self, self.pytrainer_main) from pytrainer.lib.graphdata import GraphData datalist = GraphData(title="Weight", xlabel="Date", ylabel="kg") #TODO @@ -989,14 +1003,18 @@ if widget.get_active(): print data - def on_y1change(self, widget, box, data): + def on_y1change(self, widget, box, graphdata, activity): '''Hander for changes to y1 selection''' - print "Y1 selected: " + #TODO Need to deal with different x options, ie distance and time... + logging.debug("Y1 selection toggled: %s" % graphdata) + #Loop through all options at set data correctly for child in box.get_children(): - if child.get_active(): - #This check box is active, so display graph... - #drawgraph to self.record_graph_vbox with data... - print child.get_label(), data + for item in activity.distance_data: + if activity.distance_data[item].title == child.get_label(): + logging.debug( "Setting %s to %s" % (item, str(child.get_active()) ) ) + activity.distance_data[item].show_on_y1 = child.get_active() + #Plot the activity + self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) def on_y2change(self, widget, box): '''Hander for changes to y2 selection''' Modified: pytrainer/trunk/pytrainer/lib/graphdata.py =================================================================== --- pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-28 00:44:39 UTC (rev 623) +++ pytrainer/trunk/pytrainer/lib/graphdata.py 2010-09-28 03:39:34 UTC (rev 624) @@ -19,31 +19,32 @@ import logging class GraphData: - ''' - Class to hold data and formating for graphing via matplotlib - ''' - def __init__(self, title=None, ylabel=None, xlabel=None): - logging.debug('>>') - self.title = title - self.ylabel = ylabel - self.xlabel = xlabel - self.x_values = [] - self.y_values = [] - self.linewidth = 1 - self.linecolor = '#ff0000' - self.max_x_value = None - self.min_x_value = None - self.max_y_value = None - self.min_y_value = None - logging.debug('<<') + ''' + Class to hold data and formating for graphing via matplotlib + ''' + def __init__(self, title=None, ylabel=None, xlabel=None): + logging.debug('>>') + self.title = title + self.ylabel = ylabel + self.xlabel = xlabel + self.x_values = [] + self.y_values = [] + self.linewidth = 1 + self.linecolor = '#ff0000' + self.max_x_value = None + self.min_x_value = None + self.max_y_value = None + self.min_y_value = None + self.show_on_y1 = False + logging.debug('<<') - def __len__(self): - if self.x_values is None: - return None - return len(self.x_values) - - def __str__(self): - return ''' + def __len__(self): + if self.x_values is None: + return None + return len(self.x_values) + + def __str__(self): + return ''' Title: %s ylabel: %s xlabel: %s @@ -53,31 +54,31 @@ y min max: %s %s x values: %s y values: %s''' % (self.title, - self.ylabel, - self.xlabel, - self.linewidth, - self.linecolor, - str(self.min_x_value), str(self.max_x_value), - str(self.min_y_value), str(self.max_y_value), - str(self.x_values), - str(self.y_values) - ) + self.ylabel, + self.xlabel, + self.linewidth, + self.linecolor, + str(self.min_x_value), str(self.max_x_value), + str(self.min_y_value), str(self.max_y_value), + str(self.x_values), + str(self.y_values) + ) - def addPoints(self, x=None, y=None): - if x is None or y is None: - #logging.debug("Must supply both x and y data points, got x:'%s' y:'%s'" % (str(x), str(y))) - return - #print('Adding point: %s %s' % (str(x), str(y))) - self.x_values.append(x) - self.y_values.append(y) - if self.max_x_value is None or x > self.max_x_value: - self.max_x_value = x - if self.min_x_value is None or x < self.min_x_value: - self.min_x_value = x - if self.max_y_value is None or y > self.max_y_value: - self.max_y_value = y - if self.min_y_value is None or y < self.min_y_value: - self.min_y_value = y + def addPoints(self, x=None, y=None): + if x is None or y is None: + #logging.debug("Must supply both x and y data points, got x:'%s' y:'%s'" % (str(x), str(y))) + return + #print('Adding point: %s %s' % (str(x), str(y))) + self.x_values.append(x) + self.y_values.append(y) + if self.max_x_value is None or x > self.max_x_value: + self.max_x_value = x + if self.min_x_value is None or x < self.min_x_value: + self.min_x_value = x + if self.max_y_value is None or y > self.max_y_value: + self.max_y_value = y + if self.min_y_value is None or y < self.min_y_value: + self.min_y_value = y Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-28 00:44:39 UTC (rev 623) +++ pytrainer/trunk/pytrainer/main.py 2010-09-28 03:39:34 UTC (rev 624) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#623" + self.version ="1.7.2_svn#624" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-28 00:44:46
|
Revision: 623 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=623&view=rev Author: jblance Date: 2010-09-28 00:44:39 +0000 (Tue, 28 Sep 2010) Log Message: ----------- Split elevation code into separate class files Modified Paths: -------------- pytrainer/trunk/extensions/fixelevation/fixelevation.py pytrainer/trunk/pytrainer/main.py Added Paths: ----------- pytrainer/trunk/pytrainer/lib/srtmlayer.py pytrainer/trunk/pytrainer/lib/srtmtiff.py Modified: pytrainer/trunk/extensions/fixelevation/fixelevation.py =================================================================== --- pytrainer/trunk/extensions/fixelevation/fixelevation.py 2010-09-28 00:20:39 UTC (rev 622) +++ pytrainer/trunk/extensions/fixelevation/fixelevation.py 2010-09-28 00:44:39 UTC (rev 623) @@ -1,244 +1,15 @@ #!/usr/bin/env python -import os, stat, sys +import os #, stat, sys import logging import gtk - -import random, re, urllib2, zipfile -from math import floor, ceil -from cStringIO import StringIO -from optparse import OptionParser - -from osgeo import gdal, gdalnumeric +#import random, re, urllib2, zipfile +#from math import floor, ceil +#from cStringIO import StringIO +#from optparse import OptionParser +#from osgeo import gdal, gdalnumeric from lxml import etree +from pytrainer.lib.srtmlayer import SrtmLayer -""" -A list of servers providing SRTM data in GeoTIFF -""" -srtm_server_list = [ - {'url' : 'http://droppr.org/srtm/v4.1/6_5x5_TIFs/', 'ext' : '.zip', 'active' : True }, \ - {'url' : 'ftp://xftp.jrc.it/pub/srtmV4/tiff/' , 'ext' : '.zip', 'active' : True }, \ - {'url' : 'http://srtm.csi.cgiar.org/SRT-ZIP/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ - {'url' : 'ftp://srtm.csi.cgiar.org/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ - {'url' : 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/', 'ext' : '.ZIP', 'active' : False } - ] -srtm_server = srtm_server_list[0] - -# from gpxtools -def bilinear_interpolation(tl, tr, bl, br, a, b): - """ - Based on equation from: - http://en.wikipedia.org/wiki/Bilinear_interpolation - - :Parameters: - tl : int - top-left - tr : int - top-right - bl : int - buttom-left - br : int - bottom-right - a : float - x distance to top-left - b : float - y distance to top-right - - :Returns: (float) - interpolated value - """ - b1 = tl - b2 = bl - tl - b3 = tr - tl - b4 = tl - bl - tr + br - - return b1 + b2 * a + b3 * b + b4 * a * b - -class SrtmTiff(object): - """ - Provides an interface to SRTM elevation data stored in GeoTIFF file. - - Based on code from `eleserver` code by grahamjones139. - http://code.google.com/p/eleserver/ - """ - tile = {} - - def __init__(self, filename): - """ - Reads the GeoTIFF files into memory ready for processing. - """ - self.tile = self.load_tile(filename) - - def load_tile(self, filename): - """ - Loads a GeoTIFF tile from disk and returns a dictionary containing - the file data, plus metadata about the tile. - - The dictionary returned by this function contains the following data: - xsize - the width of the tile in pixels. - ysize - the height of the tile in pixels. - lat_origin - the latitude of the top left pixel in the tile. - lon_origin - the longitude of the top left pixel in the tile. - lat_pixel - the height of one pixel in degrees latitude. - lon_pixel - the width of one pixel in degrees longitude. - N, S, E, W - the bounding box for this tile in degrees. - data - a two dimensional array containing the tile data. - - """ - dataset = gdal.Open(filename) - geotransform = dataset.GetGeoTransform() - xsize = dataset.RasterXSize - ysize = dataset.RasterYSize - lon_origin = geotransform[0] - lat_origin = geotransform[3] - lon_pixel = geotransform[1] - lat_pixel = geotransform[5] - - retdict = { - 'xsize': xsize, - 'ysize': ysize, - 'lat_origin': lat_origin, - 'lon_origin': lon_origin, - 'lon_pixel': lon_pixel, - 'lat_pixel': lat_pixel, - 'N': lat_origin, - 'S': lat_origin + lat_pixel*ysize, - 'E': lon_origin + lon_pixel*xsize, - 'W': lon_origin, - 'dataset': dataset, - } - - return retdict - - def pos_from_lat_lon(self, lat, lon): - """ - Converts coordinates (lat,lon) into the appropriate (row,column) - position in the GeoTIFF tile data stored in td. - """ - td = self.tile - N = td['N'] - S = td['S'] - E = td['E'] - W = td['W'] - lat_pixel = td['lat_pixel'] - lon_pixel = td['lon_pixel'] - xsize = td['xsize'] - ysize = td['ysize'] - - rowno_f = (lat-N)/lat_pixel - colno_f = (lon-W)/lon_pixel - rowno = int(floor(rowno_f)) - colno = int(floor(colno_f)) - - # Error checking to correct any rounding errors. - if (rowno<0): - rowno = 0 - if (rowno>(xsize-1)): - rowno = xsize-1 - if (colno<0): - colno = 0 - if (colno>(ysize-1)): - colno = xsize-1 - - return (rowno, colno, rowno_f, colno_f) - - def get_elevation(self, lat, lon): - """ - Returns the elevation in metres of point (lat, lon). - - Uses bilinar interpolation to interpolate the SRTM data to the - required point. - """ - row, col, row_f, col_f = self.pos_from_lat_lon(lat, lon) - - # NOTE - THIS IS A FIDDLE TO STOP ERRORS AT THE EDGE OF - # TILES - IT IS NO CORRECT - WE SHOULD GET TWO POINTS - # FROM THE NEXT TILE. - if row==5999: row=5998 - if col==5999: col=5998 - - htarr = gdalnumeric.DatasetReadAsArray(self.tile['dataset'], col, row, 2, 2) - height = bilinear_interpolation(htarr[0][0], htarr[0][1], htarr[1][0], htarr[1][1], - row_f-row, col_f-col) - - return height - - -class SrtmLayer(object): - """ - Provides an interface to SRTM elevation data stored in GeoTIFF files. - Files are automaticly downloaded from mirror server and cached. - - Sample usage: - - >>> lat = 52.25 - >>> lon = 16.75 - >>> srtm = SrtmLayer() - >>> ele = srtm.get_elevation(lat, lon) - >>> round(ele, 4) - 63.9979 - - """ - _cache = {} - - def _download_srtm_tiff(self, srtm_filename): - """ - Download and unzip GeoTIFF file. - """ - #msg = _("Downloading SRTM Data from server. This might take some time...") - #md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) - #md.set_title(_("Downloading SRTM Data")) - #md.set_modal(True) - #md.show() - - srtm_dir = os.path.expanduser('~/.pytrainer/SRTM_data') - if not os.path.isdir(srtm_dir): - os.mkdir(srtm_dir) - - logging.info('Downloading SRTM data file, it may take some time ...') - #url = 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/%s.ZIP' % srtm_filename[:-4] - url = '%s%s%s' % (srtm_server['url'], srtm_filename[:-4],srtm_server['ext'] ) - print "Attempting to get URL: %s" % url - zobj = StringIO() - zobj.write(urllib2.urlopen(url).read()) - z = zipfile.ZipFile(zobj) - - srtm_path = os.path.join(srtm_dir, srtm_filename) - out_file = open(srtm_path, 'w') - out_file.write(z.read(srtm_filename)) - - z.close() - out_file.close() - #md.destroy() - - - def get_srtm_filename(self, lat, lon): - """ - Filename of GeoTIFF file containing data with given coordinates. - """ - colmin = floor((6000 * (180 + lon)) / 5) - rowmin = floor((6000 * (60 - lat)) / 5) - - ilon = ceil(colmin / 6000.0) - ilat = ceil(rowmin / 6000.0) - - #return 'srtm_%02d_%02d.TIF' % (ilon, ilat) - return 'srtm_%02d_%02d.tif' % (ilon, ilat) - - def get_elevation(self, lat, lon): - """ - Returns the elevation in metres of point (lat, lon). - """ - srtm_filename = self.get_srtm_filename(lat, lon) - if srtm_filename not in self._cache: - srtm_path = os.path.join(os.path.expanduser('~/.pytrainer/SRTM_data'), srtm_filename) - if not os.path.isfile(srtm_path): - self._download_srtm_tiff(srtm_filename) - - self._cache[srtm_filename] = SrtmTiff(srtm_path) - - srtm = self._cache[srtm_filename] - return srtm.get_elevation(lat, lon) - class fixelevation: _data = None _srtm = SrtmLayer() Added: pytrainer/trunk/pytrainer/lib/srtmlayer.py =================================================================== --- pytrainer/trunk/pytrainer/lib/srtmlayer.py (rev 0) +++ pytrainer/trunk/pytrainer/lib/srtmlayer.py 2010-09-28 00:44:39 UTC (rev 623) @@ -0,0 +1,102 @@ +#!/usr/bin/env python +import os, stat, sys +import logging + +import random, re, urllib2, zipfile +from math import floor, ceil +from cStringIO import StringIO +from osgeo import gdal, gdalnumeric + +from pytrainer.lib.srtmtiff import SrtmTiff + +""" +A list of servers providing SRTM data in GeoTIFF +""" +srtm_server_list = [ + {'url' : 'http://droppr.org/srtm/v4.1/6_5x5_TIFs/', 'ext' : '.zip', 'active' : True }, \ + {'url' : 'ftp://xftp.jrc.it/pub/srtmV4/tiff/' , 'ext' : '.zip', 'active' : True }, \ + {'url' : 'http://srtm.csi.cgiar.org/SRT-ZIP/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ + {'url' : 'ftp://srtm.csi.cgiar.org/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ + {'url' : 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/', 'ext' : '.ZIP', 'active' : False } + ] +srtm_server = srtm_server_list[0] + + +class SrtmLayer(object): + """ + Provides an interface to SRTM elevation data stored in GeoTIFF files. + Files are automaticly downloaded from mirror server and cached. + + Sample usage: + + >>> lat = 52.25 + >>> lon = 16.75 + >>> srtm = SrtmLayer() + >>> ele = srtm.get_elevation(lat, lon) + >>> round(ele, 4) + 63.9979 + + """ + _cache = {} + + def _download_srtm_tiff(self, srtm_filename): + """ + Download and unzip GeoTIFF file. + """ + #msg = _("Downloading SRTM Data from server. This might take some time...") + #md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) + #md.set_title(_("Downloading SRTM Data")) + #md.set_modal(True) + #md.show() + + srtm_dir = os.path.expanduser('~/.pytrainer/SRTM_data') + if not os.path.isdir(srtm_dir): + os.mkdir(srtm_dir) + + logging.info('Downloading SRTM data file, it may take some time ...') + #url = 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/%s.ZIP' % srtm_filename[:-4] + url = '%s%s%s' % (srtm_server['url'], srtm_filename[:-4],srtm_server['ext'] ) + print "Attempting to get URL: %s" % url + zobj = StringIO() + zobj.write(urllib2.urlopen(url).read()) + z = zipfile.ZipFile(zobj) + print "Got URL: %s" % url + + srtm_path = os.path.join(srtm_dir, srtm_filename) + out_file = open(srtm_path, 'w') + out_file.write(z.read(srtm_filename)) + + z.close() + out_file.close() + #md.destroy() + + + def get_srtm_filename(self, lat, lon): + """ + Filename of GeoTIFF file containing data with given coordinates. + """ + colmin = floor((6000 * (180 + lon)) / 5) + rowmin = floor((6000 * (60 - lat)) / 5) + + ilon = ceil(colmin / 6000.0) + ilat = ceil(rowmin / 6000.0) + + #return 'srtm_%02d_%02d.TIF' % (ilon, ilat) + return 'srtm_%02d_%02d.tif' % (ilon, ilat) + + def get_elevation(self, lat, lon): + """ + Returns the elevation in metres of point (lat, lon). + """ + srtm_filename = self.get_srtm_filename(lat, lon) + if srtm_filename not in self._cache: + srtm_path = os.path.join(os.path.expanduser('~/.pytrainer/SRTM_data'), srtm_filename) + if not os.path.isfile(srtm_path): + self._download_srtm_tiff(srtm_filename) + else: + print "File already downloaded (%s)" % srtm_filename + + self._cache[srtm_filename] = SrtmTiff(srtm_path) + + srtm = self._cache[srtm_filename] + return srtm.get_elevation(lat, lon) Added: pytrainer/trunk/pytrainer/lib/srtmtiff.py =================================================================== --- pytrainer/trunk/pytrainer/lib/srtmtiff.py (rev 0) +++ pytrainer/trunk/pytrainer/lib/srtmtiff.py 2010-09-28 00:44:39 UTC (rev 623) @@ -0,0 +1,145 @@ +#!/usr/bin/env python + +import logging +from math import floor +from osgeo import gdal, gdalnumeric + +# from gpxtools +def bilinear_interpolation(tl, tr, bl, br, a, b): + """ + Based on equation from: + http://en.wikipedia.org/wiki/Bilinear_interpolation + + :Parameters: + tl : int + top-left + tr : int + top-right + bl : int + buttom-left + br : int + bottom-right + a : float + x distance to top-left + b : float + y distance to top-right + + :Returns: (float) + interpolated value + """ + b1 = tl + b2 = bl - tl + b3 = tr - tl + b4 = tl - bl - tr + br + + return b1 + b2 * a + b3 * b + b4 * a * b + + +class SrtmTiff(object): + """ + Provides an interface to SRTM elevation data stored in GeoTIFF file. + + Based on code from `eleserver` code by grahamjones139. + http://code.google.com/p/eleserver/ + """ + tile = {} + + def __init__(self, filename): + """ + Reads the GeoTIFF files into memory ready for processing. + """ + self.tile = self.load_tile(filename) + + def load_tile(self, filename): + """ + Loads a GeoTIFF tile from disk and returns a dictionary containing + the file data, plus metadata about the tile. + + The dictionary returned by this function contains the following data: + xsize - the width of the tile in pixels. + ysize - the height of the tile in pixels. + lat_origin - the latitude of the top left pixel in the tile. + lon_origin - the longitude of the top left pixel in the tile. + lat_pixel - the height of one pixel in degrees latitude. + lon_pixel - the width of one pixel in degrees longitude. + N, S, E, W - the bounding box for this tile in degrees. + data - a two dimensional array containing the tile data. + + """ + dataset = gdal.Open(filename) + geotransform = dataset.GetGeoTransform() + xsize = dataset.RasterXSize + ysize = dataset.RasterYSize + lon_origin = geotransform[0] + lat_origin = geotransform[3] + lon_pixel = geotransform[1] + lat_pixel = geotransform[5] + + retdict = { + 'xsize': xsize, + 'ysize': ysize, + 'lat_origin': lat_origin, + 'lon_origin': lon_origin, + 'lon_pixel': lon_pixel, + 'lat_pixel': lat_pixel, + 'N': lat_origin, + 'S': lat_origin + lat_pixel*ysize, + 'E': lon_origin + lon_pixel*xsize, + 'W': lon_origin, + 'dataset': dataset, + } + + return retdict + + def pos_from_lat_lon(self, lat, lon): + """ + Converts coordinates (lat,lon) into the appropriate (row,column) + position in the GeoTIFF tile data stored in td. + """ + td = self.tile + N = td['N'] + S = td['S'] + E = td['E'] + W = td['W'] + lat_pixel = td['lat_pixel'] + lon_pixel = td['lon_pixel'] + xsize = td['xsize'] + ysize = td['ysize'] + + rowno_f = (lat-N)/lat_pixel + colno_f = (lon-W)/lon_pixel + rowno = int(floor(rowno_f)) + colno = int(floor(colno_f)) + + # Error checking to correct any rounding errors. + if (rowno<0): + rowno = 0 + if (rowno>(xsize-1)): + rowno = xsize-1 + if (colno<0): + colno = 0 + if (colno>(ysize-1)): + colno = xsize-1 + + return (rowno, colno, rowno_f, colno_f) + + def get_elevation(self, lat, lon): + """ + Returns the elevation in metres of point (lat, lon). + + Uses bilinar interpolation to interpolate the SRTM data to the + required point. + """ + row, col, row_f, col_f = self.pos_from_lat_lon(lat, lon) + + # NOTE - THIS IS A FIDDLE TO STOP ERRORS AT THE EDGE OF + # TILES - IT IS NO CORRECT - WE SHOULD GET TWO POINTS + # FROM THE NEXT TILE. + if row==5999: row=5998 + if col==5999: col=5998 + + htarr = gdalnumeric.DatasetReadAsArray(self.tile['dataset'], col, row, 2, 2) + height = bilinear_interpolation(htarr[0][0], htarr[0][1], htarr[1][0], htarr[1][1], + row_f-row, col_f-col) + + return height Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-28 00:20:39 UTC (rev 622) +++ pytrainer/trunk/pytrainer/main.py 2010-09-28 00:44:39 UTC (rev 623) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#622" + self.version ="1.7.2_svn#623" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-28 00:20:47
|
Revision: 622 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=622&view=rev Author: jblance Date: 2010-09-28 00:20:39 +0000 (Tue, 28 Sep 2010) Log Message: ----------- Reinstate new graphing approach test code - including update to options to allow 'turning on' Modified Paths: -------------- pytrainer/trunk/glade/profile.glade pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/gui/windowprofile.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/profile.glade =================================================================== --- pytrainer/trunk/glade/profile.glade 2010-09-27 23:13:43 UTC (rev 621) +++ pytrainer/trunk/glade/profile.glade 2010-09-28 00:20:39 UTC (rev 622) @@ -1659,7 +1659,7 @@ <child> <widget class="GtkTable" id="table1"> <property name="visible">True</property> - <property name="n_rows">6</property> + <property name="n_rows">7</property> <property name="n_columns">3</property> <child> <widget class="GtkLabel" id="labelLogLevel"> @@ -1931,6 +1931,51 @@ <property name="bottom_attach">6</property> </packing> </child> + <child> + <widget class="GtkLabel" id="labelNewGraph"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">5</property> + <property name="ypad">5</property> + <property name="label" translatable="yes">New Graph</property> + </widget> + <packing> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkbuttonNewGraph"> + <property name="label">--newgraph</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_checkbuttonNewGraph_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + <property name="x_padding">10</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="labelNewGraphDescription"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">5</property> + <property name="label" translatable="yes"><small>Want to use experimental new approach to graphing?</small></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> </widget> </child> </widget> Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-27 23:13:43 UTC (rev 621) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-28 00:20:39 UTC (rev 622) @@ -271,19 +271,74 @@ logging.debug(">>") self.record_list = activity.tracks self.laps = activity.laps - if self.record_list is not None and len(self.record_list)>0: - self.record_vbox.set_sensitive(1) - self.drawarearecord.drawgraph(self.record_list,self.laps) + if activity.gpx_file is not None: + if not self.pytrainer_main.startup_options.newgraph: + logging.debug("Using the original graphing") + logging.debug("Activity has GPX data") + #Show drop down boxes + self.hbox30.show() + #Hide new graph details + self.graph_data_hbox.hide() + self.record_vbox.set_sensitive(1) + self.drawarearecord.drawgraph(self.record_list,self.laps) + else: + #Still just test code.... + logging.debug("Using the new TEST graphing approach") + #Hide current drop down boxes + self.hbox30.hide() + #Create a frame showing data available for graphing + #Remove existing frames + for child in self.graph_data_hbox.get_children(): + self.graph_data_hbox.remove(child) + #Build frames and vboxs to hold checkbuttons + xFrame = gtk.Frame(label="Show on X Axis") + y1Frame = gtk.Frame(label="Show on Y1 Axis") + y2Frame = gtk.Frame(label="Show on Y2 Axis") + xvbox = gtk.VBox() + y1vbox = gtk.VBox() + y2vbox = gtk.VBox() + #Populate X axis data + xdistancebutton = gtk.RadioButton(label="Distance") + xdistancebutton.connect("toggled", self.on_xaxischange, "distance") + xdistancebutton.set_active(True) + xvbox.add(xdistancebutton) + xtimebutton = gtk.RadioButton(group=xdistancebutton, label="Time") + xtimebutton.connect("toggled", self.on_xaxischange, "time") + xvbox.add(xtimebutton) + xFrame.add(xvbox) + #Populate Y axis data + for graphdata in activity.distance_data: + y1button = gtk.CheckButton(label=activity.distance_data[graphdata].title) + y1button.connect("toggled", self.on_y1change, y1vbox, activity.distance_data[graphdata]) + y2button = gtk.CheckButton(label=activity.distance_data[graphdata].title) + y2button.connect("toggled", self.on_y2change, y2vbox) + y1vbox.add(y1button) + y2vbox.add(y2button) + y1Frame.add(y1vbox) + y2Frame.add(y2vbox) + self.graph_data_hbox.pack_start(xFrame, expand=False, fill=True, padding=0) + self.graph_data_hbox.pack_start(y1Frame, expand=False, fill=True, padding=0) + self.graph_data_hbox.pack_start(y2Frame, expand=False, fill=True, padding=0) + self.graph_data_hbox.show_all() + + #TODO Fix... + self.record_vbox.set_sensitive(1) + self.drawarearecord.drawgraph(self.record_list,self.laps) else: + logging.debug("Activity has no GPX data") + #Show drop down boxes + self.hbox30.show() + #Hide new graph details + self.graph_data_hbox.hide() #Remove graph - vboxChildren = self.record_vbox.get_children() + vboxChildren = self.record_graph_vbox.get_children() logging.debug('Vbox has %d children %s' % (len(vboxChildren), str(vboxChildren) )) # ToDo: check why vertical container is shared for child in vboxChildren: #Remove all FigureCanvasGTK and NavigationToolbar2GTKAgg to stop double ups of graphs if isinstance(child, matplotlib.backends.backend_gtkagg.FigureCanvasGTK) or isinstance(child, matplotlib.backends.backend_gtkagg.NavigationToolbar2GTKAgg): logging.debug('Removing child: '+str(child)) - self.record_vbox.remove(child) + self.record_graph_vbox.remove(child) self.record_vbox.set_sensitive(0) logging.debug("<<") @@ -929,6 +984,28 @@ ## Lista de eventos ## ###################### + def on_xaxischange(self, widget, data=None): + '''Handler for record graph axis selection changes''' + if widget.get_active(): + print data + + def on_y1change(self, widget, box, data): + '''Hander for changes to y1 selection''' + print "Y1 selected: " + for child in box.get_children(): + if child.get_active(): + #This check box is active, so display graph... + #drawgraph to self.record_graph_vbox with data... + print child.get_label(), data + + def on_y2change(self, widget, box): + '''Hander for changes to y2 selection''' + print "Y2 selected: ", + for child in box.get_children(): + if child.get_active(): + print child.get_label(), + print + def on_athleteTreeView_button_press_event(self, treeview, event): x = int(event.x) y = int(event.y) Modified: pytrainer/trunk/pytrainer/gui/windowprofile.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowprofile.py 2010-09-27 23:13:43 UTC (rev 621) +++ pytrainer/trunk/pytrainer/gui/windowprofile.py 2010-09-28 00:20:39 UTC (rev 622) @@ -23,367 +23,382 @@ import logging class WindowProfile(SimpleGladeApp): - def __init__(self, data_path = None, parent=None, pytrainer_main=None): - glade_path="glade/profile.glade" - root = "newprofile" - domain = None - self.parent = parent - self.pytrainer_main = pytrainer_main - self.data_path = data_path - SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) - self.conf_options = parent.profile_options + def __init__(self, data_path = None, parent=None, pytrainer_main=None): + glade_path="glade/profile.glade" + root = "newprofile" + domain = None + self.parent = parent + self.pytrainer_main = pytrainer_main + self.data_path = data_path + SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) + self.conf_options = parent.profile_options - def new(self): - self.gender_options = { - 0:_("Male"), - 1:_("Female") - } + def new(self): + self.gender_options = { + 0:_("Male"), + 1:_("Female") + } - self.ddbb_type = { - 0:"sqlite", - 1:"mysql" - } - - #anhadimos las opciones al combobox gender - for i in self.gender_options: - self.prf_gender.insert_text(i,self.gender_options[i]) - - #hacemos lo propio para el combobox ddbb - for i in self.ddbb_type: - self.prf_ddbb.insert_text(i,self.ddbb_type[i]) + self.ddbb_type = { + 0:"sqlite", + 1:"mysql" + } + + #anhadimos las opciones al combobox gender + for i in self.gender_options: + self.prf_gender.insert_text(i,self.gender_options[i]) + + #hacemos lo propio para el combobox ddbb + for i in self.ddbb_type: + self.prf_ddbb.insert_text(i,self.ddbb_type[i]) - #preparamos la lista sports: - column_names=[_("Sport"),_("MET"),_("Extra Weight")] - for column_index, column_name in enumerate(column_names): - column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) - column.set_resizable(True) - self.sportTreeView.append_column(column) - - def setValues(self,list_options): - for i in self.conf_options.keys(): - if not list_options.has_key(i): - print 'no list options for: ' + i - continue - if i == "default_viewer": - if list_options[i] == "1": - logging.debug("Setting defult map viewer to OSM") - self.radiobuttonDefaultOSM.set_active(1) - else: - logging.debug("Setting defult map viewer to Google") - self.radiobuttonDefaultGMap.set_active(1) - else: - try: - var = getattr(self,i) - except AttributeError as e: - continue - if i == "prf_hrzones_karvonen" or i == "prf_us_system": - if list_options[i]=="True": - var.set_active(True) - - elif i == "prf_gender": - for j in self.gender_options: - if self.gender_options[j]==list_options[i]: - var.set_active(j) - elif i == "prf_ddbb": - for j in self.ddbb_type: - if self.ddbb_type[j]==list_options[i]: - var.set_active(j) - if j==0: - self._ddbb_value_deactive() - else: - self._ddbb_value_active() - else: - var.set_text(list_options[i]) - - def saveOptions(self): - list_options = {} - for i in self.conf_options.keys(): - if i == "default_viewer": - if self.radiobuttonDefaultOSM.get_active(): - list_options[i] = "1" - else: - list_options[i] = "0" - else: - try: - var = getattr(self,i) - except AttributeError as e: - continue - if i == "prf_hrzones_karvonen" or i == "prf_us_system": - if var.get_active(): - list_options[i] = "True" - else: - list_options[i] = "False" - elif i == "prf_gender" or i == "prf_ddbb": - list_options[i] = var.get_active_text() - else: - list_options[i] = var.get_text() - self.parent.setProfile(list_options) - - def on_calendar_clicked(self,widget): - calendardialog = WindowCalendar(self.data_path,self) - calendardialog.run() + #preparamos la lista sports: + column_names=[_("Sport"),_("MET"),_("Extra Weight")] + for column_index, column_name in enumerate(column_names): + column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) + column.set_resizable(True) + self.sportTreeView.append_column(column) + + def setValues(self,list_options): + for i in self.conf_options.keys(): + if not list_options.has_key(i): + print 'no list options for: ' + i + continue + if i == "default_viewer": + if list_options[i] == "1": + logging.debug("Setting defult map viewer to OSM") + self.radiobuttonDefaultOSM.set_active(1) + else: + logging.debug("Setting defult map viewer to Google") + self.radiobuttonDefaultGMap.set_active(1) + else: + try: + var = getattr(self,i) + except AttributeError as e: + continue + if i == "prf_hrzones_karvonen" or i == "prf_us_system": + if list_options[i]=="True": + var.set_active(True) + + elif i == "prf_gender": + for j in self.gender_options: + if self.gender_options[j]==list_options[i]: + var.set_active(j) + elif i == "prf_ddbb": + for j in self.ddbb_type: + if self.ddbb_type[j]==list_options[i]: + var.set_active(j) + if j==0: + self._ddbb_value_deactive() + else: + self._ddbb_value_active() + else: + var.set_text(list_options[i]) + + def saveOptions(self): + list_options = {} + for i in self.conf_options.keys(): + if i == "default_viewer": + if self.radiobuttonDefaultOSM.get_active(): + list_options[i] = "1" + else: + list_options[i] = "0" + else: + try: + var = getattr(self,i) + except AttributeError as e: + continue + if i == "prf_hrzones_karvonen" or i == "prf_us_system": + if var.get_active(): + list_options[i] = "True" + else: + list_options[i] = "False" + elif i == "prf_gender" or i == "prf_ddbb": + list_options[i] = var.get_active_text() + else: + list_options[i] = var.get_text() + self.parent.setProfile(list_options) + + def on_calendar_clicked(self,widget): + calendardialog = WindowCalendar(self.data_path,self) + calendardialog.run() - def setDate(self,date): - self.prf_age.set_text(date) + def setDate(self,date): + self.prf_age.set_text(date) - def on_switch_page(self,widget,pointer,frame): - #print widget, pointer, frame - if frame==2: - self.saveOptions() - sport_list = self.parent.getSportList() - if sport_list == 0: - pass - elif sport_list == -1: - self.sportlistbutton.set_label("It is not possible connect to the server") - else: - store = gtk.ListStore( - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - object) - for i in sport_list: - if not i[1]: - met = i[1] - else: - met = 0 - if not i[2]: - weight = i[2] - else: - weight = 0 - iter = store.append() - store.set ( - iter, - 0, str(i[0]), - 1, i[1], - 2, i[2] - ) - self.sportTreeView.set_model(store) - #self.sportlistbutton.hide() - self.sportlist.show() - elif frame == 4: #Startup Parameters page selected - self.init_params_tab() - - def init_params_tab(self): - #Show log level - if self.pytrainer_main.startup_options.log_level == logging.ERROR: - self.comboboxLogLevel.set_active(0) - elif self.pytrainer_main.startup_options.log_level == logging.WARNING: - self.comboboxLogLevel.set_active(1) - elif self.pytrainer_main.startup_options.log_level == logging.INFO: - self.comboboxLogLevel.set_active(2) - elif self.pytrainer_main.startup_options.log_level == logging.DEBUG: - self.comboboxLogLevel.set_active(3) - else: - self.comboboxLogLevel.set_active(0) - print "Unknown logging level specified" + def on_switch_page(self,widget,pointer,frame): + #print widget, pointer, frame + if frame==2: + self.saveOptions() + sport_list = self.parent.getSportList() + logging.debug("Got sport_list: %s" % str(sport_list) ) + if sport_list == 0: + pass + elif sport_list == -1: + self.sportlistbutton.set_label("It is not possible connect to the server") + else: + store = gtk.ListStore( + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + object) + for i in sport_list: + if not i[1]: + met = i[1] + else: + met = 0 + if not i[2]: + weight = i[2] + else: + weight = 0 + iter = store.append() + store.set ( + iter, + 0, str(i[0]), + 1, i[1], + 2, i[2] + ) + self.sportTreeView.set_model(store) + #self.sportlistbutton.hide() + self.sportlist.show() + elif frame == 4: #Startup Parameters page selected + self.init_params_tab() + + def init_params_tab(self): + #Show log level + if self.pytrainer_main.startup_options.log_level == logging.ERROR: + self.comboboxLogLevel.set_active(0) + elif self.pytrainer_main.startup_options.log_level == logging.WARNING: + self.comboboxLogLevel.set_active(1) + elif self.pytrainer_main.startup_options.log_level == logging.INFO: + self.comboboxLogLevel.set_active(2) + elif self.pytrainer_main.startup_options.log_level == logging.DEBUG: + self.comboboxLogLevel.set_active(3) + else: + self.comboboxLogLevel.set_active(0) + print "Unknown logging level specified" - #Show if validation requested - if self.pytrainer_main.startup_options.validate: - self.checkbuttonValidate.set_active(True) - else: - self.checkbuttonValidate.set_active(False) - - #Show if database and config check requested - if self.pytrainer_main.startup_options.check: - self.checkbuttonCheck.set_active(True) - else: - self.checkbuttonCheck.set_active(False) - - #Show if using Googlemaps API v3 - if self.pytrainer_main.startup_options.gm3: - self.checkbuttonGM3.set_active(True) - else: - self.checkbuttonGM3.set_active(False) - - #Show if unified import activated - if self.pytrainer_main.startup_options.testimport: - self.checkbuttonUnifiedImport.set_active(True) - else: - self.checkbuttonUnifiedImport.set_active(False) - - def on_comboboxLogLevel_changed(self, widget): - active = self.comboboxLogLevel.get_active() - if active == 1: - logging.debug("Setting log level to WARNING") - self.pytrainer_main.startup_options.log_level = logging.WARNING - elif active == 2: - logging.debug("Setting log level to INFO") - self.pytrainer_main.startup_options.log_level = logging.INFO - elif active == 3: - logging.debug("Setting log level to DEBUG") - self.pytrainer_main.startup_options.log_level = logging.DEBUG - else: - logging.debug("Setting log level to ERROR") - self.pytrainer_main.startup_options.log_level = logging.ERROR - self.pytrainer_main.set_logging_level(self.pytrainer_main.startup_options.log_level) - - def on_checkbuttonValidate_toggled(self, widget): - if self.checkbuttonValidate.get_active(): - logging.debug( "Validate activated") - self.pytrainer_main.startup_options.validate = True - else: - logging.debug("Validate deactivated") - self.pytrainer_main.startup_options.validate = False - - def on_checkbuttonCheck_toggled(self, widget): - if self.checkbuttonCheck.get_active(): - logging.debug( "Check activated") - if self.pytrainer_main.startup_options.check is not True: - #Need to do sanitycheck - logging.debug("Need to do sanitycheck") - self.pytrainer_main.sanityCheck() - self.pytrainer_main.startup_options.check = True - else: - logging.debug("Check deactivated") - self.pytrainer_main.startup_options.check = False - - def on_checkbuttonGM3_toggled(self, widget): - if self.checkbuttonGM3.get_active(): - logging.debug("GM3 activated") - self.pytrainer_main.startup_options.gm3 = True - else: - logging.debug("GM3 deactivated") - self.pytrainer_main.startup_options.gm3 = False - - def on_checkbuttonUnifiedImport_toggled(self, widget): - if self.checkbuttonUnifiedImport.get_active(): - logging.debug("Unified Import activated") - if self.pytrainer_main.startup_options.testimport is not True: - #Need to enable unified import - logging.debug("Need to enable unified import") - self.pytrainer_main.windowmain.set_unified_import(True) - else: - #No change - logging.debug("No change to unified import") - else: - logging.debug("Unified Import deactivated") - if self.pytrainer_main.startup_options.testimport is True: - logging.debug("Need to deactivate unified import") - self.pytrainer_main.windowmain.set_unified_import(False) - else: - logging.debug("No change to unified import") - - def on_sportlistbutton_clicked(self,widget): - sport_list = self.parent.getSportList() - if sport_list == 0: - self.parent.build_ddbb() - self.sportlistbutton.hide() - self.sportlist.show() - - - def on_accept_clicked(self,widget): - self.saveOptions() - self.close_window() - - def on_cancel_clicked(self,widget): - self.close_window() + #Show if validation requested + if self.pytrainer_main.startup_options.validate: + self.checkbuttonValidate.set_active(True) + else: + self.checkbuttonValidate.set_active(False) + + #Show if database and config check requested + if self.pytrainer_main.startup_options.check: + self.checkbuttonCheck.set_active(True) + else: + self.checkbuttonCheck.set_active(False) + + #Show if using Googlemaps API v3 + if self.pytrainer_main.startup_options.gm3: + self.checkbuttonGM3.set_active(True) + else: + self.checkbuttonGM3.set_active(False) + + #Show if unified import activated + if self.pytrainer_main.startup_options.testimport: + self.checkbuttonUnifiedImport.set_active(True) + else: + self.checkbuttonUnifiedImport.set_active(False) + + #Show if new graph activated + if self.pytrainer_main.startup_options.newgraph: + self.checkbuttonNewGraph.set_active(True) + else: + self.checkbuttonNewGraph.set_active(False) + + def on_comboboxLogLevel_changed(self, widget): + active = self.comboboxLogLevel.get_active() + if active == 1: + logging.debug("Setting log level to WARNING") + self.pytrainer_main.startup_options.log_level = logging.WARNING + elif active == 2: + logging.debug("Setting log level to INFO") + self.pytrainer_main.startup_options.log_level = logging.INFO + elif active == 3: + logging.debug("Setting log level to DEBUG") + self.pytrainer_main.startup_options.log_level = logging.DEBUG + else: + logging.debug("Setting log level to ERROR") + self.pytrainer_main.startup_options.log_level = logging.ERROR + self.pytrainer_main.set_logging_level(self.pytrainer_main.startup_options.log_level) + + def on_checkbuttonValidate_toggled(self, widget): + if self.checkbuttonValidate.get_active(): + logging.debug( "Validate activated") + self.pytrainer_main.startup_options.validate = True + else: + logging.debug("Validate deactivated") + self.pytrainer_main.startup_options.validate = False + + def on_checkbuttonCheck_toggled(self, widget): + if self.checkbuttonCheck.get_active(): + logging.debug( "Check activated") + if self.pytrainer_main.startup_options.check is not True: + #Need to do sanitycheck + logging.debug("Need to do sanitycheck") + self.pytrainer_main.sanityCheck() + self.pytrainer_main.startup_options.check = True + else: + logging.debug("Check deactivated") + self.pytrainer_main.startup_options.check = False + + def on_checkbuttonGM3_toggled(self, widget): + if self.checkbuttonGM3.get_active(): + logging.debug("GM3 activated") + self.pytrainer_main.startup_options.gm3 = True + else: + logging.debug("GM3 deactivated") + self.pytrainer_main.startup_options.gm3 = False + + def on_checkbuttonUnifiedImport_toggled(self, widget): + if self.checkbuttonUnifiedImport.get_active(): + logging.debug("Unified Import activated") + if self.pytrainer_main.startup_options.testimport is not True: + #Need to enable unified import + logging.debug("Need to enable unified import") + self.pytrainer_main.windowmain.set_unified_import(True) + else: + #No change + logging.debug("No change to unified import") + else: + logging.debug("Unified Import deactivated") + if self.pytrainer_main.startup_options.testimport is True: + logging.debug("Need to deactivate unified import") + self.pytrainer_main.windowmain.set_unified_import(False) + else: + logging.debug("No change to unified import") + + def on_checkbuttonNewGraph_toggled(self, widget): + if self.checkbuttonNewGraph.get_active(): + logging.debug("NewGraph activated") + self.pytrainer_main.startup_options.newgraph = True + else: + logging.debug("NewGraph deactivated") + self.pytrainer_main.startup_options.newgraph = False + + def on_sportlistbutton_clicked(self,widget): + sport_list = self.parent.getSportList() + if sport_list == 0: + self.parent.build_ddbb() + self.sportlistbutton.hide() + self.sportlist.show() + + + def on_accept_clicked(self,widget): + self.saveOptions() + self.close_window() + + def on_cancel_clicked(self,widget): + self.close_window() - def close_window(self): - self.newprofile.hide() - self.newprofile = None - self.quit() + def close_window(self): + self.newprofile.hide() + self.newprofile = None + self.quit() - def _ddbb_value_active(self): - self.prf_ddbbhost_label.set_sensitive(1) - self.prf_ddbbname_label.set_sensitive(1) - self.prf_ddbbuser_label.set_sensitive(1) - self.prf_ddbbpass_label.set_sensitive(1) - self.prf_ddbbhost.set_sensitive(1) - self.prf_ddbbname.set_sensitive(1) - self.prf_ddbbuser.set_sensitive(1) - self.prf_ddbbpass.set_sensitive(1) - - def _ddbb_value_deactive(self): - self.prf_ddbbhost_label.set_sensitive(0) - self.prf_ddbbname_label.set_sensitive(0) - self.prf_ddbbuser_label.set_sensitive(0) - self.prf_ddbbpass_label.set_sensitive(0) - self.prf_ddbbhost.set_sensitive(0) - self.prf_ddbbname.set_sensitive(0) - self.prf_ddbbuser.set_sensitive(0) - self.prf_ddbbpass.set_sensitive(0) + def _ddbb_value_active(self): + self.prf_ddbbhost_label.set_sensitive(1) + self.prf_ddbbname_label.set_sensitive(1) + self.prf_ddbbuser_label.set_sensitive(1) + self.prf_ddbbpass_label.set_sensitive(1) + self.prf_ddbbhost.set_sensitive(1) + self.prf_ddbbname.set_sensitive(1) + self.prf_ddbbuser.set_sensitive(1) + self.prf_ddbbpass.set_sensitive(1) + + def _ddbb_value_deactive(self): + self.prf_ddbbhost_label.set_sensitive(0) + self.prf_ddbbname_label.set_sensitive(0) + self.prf_ddbbuser_label.set_sensitive(0) + self.prf_ddbbpass_label.set_sensitive(0) + self.prf_ddbbhost.set_sensitive(0) + self.prf_ddbbname.set_sensitive(0) + self.prf_ddbbuser.set_sensitive(0) + self.prf_ddbbpass.set_sensitive(0) - def on_prf_ddbb_changed(self,widget): - i = self.prf_ddbb.get_active_text() - if i == "mysql": - self._ddbb_value_active() - else: - self._ddbb_value_deactive() + def on_prf_ddbb_changed(self,widget): + i = self.prf_ddbb.get_active_text() + if i == "mysql": + self._ddbb_value_active() + else: + self._ddbb_value_deactive() - def on_addsport_clicked(self,widget): - self.hidesportsteps() - self.buttonbox.set_sensitive(0) - self.addsport.show() + def on_addsport_clicked(self,widget): + self.hidesportsteps() + self.buttonbox.set_sensitive(0) + self.addsport.show() - def on_newsport_accept_clicked(self,widget): - sport = self.newsportentry.get_text() - met = self.newmetentry.get_text() - weight = self.newweightentry.get_text() - self.parent.addNewSport(sport,met,weight) - self.parent.actualize_mainsportlist() - self.on_switch_page(None,None,2) - self.hidesportsteps() - self.buttonbox.set_sensitive(1) - self.sportlist.show() + def on_newsport_accept_clicked(self,widget): + sport = self.newsportentry.get_text() + met = self.newmetentry.get_text() + weight = self.newweightentry.get_text() + self.parent.addNewSport(sport,met,weight) + self.parent.actualize_mainsportlist() + self.on_switch_page(None,None,2) + self.hidesportsteps() + self.buttonbox.set_sensitive(1) + self.sportlist.show() - def on_delsport_clicked(self,widget): - selected,iter = self.sportTreeView.get_selection().get_selected() - if iter: - self.buttonbox.set_sensitive(0) - sport = selected.get_value(iter,0) - self.sportnamedel.set_text(sport) - self.hidesportsteps() - self.deletesport.show() + def on_delsport_clicked(self,widget): + selected,iter = self.sportTreeView.get_selection().get_selected() + if iter: + self.buttonbox.set_sensitive(0) + sport = selected.get_value(iter,0) + self.sportnamedel.set_text(sport) + self.hidesportsteps() + self.deletesport.show() - def on_deletesport_clicked(self,widget): - sport = self.sportnamedel.get_text() - self.parent.delSport(sport) - self.parent.actualize_mainsportlist() - self.on_switch_page(None,None,2) - self.hidesportsteps() - self.buttonbox.set_sensitive(1) - self.sportlist.show() - - def on_editsport_clicked(self,widget): - self.buttonbox.set_sensitive(0) - selected,iter = self.sportTreeView.get_selection().get_selected() - if iter: - sport = selected.get_value(iter,0) - name,met,weight = self.parent.getSportInfo(sport) - self.editsportentry.set_text(sport) - self.sportnameedit.set_text(sport) - self.editweightentry.set_text(str(weight)) - self.editmetentry.set_text(str(met)) - self.hidesportsteps() - self.editsport.show() - - def on_editsport_accept_clicked(self,widget): - oldnamesport = self.sportnameedit.get_text() - newnamesport = self.editsportentry.get_text() - newmetsport = self.editmetentry.get_text() - newweightsport = self.editweightentry.get_text() - self.parent.updateSport(oldnamesport,newnamesport,newmetsport,newweightsport) - self.parent.actualize_mainsportlist() - self.on_switch_page(None,None,2) - self.hidesportsteps() - self.buttonbox.set_sensitive(1) - self.sportlist.show() - - def on_sportcancel_clicked(self,widget): - self.hidesportsteps() - self.buttonbox.set_sensitive(1) - self.sportlist.show() + def on_deletesport_clicked(self,widget): + sport = self.sportnamedel.get_text() + self.parent.delSport(sport) + self.parent.actualize_mainsportlist() + self.on_switch_page(None,None,2) + self.hidesportsteps() + self.buttonbox.set_sensitive(1) + self.sportlist.show() + + def on_editsport_clicked(self,widget): + self.buttonbox.set_sensitive(0) + selected,iter = self.sportTreeView.get_selection().get_selected() + if iter: + sport = selected.get_value(iter,0) + name,met,weight = self.parent.getSportInfo(sport) + self.editsportentry.set_text(sport) + self.sportnameedit.set_text(sport) + self.editweightentry.set_text(str(weight)) + self.editmetentry.set_text(str(met)) + self.hidesportsteps() + self.editsport.show() + + def on_editsport_accept_clicked(self,widget): + oldnamesport = self.sportnameedit.get_text() + newnamesport = self.editsportentry.get_text() + newmetsport = self.editmetentry.get_text() + newweightsport = self.editweightentry.get_text() + self.parent.updateSport(oldnamesport,newnamesport,newmetsport,newweightsport) + self.parent.actualize_mainsportlist() + self.on_switch_page(None,None,2) + self.hidesportsteps() + self.buttonbox.set_sensitive(1) + self.sportlist.show() + + def on_sportcancel_clicked(self,widget): + self.hidesportsteps() + self.buttonbox.set_sensitive(1) + self.sportlist.show() - def on_calculatemaxhr_clicked(self,widget=None): - import datetime - today = "%s"%datetime.date.today() - year1,month1,day1 = today.split("-") - year2,month2,day2 = self.prf_age.get_text().split("-") - diff = datetime.datetime(int(year1), int(month1), int(day1),0,0,0) - datetime.datetime(int(year2), int(month2), int(day2),0,0,0) - self.prf_maxhr.set_text("%d" %(220-int(diff.days/365))) + def on_calculatemaxhr_clicked(self,widget=None): + import datetime + today = "%s"%datetime.date.today() + year1,month1,day1 = today.split("-") + year2,month2,day2 = self.prf_age.get_text().split("-") + diff = datetime.datetime(int(year1), int(month1), int(day1),0,0,0) - datetime.datetime(int(year2), int(month2), int(day2),0,0,0) + self.prf_maxhr.set_text("%d" %(220-int(diff.days/365))) - def hidesportsteps(self): - self.sportlist.hide() - self.addsport.hide() - self.deletesport.hide() - self.editsport.hide() + def hidesportsteps(self): + self.sportlist.hide() + self.addsport.hide() + self.deletesport.hide() + self.editsport.hide() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-27 23:13:43 UTC (rev 621) +++ pytrainer/trunk/pytrainer/main.py 2010-09-28 00:20:39 UTC (rev 622) @@ -47,431 +47,432 @@ from lib.ddbb import DDBB class pyTrainer: - def __init__(self,filename = None, data_path = None): - #Version constants - self.version ="1.7.2_svn#621" - self.DB_version = 3 - #Process command line options - self.startup_options = self.get_options() - #Setup logging - self.set_logging(self.startup_options.log_level) - logging.debug('>>') - self.data_path = data_path - self.date = Date() - self.ddbb = None - # Checking profile - logging.debug('Checking configuration and profile...') - self.profile = Profile(self.data_path,self) - self.windowmain = None - self.ddbb = DDBB(self.profile) - logging.debug('connecting to DDBB') - self.ddbb.connect() + def __init__(self,filename = None, data_path = None): + #Version constants + self.version ="1.7.2_svn#622" + self.DB_version = 3 + #Process command line options + self.startup_options = self.get_options() + #Setup logging + self.set_logging(self.startup_options.log_level) + logging.debug('>>') + self.data_path = data_path + self.date = Date() + self.ddbb = None + # Checking profile + logging.debug('Checking configuration and profile...') + self.profile = Profile(self.data_path,self) + self.windowmain = None + self.ddbb = DDBB(self.profile) + logging.debug('connecting to DDBB') + self.ddbb.connect() - #Get user's DB version - currentDB_version = self.profile.getValue("pytraining","DB_version") - logging.debug("Current DB version: "+str(currentDB_version)) - # DB check can be triggered either via new version (mandatory) or as runtime parameter (--check) - if self.startup_options.check: # User requested check - self.sanityCheck() - elif currentDB_version is None: # No stored DB version - check DB etc - self.sanityCheck() - elif self.DB_version > int(currentDB_version): # DB version expected is newer than user's version - check DB etc - self.sanityCheck() - else: - logging.info('No sanity check requested') - self.record = Record(data_path,self) - pool_size = self.profile.getIntValue("pytraining","activitypool_size", default=1) - self.activitypool = ActivityPool(self, size=pool_size) - #preparamos la ventana principal - self.windowmain = Main(data_path,self,self.version, gpxDir=self.profile.gpxdir) - self.date = Date(self.windowmain.calendar) - self.waypoint = Waypoint(data_path,self) - self.extension = Extension(data_path, self) - self.plugins = Plugins(data_path, self) - self.importdata = Importdata(data_path, self, self.profile) - self.loadPlugins() - self.loadExtensions() - self.windowmain.setup() - self.windowmain.on_calendar_selected(None) - self.refreshMainSportList() - self.windowmain.run() - logging.debug('<<') + #Get user's DB version + currentDB_version = self.profile.getValue("pytraining","DB_version") + logging.debug("Current DB version: "+str(currentDB_version)) + # DB check can be triggered either via new version (mandatory) or as runtime parameter (--check) + if self.startup_options.check: # User requested check + self.sanityCheck() + elif currentDB_version is None: # No stored DB version - check DB etc + self.sanityCheck() + elif self.DB_version > int(currentDB_version): # DB version expected is newer than user's version - check DB etc + self.sanityCheck() + else: + logging.info('No sanity check requested') + self.record = Record(data_path,self) + pool_size = self.profile.getIntValue("pytraining","activitypool_size", default=1) + self.activitypool = ActivityPool(self, size=pool_size) + #preparamos la ventana principal + self.windowmain = Main(data_path,self,self.version, gpxDir=self.profile.gpxdir) + self.date = Date(self.windowmain.calendar) + self.waypoint = Waypoint(data_path,self) + self.extension = Extension(data_path, self) + self.plugins = Plugins(data_path, self) + self.importdata = Importdata(data_path, self, self.profile) + self.loadPlugins() + self.loadExtensions() + self.windowmain.setup() + self.windowmain.on_calendar_selected(None) + self.refreshMainSportList() + self.windowmain.run() + logging.debug('<<') - def get_options(self): - ''' - Define usage and accepted options for command line startup + def get_options(self): + ''' + Define usage and accepted options for command line startup - returns: options - dict with option: value pairs - ''' - usage = '''usage: %prog [options] + returns: options - dict with option: value pairs + ''' + usage = '''usage: %prog [options] - For more help on valid options try: - %prog -h ''' - parser = OptionParser(usage=usage) - parser.set_defaults(log_level=logging.ERROR, validate=False, gm3=True, testimport=False, equip=False) - parser.add_option("-d", "--debug", action="store_const", const=logging.DEBUG, dest="log_level", help="enable logging at debug level") - parser.add_option("-i", "--info", action="store_const", const=logging.INFO, dest="log_level", help="enable logging at info level") - parser.add_option("-w", "--warn", action="store_const", const=logging.WARNING, dest="log_level", help="enable logging at warning level") - parser.add_option("--valid", action="store_true", dest="validate", help="enable validation of files imported by plugins (details at info or debug logging level) - note plugin must support validation") - parser.add_option("--check", action="store_true", dest="check", help="triggers database (only sqlite based) and configuration file sanity checks, adding fields if necessary. Backup of database is done before any change. Details at info or debug logging level") - parser.add_option("--gmaps2", action="store_false", dest="gm3", help="Use old Google Maps API version (v2)") - parser.add_option("--testimport", action="store_true", dest="testimport", help="EXPERIMENTAL: show new import functionality - for testing only USE AT YOUR OWN RISK") - parser.add_option("--equip", action="store_false", dest="equip", help="EXPERIMENTAL: enable equipment management") - (options, args) = parser.parse_args() - return options + For more help on valid options try: + %prog -h ''' + parser = OptionParser(usage=usage) + parser.set_defaults(log_level=logging.ERROR, validate=False, gm3=True, testimport=True, equip=False, newgraph=False) + parser.add_option("-d", "--debug", action="store_const", const=logging.DEBUG, dest="log_level", help="enable logging at debug level") + parser.add_option("-i", "--info", action="store_const", const=logging.INFO, dest="log_level", help="enable logging at info level") + parser.add_option("-w", "--warn", action="store_const", const=logging.WARNING, dest="log_level", help="enable logging at warning level") + parser.add_option("--valid", action="store_true", dest="validate", help="enable validation of files imported by plugins (details at info or debug logging level) - note plugin must support validation") + parser.add_option("--check", action="store_true", dest="check", help="triggers database (only sqlite based) and configuration file sanity checks, adding fields if necessary. Backup of database is done before any change. Details at info or debug logging level") + parser.add_option("--gmaps2", action="store_false", dest="gm3", help="Use old Google Maps API version (v2)") + parser.add_option("--testimport", action="store_true", dest="testimport", help="EXPERIMENTAL: show new import functionality - for testing only USE AT YOUR OWN RISK") + parser.add_option("--equip", action="store_false", dest="equip", help="EXPERIMENTAL: enable equipment management") + parser.add_option("--newgraph", action="store_true", dest="newgraph", help="EXPERIMENTAL: new graphing approach") + (options, args) = parser.parse_args() + return options - def set_logging(self,level): - '''Setup rotating log file with customized format''' - PATH = os.environ['HOME']+"/.pytrainer" - if not os.path.exists(PATH): - os.mkdir(PATH) - LOG_FILENAME = PATH + "/log.out" - rotHandler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=100000, backupCount=5) - formatter = logging.Formatter('%(asctime)s|%(levelname)s|%(module)s|%(funcName)s|%(message)s') - rotHandler.setFormatter(formatter) - logging.getLogger('').addHandler(rotHandler) - self.set_logging_level(self.startup_options.log_level) + def set_logging(self,level): + '''Setup rotating log file with customized format''' + PATH = os.environ['HOME']+"/.pytrainer" + if not os.path.exists(PATH): + os.mkdir(PATH) + LOG_FILENAME = PATH + "/log.out" + rotHandler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=100000, backupCount=5) + formatter = logging.Formatter('%(asctime)s|%(levelname)s|%(module)s|%(funcName)s|%(message)s') + rotHandler.setFormatter(formatter) + logging.getLogger('').addHandler(rotHandler) + self.set_logging_level(self.startup_options.log_level) - def set_logging_level(self, level): - '''Set level of information written to log''' - logging.debug("Setting logger to level: "+ str(level)) - logging.getLogger('').setLevel(level) + def set_logging_level(self, level): + '''Set level of information written to log''' + logging.debug("Setting logger to level: "+ str(level)) + logging.getLogger('').setLevel(level) - def quit(self): - logging.debug('--') - logging.info("Exit!") - #self.webservice.stop() - self.windowmain.gtk_main_quit() - logging.shutdown() - sys.exit() # Any nonzero value is considered “abnormal termination” by shells and the like + def quit(self): + logging.debug('--') + logging.info("Exit!") + #self.webservice.stop() + self.windowmain.gtk_main_quit() + logging.shutdown() + sys.exit() # Any nonzero value is considered “abnormal termination” by shells and the like - def loadPlugins(self): - logging.debug('>>') - activeplugins = self.plugins.getActivePlugins() - if (len(activeplugins)<1): - logging.info("No active plugins") - else: - for plugin in activeplugins: - txtbutton = self.plugins.loadPlugin(plugin) - self.windowmain.addImportPlugin(txtbutton) - logging.debug('<<') + def loadPlugins(self): + logging.debug('>>') + activeplugins = self.plugins.getActivePlugins() + if (len(activeplugins)<1): + logging.info("No active plugins") + else: + for plugin in activeplugins: + txtbutton = self.plugins.loadPlugin(plugin) + self.windowmain.addImportPlugin(txtbutton) + logging.debug('<<') - def loadExtensions(self): - logging.debug('>>') - activeextensions = self.extension.getActiveExtensions() - if (len(activeextensions)<1): - logging.info("No active extensions") - else: - for extension in activeextensions: - txtbutton = self.extension.loadExtension(extension) - self.windowmain.addExtension(txtbutton) - logging.debug('<<') + def loadExtensions(self): + logging.debug('>>') + activeextensions = self.extension.getActiveExtensions() + if (len(activeextensions)<1): + logging.info("No active extensions") + else: + for extension in activeextensions: + txtbutton = self.extension.loadExtension(extension) + self.windowmain.addExtension(txtbutton) + logging.debug('<<') - def runPlugin(self,widget,pathPlugin): - logging.debug('>>') - self.pluginClass = self.plugins.importClass(pathPlugin) - pluginFiles = self.pluginClass.run() - if pluginFiles is not None: - logging.debug("Plugin returned %d files" % (len(pluginFiles)) ) - #process returned GPX files - for (pluginFile, sport) in pluginFiles: - if os.path.isfile(pluginFile): - logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(pluginFile), sport)) - if self.record.importFromGPX(pluginFile, sport) is None: - logging.error("Error importing file "+pluginFile) - else: - logging.error('File '+pluginFile+' not valid') - else: - logging.debug("No files returned from Plugin") - self.refreshListRecords() - self.refreshGraphView("day") - logging.debug('<<') + def runPlugin(self,widget,pathPlugin): + logging.debug('>>') + self.pluginClass = self.plugins.importClass(pathPlugin) + pluginFiles = self.pluginClass.run() + if pluginFiles is not None: + logging.debug("Plugin returned %d files" % (len(pluginFiles)) ) + #process returned GPX files + for (pluginFile, sport) in pluginFiles: + if os.path.isfile(pluginFile): + logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(pluginFile), sport)) + if self.record.importFromGPX(pluginFile, sport) is None: + logging.error("Error importing file "+pluginFile) + else: + logging.error('File '+pluginFile+' not valid') + else: + logging.debug("No files returned from Plugin") + self.refreshListRecords() + self.refreshGraphView("day") + logging.debug('<<') - def runExtension(self,extension,id): - logging.debug('>>') - print("Extension id: %s" % str(id)) - activity = self.activitypool.get_activity(id) - txtbutton,pathExtension,type = extension - self.extensionClass = self.extension.importClass(pathExtension) - self.extensionClass.run(id, activity) - #if type == "record": - # #Si es record le tenemos que crear el googlemaps, el gpx y darle el id de la bbdd - # alert = self.extension.runExtension(pathExtension,id) + def runExtension(self,extension,id): + logging.debug('>>') + print("Extension id: %s" % str(id)) + activity = self.activitypool.get_activity(id) + txtbutton,pathExtension,type = extension + self.extensionClass = self.extension.importClass(pathExtension) + self.extensionClass.run(id, activity) + #if type == "record": + # #Si es record le tenemos que crear el googlemaps, el gpx y darle el id de la bbdd + # alert = self.extension.runExtension(pathExtension,id) - logging.debug('<<') + logging.debug('<<') - def refreshMainSportList(self): - logging.debug('>>') - listSport = self.profile.getSportList() - self.windowmain.updateSportList(listSport) - logging.debug('<<') + def refreshMainSportList(self): + logging.debug('>>') + listSport = self.profile.getSportList() + self.windowmain.updateSportList(listSport) + logging.debug('<<') - def refreshGraphView(self, view, sport=None): - logging.debug('>>') - if self.windowmain is None: - logging.debug("First call to refreshGraphView") - logging.debug('<<') - return - date_selected = self.date.getDate() - if view=="record": - logging.debug('record view') - if self.windowmain.recordview.get_current_page()==0: - self.refreshRecordGraphView("info") - elif self.windowmain.recordview.get_current_page()==1: - self.refreshRecordGraphView("graphs") - elif self.windowmain.recordview.get_current_page()==2: - self.refreshRecordGraphView("map") - elif self.windowmain.recordview.get_current_page()==3: - self.refreshRecordGraphView("heartrate") - elif view=="day": - logging.debug('day view') - record_list = self.record.getrecordList(date_selected) - self.windowmain.actualize_dayview(record_list) - #selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() - elif view=="week": - logging.debug('week view') - date_ini, date_end = self.date.getWeekInterval(date_selected, self.profile.prf_us_system) - sport = self.windowmain.getSportSelected() - record_list = self.record.getrecordPeriod(date_ini, date_end, sport) - self.windowmain.actualize_weekview(record_list, date_ini, date_end) - elif view=="month": - logging.debug('month view') - date_ini, date_end = self.date.getMonthInterval(date_selected) - sport = self.windowmain.getSportSelected() - record_list = self.record.getrecordPeriodSport(date_ini, date_end,sport) - nameMonth, daysInMonth = self.date.getNameMonth(date_selected) - self.windowmain.actualize_monthview(record_list, nameMonth) - self.windowmain.actualize_monthgraph(record_list, daysInMonth) - elif view=="year": - logging.debug('year view') - date_ini, date_end = self.date.getYearInterval(date_selected) - sport = self.windowmain.getSportSelected() - year = self.date.getYear(date_selected) - record_list = self.record.getrecordPeriodSport(date_ini, date_end,sport) - self.windowmain.actualize_yearview(record_list, year) - self.windowmain.actualize_yeargraph(record_list) - elif view=="listview": - logging.debug('list view') - self.refreshListView() - else: - print "Unknown view %s" % view - logging.debug('<<') + def refreshGraphView(self, view, sport=None): + logging.debug('>>') + if self.windowmain is None: + logging.debug("First call to refreshGraphView") + logging.debug('<<') + return + date_selected = self.date.getDate() + if view=="record": + logging.debug('record view') + if self.windowmain.recordview.get_current_page()==0: + self.refreshRecordGraphView("info") + elif self.windowmain.recordview.get_current_page()==1: + self.refreshRecordGraphView("graphs") + elif self.windowmain.recordview.get_current_page()==2: + self.refreshRecordGraphView("map") + elif self.windowmain.recordview.get_current_page()==3: + self.refreshRecordGraphView("heartrate") + elif view=="day": + logging.debug('day view') + record_list = self.record.getrecordList(date_selected) + self.windowmain.actualize_dayview(record_list) + #selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() + elif view=="week": + logging.debug('week view') + date_ini, date_end = self.date.getWeekInterval(date_selected, self.profile.prf_us_system) + sport = self.windowmain.getSportSelected() + record_list = self.record.getrecordPeriod(date_ini, date_end, sport) + self.windowmain.actualize_weekview(record_list, date_ini, date_end) + elif view=="month": + logging.debug('month view') + date_ini, date_end = self.date.getMonthInterval(date_selected) + sport = self.windowmain.getSportSelected() + record_list = self.record.getrecordPeriodSport(date_ini, date_end,sport) + nameMonth, daysInMonth = self.date.getNameMonth(date_selected) + self.windowmain.actualize_monthview(record_list, nameMonth) + self.windowmain.actualize_monthgraph(record_list, daysInMonth) + elif view=="year": + logging.debug('year view') + date_ini, date_end = self.date.getYearInterval(date_selected) + sport = self.windowmain.getSportSelected() + year = self.date.getYear(date_selected) + record_list = self.record.getrecordPeriodSport(date_ini, date_end,sport) + self.windowmain.actualize_yearview(record_list, year) + self.windowmain.actualize_yeargraph(record_list) + elif view=="listview": + logging.debug('list view') + self.refreshListView() + else: + print "Unknown view %s" % view + logging.debug('<<') - def refreshRecordGraphView(self, view): - logging.debug('>>') - logging.info('Working on '+view+' graph') - selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() - if iter: - id_record = selected.get_value(iter,0) - else: - id_record = None - view="info" - activity = self.activitypool.get_activity(id_record) - if view=="info": - self.windowmain.actualize_recordview(activity) - if view=="graphs": - self.windowmain.actualize_recordgraph(activity) - if view=="map": - self.refreshMapView() - if view=="heartrate": - self.windowmain.actualize_heartrategraph(activity) - self.windowmain.actualize_hrview(activity) - logging.debug('<<') + def refreshRecordGraphView(self, view): + logging.debug('>>') + logging.info('Working on '+view+' graph') + selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() + if iter: + id_record = selected.get_value(iter,0) + else: + id_record = None + view="info" + activity = self.activitypool.get_activity(id_record) + if view=="info": + self.windowmain.actualize_recordview(activity) + if view=="graphs": + self.windowmain.actualize_recordgraph(activity) + if view=="map": + self.refreshMapView() + if view=="heartrate": + self.windowmain.actualize_heartrategraph(activity) + self.windowmain.actualize_hrview(activity) + logging.debug('<<') - def refreshMapView(self, full_screen=False): - logging.debug('>>') - if self.windowmain is None: - logging.debug('Called before windowmain initialisation') - logging.debug('<<') - return - selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() - id_record = selected.get_value(iter,0) - activity = self.activitypool.get_activity(id_record) - logging.debug('Trying to show map for record '+str(id_record)) - self.windowmain.actualize_map(activity, full_screen) - logging.debug('<<') + def refreshMapView(self, full_screen=False): + logging.debug('>>') + if self.windowmain is None: + logging.debug('Called before windowmain initialisation') + logging.debug('<<') + return + selected,iter = self.windowmain.recordTreeView.get_selection().get_selected() + id_record = selected.get_value(iter,0) + activity = self.activitypool.get_ac... [truncated message content] |
From: <jb...@us...> - 2010-09-27 23:13:49
|
Revision: 621 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=621&view=rev Author: jblance Date: 2010-09-27 23:13:43 +0000 (Mon, 27 Sep 2010) Log Message: ----------- Extra debuging in DB check function Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/ddbb.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/lib/ddbb.py =================================================================== --- pytrainer/trunk/pytrainer/lib/ddbb.py 2010-09-27 23:07:11 UTC (rev 620) +++ pytrainer/trunk/pytrainer/lib/ddbb.py 2010-09-27 23:13:43 UTC (rev 621) @@ -25,217 +25,219 @@ from pytrainer.lib.date import Date class DDBB: - def __init__(self, configuration, pytrainer_main=None): - self.pytrainer_main = pytrainer_main - self.configuration = configuration - self.ddbb_type = configuration.getValue("pytraining","prf_ddbb") - if self.ddbb_type == "mysql": #TODO no longer supported? - from mysqlUtils import Sql - else: - from sqliteUtils import Sql + def __init__(self, configuration, pytrainer_main=None): + self.pytrainer_main = pytrainer_main + self.configuration = configuration + self.ddbb_type = configuration.getValue("pytraining","prf_ddbb") + if self.ddbb_type == "mysql": #TODO no longer supported? + from mysqlUtils import Sql + else: + from sqliteUtils import Sql - self.confdir = configuration.confdir - self.ddbb_path = "%s/pytrainer.ddbb" %self.confdir + self.confdir = configuration.confdir + self.ddbb_path = "%s/pytrainer.ddbb" %self.confdir - ddbb_host = configuration.getValue("pytraining","prf_ddbbhost") - ddbb = configuration.getValue("pytraining","prf_ddbbname") - ddbb_user = configuration.getValue("pytraining","prf_ddbbuser") - ddbb_pass = configuration.getValue("pytraining","prf_ddbbpass") - self.ddbbObject = Sql(ddbb_host,ddbb,ddbb_user,ddbb_pass,configuration) + ddbb_host = configuration.getValue("pytraining","prf_ddbbhost") + ddbb = configuration.getValue("pytraining","prf_ddbbname") + ddbb_user = configuration.getValue("pytraining","prf_ddbbuser") + ddbb_pass = configuration.getValue("pytraining","prf_ddbbpass") + self.ddbbObject = Sql(ddbb_host,ddbb,ddbb_user,ddbb_pass,configuration) - def connect(self): - #si devolvemos 1 ha ido todo con exito : return 1 if all successful - #con 0 es que no estaba la bbdd creada : 0 is DB not created - #con -1 imposible conectar a la maquina. : -1 is impossible to connect to the host - var = self.ddbbObject.connect() - if var == 0: - self.ddbbObject.createDDBB() - self.ddbbObject.connect() - self.ddbbObject.createTables() - var = 1 - return var + def connect(self): + #si devolvemos 1 ha ido todo con exito : return 1 if all successful + #con 0 es que no estaba la bbdd creada : 0 is DB not created + #con -1 imposible conectar a la maquina. : -1 is impossible to connect to the host + var = self.ddbbObject.connect() + if var == 0: + self.ddbbObject.createDDBB() + self.ddbbObject.connect() + self.ddbbObject.createTables() + var = 1 + return var - def disconnect(self): - self.ddbbObject.disconnect() + def disconnect(self): + self.ddbbObject.disconnect() - def build_ddbb(self): #TODO Is this needed? - self.ddbbObject.createDDBB() - self.ddbbObject.connect() - self.ddbbObject.createTables() - self.ddbbObject.createTableVersion() + def build_ddbb(self): #TODO Is this needed? + self.ddbbObject.createDDBB() + self.ddbbObject.connect() + self.ddbbObject.createTables() + self.ddbbObject.createTableVersion() - def select(self,table,cells,condition=None): - return self.ddbbObject.select(table,cells,condition) + def select(self,table,cells,condition=None): + return self.ddbbObject.select(table,cells,condition) - def select_dict(self,table,cells,condition=None): - ''' - Function to query DB - -- inputs - ---- table - string tablename(s) - ---- cells - list of cells to select - ---- condition - string to fit SQL where clause or None - -- returns - ---- list of dicts with cells as keys - ''' - return_value = [] - #Only query db if table and cells are supplied - if table is not None and cells is not None: - cellString = ','.join(cells) #create cell list string - results = self.ddbbObject.select(table,cellString,condition) - for result in results: - dict = {} - #Loop through cells and create dict of results - for i, cell in enumerate(cells): - dict[cell] = result[i] - return_value.append(dict) - return return_value + def select_dict(self,table,cells,condition=None): + ''' + Function to query DB + -- inputs + ---- table - string tablename(s) + ---- cells - list of cells to select + ---- condition - string to fit SQL where clause or None + -- returns + ---- list of dicts with cells as keys + ''' + return_value = [] + #Only query db if table and cells are supplied + if table is not None and cells is not None: + cellString = ','.join(cells) #create cell list string + results = self.ddbbObject.select(table,cellString,condition) + for result in results: + dict = {} + #Loop through cells and create dict of results + for i, cell in enumerate(cells): + dict[cell] = result[i] + return_value.append(dict) + return return_value - def insert(self,table,cells,values): - self.ddbbObject.insert(table,cells,values) + def insert(self,table,cells,values): + self.ddbbObject.insert(table,cells,values) - def delete(self,table,condition): - self.ddbbObject.delete(table,condition) + def delete(self,table,condition): + self.ddbbObject.delete(table,condition) - def update(self,table,cells,value,condition): - self.ddbbObject.update(table,cells,value,condition) + def update(self,table,cells,value,condition): + self.ddbbObject.update(table,cells,value,condition) - def lastRecord(self,table): - id = "id_" + table[:-1] #prune 's' of table name and pre-pend 'id_' to get id column - sql = "select %s from %s order by %s Desc limit 0,1" %(id,table,id) - ret_val = self.ddbbObject.freeExec(sql) - return ret_val[0][0] + def lastRecord(self,table): + id = "id_" + table[:-1] #prune 's' of table name and pre-pend 'id_' to get id column + sql = "select %s from %s order by %s Desc limit 0,1" %(id,table,id) + ret_val = self.ddbbObject.freeExec(sql) + return ret_val[0][0] - def checkDBIntegrity(self): - """17.11.2009 - dgranda - Retrieves tables and columns from database, checks current ones and adds something if missed. New in version 1.7.0 - args: none - returns: none""" - logging.debug('>>') - logging.info('Checking PyTrainer database') - if self.ddbb_type != "sqlite": - logging.error('Support for MySQL database is decommissioned, please migrate to SQLite. Exiting check') - exit(-2) - #Define the tables and their columns that should be in the database - tablesList = { "records":{ "id_record":"integer primary key autoincrement", - "date":"date", - "sport":"integer", - "distance":"float", - "time":"varchar(200)", - "beats":"float", - "average":"float", - "calories":"int", - "comments":"text", - "gpslog":"varchar(200)", - "title":"varchar(200)", - "upositive":"float", - "unegative":"float", - "maxspeed":"float", - "maxpace":"float", - "pace":"float", - "maxbeats":"float", - "date_time_local":"varchar2(20)", - "date_time_utc":"varchar2(20)", - }, - "sports":{ "id_sports":"integer primary key autoincrement", - "name":"varchar(100)", - "weight":"float", - "met":"float", - }, - "waypoints":{ "id_waypoint":"integer primary key autoincrement", - "lat":"float", - "lon":"float", - "ele":"float", - "comment":"varchar(240)", - "time":"date", - "name":"varchar(200)", - "sym":"varchar(200)", - }, - "laps":{ "id_lap": "integer primary key autoincrement", - "record": "integer", - "lap_number": "integer", - "elapsed_time": "varchar(20)", - "distance": "float", - "start_lat": "float", - "start_lon": "float", - "end_lat": "float", - "end_lon": "float", - "calories": "int", - }, - } - try: - tablesDBT = self.ddbbObject.select("sqlite_master","name", "type IN ('table','view') AND name NOT LIKE 'sqlite_%' ORDER BY name") - except: - logging.error('Not able to retrieve which tables are in DB. Printing traceback') - traceback.print_exc() - exit(-1) + def checkDBIntegrity(self): + """17.11.2009 - dgranda + Retrieves tables and columns from database, checks current ones and adds something if missed. New in version 1.7.0 + args: none + returns: none""" + logging.debug('>>') + logging.info('Checking PyTrainer database') + if self.ddbb_type != "sqlite": + logging.error('Support for MySQL database is decommissioned, please migrate to SQLite. Exiting check') + exit(-2) + #Define the tables and their columns that should be in the database + tablesList = { "records":{ "id_record":"integer primary key autoincrement", + "date":"date", + "sport":"integer", + "distance":"float", + "time":"varchar(200)", + "beats":"float", + "average":"float", + "calories":"int", + "comments":"text", + "gpslog":"varchar(200)", + "title":"varchar(200)", + "upositive":"float", + "unegative":"float", + "maxspeed":"float", + "maxpace":"float", + "pace":"float", + "maxbeats":"float", + "date_time_local":"varchar2(20)", + "date_time_utc":"varchar2(20)", + }, + "sports":{ "id_sports":"integer primary key autoincrement", + "name":"varchar(100)", + "weight":"float", + "met":"float", + }, + "waypoints":{ "id_waypoint":"integer primary key autoincrement", + "lat":"float", + "lon":"float", + "ele":"float", + "comment":"varchar(240)", + "time":"date", + "name":"varchar(200)", + "sym":"varchar(200)", + }, + "laps":{ "id_lap": "integer primary key autoincrement", + "record": "integer", + "lap_number": "integer", + "elapsed_time": "varchar(20)", + "distance": "float", + "start_lat": "float", + "start_lon": "float", + "end_lat": "float", + "end_lon": "float", + "calories": "int", + }, + } + try: + tablesDBT = self.ddbbObject.select("sqlite_master","name", "type IN ('table','view') AND name NOT LIKE 'sqlite_%' ORDER BY name") + except: + logging.error('Not able to retrieve which tables are in DB. Printing traceback') + traceback.print_exc() + exit(-1) - tablesDB = [] # Database retrieves a list with tuples ¿? - for entry in tablesDBT: - tablesDB.append(entry[0]) - logging.debug('Found '+ str(len(tablesDB))+' tables in DB: '+ str(tablesDB)) + tablesDB = [] # Database retrieves a list with tuples ¿? + for entry in tablesDBT: + tablesDB.append(entry[0]) + logging.debug('Found '+ str(len(tablesDB))+' tables in DB: '+ str(tablesDB)) - # Create a compressed copy of current DB - try: - self.createDatabaseBackup() - except: - logging.error('Not able to make a copy of current DB. Printing traceback and exiting') - traceback.print_exc() - exit(-1) + # Create a compressed copy of current DB + try: + self.createDatabaseBackup() + except: + logging.error('Not able to make a copy of current DB. Printing traceback and exiting') + traceback.print_exc() + exit(-1) - #Check Tables - for entry in tablesList: - if entry not in tablesDB: - logging.warn('Table '+str(entry)+' does not exist in DB') - self.ddbbObject.createTableDefault(entry,tablesList[entry]) - else: - self.ddbbObject.checkTable(entry,tablesList[entry]) + #Check Tables + for entry in tablesList: + if entry not in tablesDB: + logging.warn('Table '+str(entry)+' does not exist in DB') + self.ddbbObject.createTableDefault(entry,tablesList[entry]) + else: + self.ddbbObject.checkTable(entry,tablesList[entry]) - #Run any functions to update or correct data - #These functions _must_ be safe to run at any time (i.e. not be version specfic or only safe to run once) - self.populate_date_time_local() - logging.debug('<<') + #Run any functions to update or correct data + #These functions _must_ be safe to run at any time (i.e. not be version specfic or only safe to run once) + self.populate_date_time_local() + logging.debug('<<') - def createDatabaseBackup(self): - logging.debug('>>') - logging.debug('Database path: '+str(self.ddbb_path)) - result = commands.getstatusoutput('gzip -c '+self.ddbb_path+' > '+self.ddbb_path+'_`date +%Y%m%d_%H%M`.gz') - if result[0] != 0: - raise Exception, "Copying current database does not work, error #"+str(result[0]) - else: - logging.info('Database backup successfully created') - logging.debug('<<') + def createDatabaseBackup(self): + logging.debug('>>') + logging.debug('Database path: '+str(self.ddbb_path)) + result = commands.getstatusoutput('gzip -c '+self.ddbb_path+' > '+self.ddbb_path+'_`date +%Y%m%d_%H%M`.gz') + if result[0] != 0: + raise Exception, "Copying current database does not work, error #"+str(result[0]) + else: + logging.info('Database backup successfully created') + logging.debug('<<') - def populate_date_time_local(self): - ''' Populate date_time_local and date from date_time_utc - only access records that date_time_local is NULL - using OS timezone to create local_time + def populate_date_time_local(self): + ''' Populate date_time_local and date from date_time_utc + only access records that date_time_local is NULL + using OS timezone to create local_time - also updates date if date != local_time + also updates date if date != local_time - TODO - leaves date_time_local blank for records that have been manually created (as date_time_utc will actually be local time) - ''' - logging.debug('--') - listOfRecords = self.ddbbObject.select("records","id_record,date,date_time_utc,date_time_local", "date_time_local is NULL") - logging.debug("Found %d records in DB without date_time_local field populated" % (len(listOfRecords) ) ) - for record in listOfRecords: - try: - gpxfile = configuration.gpxdir+"/%s.gpx"%(record[0]) - dateFromUTC = Date().getDateTime(record[2]) - if os.path.isfile(gpxfile) : #GPX file exists for this record - probably not a manual record - date_time_local = str(dateFromUTC[1]) - dateFromLocal = dateFromUTC[1].strftime("%Y-%m-%d") - if record[1] != dateFromLocal: - #date field incorrect - update it - logging.debug("Updating record id: %s with date: %s and date_time_local: %s" % (record[0], dateFromLocal, date_time_local) ) - self.ddbbObject.update("records","date, date_time_local",[dateFromLocal, date_time_local], "id_record = %d" %record[0]) - else: - #date field OK, just update date_time_local - logging.debug("Updating record id: %s with date_time_local: %s" % (record[0], date_time_local) ) - self.ddbbObject.update("records","date_time_local",[date_time_local], "id_record = %d" %record[0]) - else: #Manual entry? - #For manual entries, the UTC time is the local time - #TODO figure out a way to correct this... - pass - except: - print "Error updating record: " + str(record) - logging.debug("Error updating record: " + str(record)) + TODO - leaves date_time_local blank for records that have been manually created (as date_time_utc will actually be local time) + ''' + logging.debug('--') + listOfRecords = self.ddbbObject.select("records","id_record,date,date_time_utc,date_time_local", "date_time_local is NULL") + logging.debug("Found %d records in DB without date_time_local field populated" % (len(listOfRecords) ) ) + for record in listOfRecords: + try: + gpxfile = configuration.gpxdir+"/%s.gpx"%(record[0]) + dateFromUTC = Date().getDateTime(record[2]) + if os.path.isfile(gpxfile) : #GPX file exists for this record - probably not a manual record + date_time_local = str(dateFromUTC[1]) + dateFromLocal = dateFromUTC[1].strftime("%Y-%m-%d") + if record[1] != dateFromLocal: + #date field incorrect - update it + logging.debug("Updating record id: %s with date: %s and date_time_local: %s" % (record[0], dateFromLocal, date_time_local) ) + self.ddbbObject.update("records","date, date_time_local",[dateFromLocal, date_time_local], "id_record = %d" %record[0]) + else: + #date field OK, just update date_time_local + logging.debug("Updating record id: %s with date_time_local: %s" % (record[0], date_time_local) ) + self.ddbbObject.update("records","date_time_local",[date_time_local], "id_record = %d" %record[0]) + else: #Manual entry? + #For manual entries, the UTC time is the local time + #TODO figure out a way to correct this... + pass + except Exception as e: + print "Error updating record: " + str(record) + print e + logging.debug("Error updating record: " + str(record)) + logging.debug(str(e)) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-27 23:07:11 UTC (rev 620) +++ pytrainer/trunk/pytrainer/main.py 2010-09-27 23:13:43 UTC (rev 621) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#620" + self.version ="1.7.2_svn#621" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-27 23:07:18
|
Revision: 620 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=620&view=rev Author: jblance Date: 2010-09-27 23:07:11 +0000 (Mon, 27 Sep 2010) Log Message: ----------- Possible fix and extra debuging for failure to show beats in listview Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-23 10:57:50 UTC (rev 619) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-27 23:07:11 UTC (rev 620) @@ -696,7 +696,6 @@ #date,distance,average,title,sports.name,id_record,time,beats,caloriesi #Laas columnas son: #column_names=[_("id"),_("Title"),_("Date"),_("Distance"),_("Sport"),_("Time"),_("Beats"),_("Average"),("Calories")] - date = Date() store = gtk.ListStore( gobject.TYPE_INT, @@ -711,19 +710,38 @@ object) for i in record_list: hour,min,sec = date.second2time(int(i[6])) - time = "%d:%02d:%02d" %(hour,min,sec) + _time = "%d:%02d:%02d" %(hour,min,sec) + try: + _id = int(i[5]) + except (ValueError, TypeError) as e: + logging.debug("Unable to determine id for record: %s" % str(i)) + logging.debug(str(e)) + continue + _title = str(i[3]) + _date = str(i[0]) + _distance = float(i[1]) + _sport = str(i[4]) + _average = float(i[2]) + _calories = int(i[8]) + try: + _beats = round(float(i[7])) + except (ValueError, TypeError) as e: + logging.debug("Unable to parse beats for %s" % str(i[7]) ) + logging.debug(str(e)) + _beats = 0.0 + iter = store.append() store.set ( iter, - 0, int(i[5]), # id - 1, str(i[3]), # title - 2, str(i[0]), # date - 3, float(i[1]), # distance - 4, str(i[4]), # sport - 5, time, - 6, round(float(i[7])), # beats - 7, float(i[2]), # average - 8, int(i[8]) # calories + 0, _id, + 1, _title, + 2, _date, + 3, _distance, + 4, _sport, + 5, _time, + 6, _beats, + 7, _average, + 8, _calories ) #self.allRecordTreeView.set_headers_clickable(True) self.allRecordTreeView.set_model(store) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-23 10:57:50 UTC (rev 619) +++ pytrainer/trunk/pytrainer/main.py 2010-09-27 23:07:11 UTC (rev 620) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#619" + self.version ="1.7.2_svn#620" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-23 10:57:56
|
Revision: 619 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=619&view=rev Author: jblance Date: 2010-09-23 10:57:50 +0000 (Thu, 23 Sep 2010) Log Message: ----------- Fix elevation improvements from Arnd Modified Paths: -------------- pytrainer/trunk/extensions/fixelevation/fixelevation.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/extensions/fixelevation/fixelevation.py =================================================================== --- pytrainer/trunk/extensions/fixelevation/fixelevation.py 2010-09-23 10:45:08 UTC (rev 618) +++ pytrainer/trunk/extensions/fixelevation/fixelevation.py 2010-09-23 10:57:50 UTC (rev 619) @@ -11,8 +11,18 @@ from osgeo import gdal, gdalnumeric from lxml import etree +""" +A list of servers providing SRTM data in GeoTIFF +""" +srtm_server_list = [ + {'url' : 'http://droppr.org/srtm/v4.1/6_5x5_TIFs/', 'ext' : '.zip', 'active' : True }, \ + {'url' : 'ftp://xftp.jrc.it/pub/srtmV4/tiff/' , 'ext' : '.zip', 'active' : True }, \ + {'url' : 'http://srtm.csi.cgiar.org/SRT-ZIP/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ + {'url' : 'ftp://srtm.csi.cgiar.org/SRTM_V41/SRTM_Data_GeoTiff/' , 'ext' : '.zip' , 'active' : True }, \ + {'url' : 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/', 'ext' : '.ZIP', 'active' : False } + ] +srtm_server = srtm_server_list[0] - # from gpxtools def bilinear_interpolation(tl, tr, bl, br, a, b): """ @@ -180,18 +190,19 @@ #md.set_modal(True) #md.show() + srtm_dir = os.path.expanduser('~/.pytrainer/SRTM_data') + if not os.path.isdir(srtm_dir): + os.mkdir(srtm_dir) + logging.info('Downloading SRTM data file, it may take some time ...') - url = 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/%s.ZIP' % srtm_filename[:-4] + #url = 'http://hypersphere.telascience.org/elevation/cgiar_srtm_v4/tiff/zip/%s.ZIP' % srtm_filename[:-4] + url = '%s%s%s' % (srtm_server['url'], srtm_filename[:-4],srtm_server['ext'] ) print "Attempting to get URL: %s" % url zobj = StringIO() zobj.write(urllib2.urlopen(url).read()) z = zipfile.ZipFile(zobj) - - gpxtools_dir = os.path.expanduser('~/.pytrainer/SRTM_data') - if not os.path.isdir(gpxtools_dir): - os.mkdir(gpxtools_dir) - srtm_path = os.path.join(gpxtools_dir, srtm_filename) + srtm_path = os.path.join(srtm_dir, srtm_filename) out_file = open(srtm_path, 'w') out_file.write(z.read(srtm_filename)) @@ -210,8 +221,9 @@ ilon = ceil(colmin / 6000.0) ilat = ceil(rowmin / 6000.0) - return 'srtm_%02d_%02d.TIF' % (ilon, ilat) - + #return 'srtm_%02d_%02d.TIF' % (ilon, ilat) + return 'srtm_%02d_%02d.tif' % (ilon, ilat) + def get_elevation(self, lat, lon): """ Returns the elevation in metres of point (lat, lon). @@ -241,8 +253,18 @@ logging.debug(">>") gpx_file = "%s/gpx/%s.gpx" % (self.conf_dir, id) if os.path.isfile(gpx_file): + # Backup original raw data as *.orig.gpx + orig_file = open(gpx_file, 'r') + orig_data = orig_file.read() + orig_file.close() + backup_file = open("%s/gpx/%s.orig.gpx" % (self.conf_dir, id), 'w') + backup_file.write(orig_data) + backup_file.close() #GPX file is ok and found, so open it logging.debug("ELE GPX file: %s found, size: %d" % (gpx_file, os.path.getsize(gpx_file))) + + + """ Parse GPX file to ElementTree instance. """ @@ -266,7 +288,7 @@ ele.text = str(self._srtm.get_elevation(lat, lon)) trkpt.append(ele) """ - write out to original *.gpx. Shall original ele-values backuped/stored somewhere ? + write out to original *.gpx. """ self._data.write( gpx_file, encoding=self._data.docinfo.encoding, Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-23 10:45:08 UTC (rev 618) +++ pytrainer/trunk/pytrainer/main.py 2010-09-23 10:57:50 UTC (rev 619) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#618" + self.version ="1.7.2_svn#619" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |