From: <jb...@us...> - 2010-09-20 00:41:15
|
Revision: 612 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=612&view=rev Author: jblance Date: 2010-09-20 00:41:08 +0000 (Mon, 20 Sep 2010) Log Message: ----------- Some corrections to pace display and calculation as suggested by Arnd Modified Paths: -------------- pytrainer/trunk/pytrainer/activitypool.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Modified: pytrainer/trunk/pytrainer/activitypool.py =================================================================== --- pytrainer/trunk/pytrainer/activitypool.py 2010-09-10 03:27:57 UTC (rev 611) +++ pytrainer/trunk/pytrainer/activitypool.py 2010-09-20 00:41:08 UTC (rev 612) @@ -43,7 +43,14 @@ self.pool = {} self.pool_queue = [] logging.debug("<<") - + + def remove_activity(self, id): + sid = str(id) + if sid in self.pool.keys(): + logging.debug("Found activity in pool") + self.pool_queue.remove(sid) + del self.pool[sid] + def get_activity(self, id): sid = str(id) if sid in self.pool.keys(): Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-10 03:27:57 UTC (rev 611) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-20 00:41:08 UTC (rev 612) @@ -28,6 +28,7 @@ from popupmenu import PopupMenu from aboutdialog import About +from pytrainer.record import Record from pytrainer.lib.date import Date from pytrainer.lib.xmlUtils import XMLParser #from pytrainer.lib.gpx import Gpx @@ -244,8 +245,8 @@ self.record_unegative.set_text("%0.2f" %activity.unegative) self.record_average.set_text("%0.2f" %activity.average) self.record_maxspeed.set_text("%0.2f" %activity.maxspeed) - self.record_pace.set_text("%0.2f" %activity.pace) - self.record_maxpace.set_text("%0.2f" %activity.maxpace) + self.record_pace.set_text(Record().pace_from_float(activity.pace)) + self.record_maxpace.set_text(Record().pace_from_float(activity.maxpace)) self.record_sport.set_text(activity.sport_name) #self.record_date.set_text(str(date)) @@ -344,8 +345,8 @@ maxbeats = 0 maxspeed = 0 average = 0 - maxpace = "0.00" - pace = "0.00" + maxpace = "0:00" + pace = "0:00" for record in record_list: distance += self.parseFloat(record[2]) calories += self.parseFloat(record[7]) @@ -367,9 +368,9 @@ if distance > 0: average = distance/(timeinseconds/60/60) if maxspeed > 0: - maxpace = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) if average > 0: - pace = "%d.%02d" %((3600/average)/60,(3600/average)%60) + pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) self.dayview.set_sensitive(1) self.day_distance.set_text("%0.2f" %distance) @@ -381,15 +382,15 @@ self.day_maxbeats.set_text("%0.2f" %maxbeats) self.day_average.set_text("%0.2f" %average) self.day_maxspeed.set_text("%0.2f" %maxspeed) - self.day_pace.set_text(pace) - self.day_maxpace.set_text(maxpace) + self.day_pace.set_text("%s" %pace) + self.day_maxpace.set_text("%s" %maxpace) self.day_calories.set_text("%0.0f" %calories) self.day_topic.set_text(str(record[1])) else: self.dayview.set_sensitive(0) logging.debug("<<") - + def actualize_daygraph(self,record_list): logging.debug(">>") if len(record_list)>0: @@ -435,8 +436,8 @@ time_in_min = 0 tbeats = 0 maxspeed = 0 - pace = "0.00" - maxpace = "0.00" + pace = "0:00" + maxpace = "0:00" maxbeats = 0 if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": @@ -482,10 +483,10 @@ if maxspeed > 0: #maxpace = 60/maxspeed - maxpace = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) if average > 0: #pace = 60/average - pace = "%d.%02d" %((3600/average)/60,(3600/average)%60) + pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) self.weeka_distance.set_text("%0.2f" %km) hour,min,sec = self.parent.date.second2time(time) @@ -513,8 +514,8 @@ time_in_min = 0 tbeats = 0 maxspeed = 0 - pace = "0.00" - maxpace = "0.00" + pace = "0:00" + maxpace = "0:00" maxbeats = 0 if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": @@ -560,10 +561,10 @@ if maxspeed > 0: #maxpace = 60/maxspeed - maxpace = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + maxpace = "%d:%02d" %((3600/maxspeed)/60,float(3600/maxspeed)%60) if average > 0: #pace = 60/average - pace = "%d.%02d" %((3600/average)/60,(3600/average)%60) + pace = "%d:%02d" %((3600/average)/60,float(3600/average)%60) self.montha_distance.set_text("%0.2f" %km) hour,min,sec = self.parent.date.second2time(time) @@ -595,8 +596,8 @@ time_in_min = 0 tbeats = 0 maxspeed = 0 - pace = "0.00" - maxpace = "0.00" + pace = "0:00" + maxpace = "0:00" maxbeats = 0 if num_records>0: for record in record_list: @@ -623,10 +624,10 @@ if maxspeed > 0: #maxpace = 60/maxspeed - maxpace = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) if average > 0: #pace = 60/average - pace = "%d.%02d" %((3600/average)/60,(3600/average)%60) + pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) self.yeara_distance.set_text("%0.2f" %km) hour,min,sec = self.parent.date.second2time(time) Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-09-10 03:27:57 UTC (rev 611) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-09-20 00:41:08 UTC (rev 612) @@ -21,6 +21,7 @@ import gtk, gobject from SimpleGladeApp import SimpleGladeApp from windowcalendar import WindowCalendar + from filechooser import FileChooser from pytrainer.lib.date import Date import dateutil.parser @@ -504,8 +505,16 @@ distance = float(self.rcd_distance.get_text()) if distance<1: return False + #Calc Pace average = time_in_min/distance - self.rcd_pace.set_text("%0.2f" %average) + #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() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-10 03:27:57 UTC (rev 611) +++ pytrainer/trunk/pytrainer/main.py 2010-09-20 00:41:08 UTC (rev 612) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#611" + self.version ="1.7.2_svn#612" self.DB_version = 3 #Process command line options self.startup_options = self.get_options() Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-09-10 03:27:57 UTC (rev 611) +++ pytrainer/trunk/pytrainer/record.py 2010-09-20 00:41:08 UTC (rev 612) @@ -107,11 +107,29 @@ self.parseFloatRecord(list_options["rcd_unegative"]), self.parseFloatRecord(list_options["rcd_maxvel"]), self.parseFloatRecord(list_options["rcd_maxpace"]), - self.parseFloatRecord(list_options["rcd_pace"]), - self.parseFloatRecord(list_options["rcd_maxbeats"]) + self.pace_to_float(list_options["rcd_pace"]), + self.pace_to_float(list_options["rcd_maxbeats"]) ) logging.debug('<<') return cells,values + + def pace_to_float(self, value): + '''Take a mm:ss or mm.ss and return float''' + value = value.replace(':', '.') + try: + value = float(value) + except ValueError: + value = None + return value + + def pace_from_float(self, value): + '''Helper to generate mm:ss from float representation mm.ss (or mm,ss?)''' + #Check that value supplied is a float + try: + _value = "%0.2f" % float(value) + except ValueError: + _value = str(value) + return _value.replace('.',':') def _formatRecordNew (self, list_options): """20.07.2008 - dgranda @@ -141,8 +159,8 @@ 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.parseFloatRecord(list_options["rcd_pace"]), + self.pace_to_float(list_options["rcd_maxpace"]), + self.pace_to_float(list_options["rcd_pace"]), self.parseFloatRecord(list_options["rcd_maxbeats"]), list_options["date_time_utc"], list_options["date_time_local"], @@ -263,6 +281,8 @@ def updateRecord(self, list_options, id_record): logging.debug('>>') + #Remove activity from pool so data is updated + self.pytrainer_main.activitypool.remove_activity(id_record) gpxfile = self.pytrainer_main.profile.gpxdir+"/%d.gpx"%int(id_record) gpxOrig = list_options["rcd_gpxfile"] if os.path.isfile(gpxOrig): @@ -274,7 +294,7 @@ logging.debug('updating bbdd') #ein? cells,values = self._formatRecord(list_options) self.pytrainer_main.ddbb.update("records",cells,values," id_record=%d" %int(id_record)) - self.parent.refreshListView() + self.pytrainer_main.refreshListView() logging.debug('<<') def parseFloatRecord(self,string): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-09-21 10:22:10
|
Revision: 615 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=615&view=rev Author: jblance Date: 2010-09-21 10:22:04 +0000 (Tue, 21 Sep 2010) Log Message: ----------- Small correction to ensure no graph is shown for activities with no gpx data Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-21 05:00:23 UTC (rev 614) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-21 10:22:04 UTC (rev 615) @@ -271,19 +271,21 @@ logging.debug(">>") self.record_list = activity.tracks self.laps = activity.laps - if self.record_list is not None and len(self.record_list)>0: + if activity.gpx_file is not None: + logging.debug("Activity has GPX data") self.record_vbox.set_sensitive(1) self.drawarearecord.drawgraph(self.record_list,self.laps) else: + logging.debug("Activity has no GPX data") #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("<<") @@ -390,7 +392,7 @@ else: self.dayview.set_sensitive(0) logging.debug("<<") - + def actualize_daygraph(self,record_list): logging.debug(">>") if len(record_list)>0: @@ -678,7 +680,7 @@ iter = history_store.append() history_store.set ( iter, - 0, data_index, + 0, data_index, 1, date, #TODO need to sort date graphing... 2, "%0.2f" % weight, 3, "%0.2f" % float(data['BF']), @@ -888,7 +890,7 @@ logging.debug("Reseting graph Y axis with ylimits: %s" % str(y1limits) ) self.drawarearecord.drawgraph(self.record_list,self.laps, y1limits=y1limits, y1color=y1color, y1_linewidth=y1_linewidth) logging.debug("<<") - + def update_athlete_item(self, idx, date, weight, bf, restingHR, maxHR): logging.debug(">>") #Prepare vars @@ -910,7 +912,7 @@ ###################### ## Lista de eventos ## ###################### - + def on_athleteTreeView_button_press_event(self, treeview, event): x = int(event.x) y = int(event.y) Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-09-21 05:00:23 UTC (rev 614) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-09-21 10:22:04 UTC (rev 615) @@ -63,7 +63,7 @@ maxspeed - (float) maximum speed obtained during activity maxpace - (float) maxium pace obtained during activity pace - (float) average pace for activity - has_data - (bool) true if gpx processed and instance has data populated + has_data - (bool) true if instance has data populated ''' def __init__(self, pytrainer_main = None, id = None): logging.debug(">>") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-21 05:00:23 UTC (rev 614) +++ pytrainer/trunk/pytrainer/main.py 2010-09-21 10:22:04 UTC (rev 615) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#614" + self.version ="1.7.2_svn#615" 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-22 10:23:06
|
Revision: 617 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=617&view=rev Author: jblance Date: 2010-09-22 10:23:00 +0000 (Wed, 22 Sep 2010) Log Message: ----------- Minor changes to test graphing (disabled) 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-21 11:35:28 UTC (rev 616) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-22 10:23:00 UTC (rev 617) @@ -272,11 +272,16 @@ self.record_list = activity.tracks self.laps = activity.laps if activity.gpx_file is not None: - logging.debug("Activity has GPX data") - self.record_vbox.set_sensitive(1) - self.drawarearecord.drawgraph(self.record_list,self.laps) - #Create a frame showing data available for graphing - if False: #Still just test code + if True: + logging.debug("Activity has GPX data") + self.record_vbox.set_sensitive(1) + self.drawarearecord.drawgraph(self.record_list,self.laps) + + else: #Still just test code + #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") @@ -295,12 +300,12 @@ xFrame.add(xvbox) #Populate Y axis data for graphdata in activity.distance_data: - y1checkbutton = gtk.CheckButton(label=activity.distance_data[graphdata].title) - y1checkbutton.connect("toggled", self.on_y1change, y1vbox) - y2checkbutton = gtk.CheckButton(label=activity.distance_data[graphdata].title) - y2checkbutton.connect("toggled", self.on_y2change, y2vbox) - y1vbox.add(y1checkbutton) - y2vbox.add(y2checkbutton) + 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) @@ -950,13 +955,15 @@ if widget.get_active(): print data - def on_y1change(self, widget, box): + def on_y1change(self, widget, box, data): '''Hander for changes to y1 selection''' - print "Y1 selected: ", + print "Y1 selected: " for child in box.get_children(): if child.get_active(): - print child.get_label(), - print + #This check box is active, so display graph... + #drawgraph to self.record_graph_vbox with data.... + print child.get_label(), data + #print def on_y2change(self, widget, box): '''Hander for changes to y2 selection''' Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-09-21 11:35:28 UTC (rev 616) +++ pytrainer/trunk/pytrainer/main.py 2010-09-22 10:23:00 UTC (rev 617) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#616" + self.version ="1.7.2_svn#617" 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:45:16
|
Revision: 618 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=618&view=rev Author: jblance Date: 2010-09-23 10:45:08 +0000 (Thu, 23 Sep 2010) Log Message: ----------- listview improvements from Arnd 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-22 10:23:00 UTC (rev 617) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-09-23 10:45:08 UTC (rev 618) @@ -48,1305 +48,1243 @@ from pytrainer.gui.drawGraph import DrawGraph class Main(SimpleGladeApp): - def __init__(self, data_path = None, parent = None, version = None, gpxDir = None): - def url_hook(dialog, url): - pytrainer.lib.webUtils.open_url_in_browser(url) - # Available in PyGTK 2.6 and above - gtk.about_dialog_set_url_hook(url_hook) - self.version = version - self.parent = parent - self.pytrainer_main = parent - self.data_path = data_path - glade_path="glade/pytrainer.glade" - root = "window1" - domain = None - SimpleGladeApp.__init__(self, self.data_path+glade_path, root, domain) + def __init__(self, data_path = None, parent = None, version = None, gpxDir = None): + def url_hook(dialog, url): + pytrainer.lib.webUtils.open_url_in_browser(url) + # Available in PyGTK 2.6 and above + gtk.about_dialog_set_url_hook(url_hook) + self.version = version + self.parent = parent + self.pytrainer_main = parent + self.data_path = data_path + glade_path="glade/pytrainer.glade" + root = "window1" + domain = None + SimpleGladeApp.__init__(self, self.data_path+glade_path, root, domain) - self.popup = PopupMenu(data_path,self) - self.block = False - self.activeSport = None - self.gpxDir = gpxDir - self.record_list = None - self.laps = None - self.y1_limits = None - self.y1_color = None - self.y1_linewidth = 1 + self.popup = PopupMenu(data_path,self) + self.block = False + self.activeSport = None + self.gpxDir = gpxDir + self.record_list = None + self.laps = None + self.y1_limits = None + self.y1_color = None + self.y1_linewidth = 1 - def new(self): - self.testimport = self.pytrainer_main.startup_options.testimport - self.menublocking = 0 - self.selected_view="day" - self.window1.set_title ("pyTrainer %s" % self.version) - try: - width, height = self.pytrainer_main.profile.getValue("pytraining","window_size").split(',') - self.window1.resize(int(width), int(height)) - except: - pass - self.record_list = [] - #create the columns for the listdayrecord - column_names=[_("id"),_("Start"), _("Sport"),_("Kilometer")] - self.create_treeview(self.recordTreeView,column_names) - #create the columns for the listarea - column_names=[_("id"),_("Title"),_("Date"),_("Distance"),_("Sport"),_("Time"),_("Beats"),_("Average"),("Calories")] - self.create_treeview(self.allRecordTreeView,column_names) - self.create_menulist(column_names) - #create the columns for the waypoints treeview - column_names=[_("id"),_("Waypoint")] - self.create_treeview(self.waypointTreeView,column_names) - #create the columns for the history treeview - column_names=[_("id"),_("Date"),_("Weight"),_("Body Fat %"),_("Resting HR"),_("Max HR")] - self.create_treeview(self.athleteTreeView,column_names) - self.fileconf = self.pytrainer_main.profile.confdir+"/listviewmenu.xml" - if not os.path.isfile(self.fileconf): - self._createXmlListView(self.fileconf) - self.showAllRecordTreeViewColumns() - self.allRecordTreeView.set_search_column(1) - self.notebook.set_current_page(1) + def new(self): + self.testimport = self.pytrainer_main.startup_options.testimport + self.menublocking = 0 + self.selected_view="day" + self.window1.set_title ("pyTrainer %s" % self.version) + try: + width, height = self.pytrainer_main.profile.getValue("pytraining","window_size").split(',') + self.window1.resize(int(width), int(height)) + except: + pass + self.record_list = [] + #create the columns for the listdayrecord + column_names=[_("id"),_("Start"), _("Sport"),_("Kilometer")] + self.create_treeview(self.recordTreeView,column_names) + #create the columns for the listarea + column_names=[_("id"),_("Title"),_("Date"),_("Distance"),_("Sport"),_("Time"),_("Beats"),_("Average"),("Calories")] + self.create_treeview(self.allRecordTreeView,column_names) + self.create_menulist(column_names) + #create the columns for the waypoints treeview + column_names=[_("id"),_("Waypoint")] + self.create_treeview(self.waypointTreeView,column_names) + #create the columns for the history treeview + column_names=[_("id"),_("Date"),_("Weight"),_("Body Fat %"),_("Resting HR"),_("Max HR")] + self.create_treeview(self.athleteTreeView,column_names) + self.fileconf = self.pytrainer_main.profile.confdir+"/listviewmenu.xml" + if not os.path.isfile(self.fileconf): + self._createXmlListView(self.fileconf) + self.showAllRecordTreeViewColumns() + self.allRecordTreeView.set_search_column(1) + self.notebook.set_current_page(1) - #Disable import menu item unless specified on startup - self.set_unified_import(self.testimport) + #Disable import menu item unless specified on startup + self.set_unified_import(self.testimport) - #Set correct map viewer - if self.pytrainer_main.profile.getValue("pytraining","default_viewer") == "1": - self.radiobuttonOSM.set_active(1) - else: - self.radiobuttonGMap.set_active(1) + #Set correct map viewer + if self.pytrainer_main.profile.getValue("pytraining","default_viewer") == "1": + self.radiobuttonOSM.set_active(1) + else: + self.radiobuttonGMap.set_active(1) - def setup(self): - self.createGraphs(RecordGraph,DayGraph,WeekGraph, MonthGraph,YearGraph,HeartRateGraph) - self.createMap(MapViewer,self.pytrainer_main.waypoint) - self.createWaypointEditor(WaypointEditor,self.pytrainer_main.waypoint, parent=self.pytrainer_main) - page = self.notebook.get_current_page() - self.on_page_change(None,None,page) + def setup(self): + self.createGraphs(RecordGraph,DayGraph,WeekGraph, MonthGraph,YearGraph,HeartRateGraph) + self.createMap(MapViewer,self.pytrainer_main.waypoint) + self.createWaypointEditor(WaypointEditor,self.pytrainer_main.waypoint, parent=self.pytrainer_main) + page = self.notebook.get_current_page() + self.on_page_change(None,None,page) - def set_unified_import(self, status=False): - self.menu_importdata.set_sensitive(status) - self.parent.testimport = status + def set_unified_import(self, status=False): + self.menu_importdata.set_sensitive(status) + self.parent.testimport = status - def _createXmlListView(self,file): - menufile = XMLParser(file) - savedOptions = [] - savedOptions.append(("date","True")) - savedOptions.append(("distance","True")) - savedOptions.append(("average","False")) - savedOptions.append(("title","True")) - savedOptions.append(("sport","True")) - savedOptions.append(("id_record","False")) - savedOptions.append(("time","False")) - savedOptions.append(("beats","False")) - savedOptions.append(("calories","False")) - menufile.createXMLFile("listviewmenu",savedOptions) + def _createXmlListView(self,file): + menufile = XMLParser(file) + savedOptions = [] + savedOptions.append(("date","True")) + savedOptions.append(("distance","True")) + savedOptions.append(("average","False")) + savedOptions.append(("title","True")) + savedOptions.append(("sport","True")) + savedOptions.append(("id_record","False")) + savedOptions.append(("time","False")) + savedOptions.append(("beats","False")) + savedOptions.append(("calories","False")) + menufile.createXMLFile("listviewmenu",savedOptions) - def removeImportPlugin(self, plugin): - for widget in self.menuitem1_menu: - if widget.get_name() == plugin[1]: - self.menuitem1_menu.remove(widget) + def removeImportPlugin(self, plugin): + for widget in self.menuitem1_menu: + if widget.get_name() == plugin[1]: + self.menuitem1_menu.remove(widget) - def removeExtension(self, extension): - for widget in self.recordbuttons_hbox: - if widget.get_name() == extension[1]: - logging.debug("Removing extension: %s " % extension[0]) - self.recordbuttons_hbox.remove(widget) + def removeExtension(self, extension): + for widget in self.recordbuttons_hbox: + if widget.get_name() == extension[1]: + logging.debug("Removing extension: %s " % extension[0]) + self.recordbuttons_hbox.remove(widget) - def addImportPlugin(self,plugin): - button = gtk.MenuItem(plugin[0]) - button.set_name(plugin[1]) - button.connect("activate", self.parent.runPlugin, plugin[1]) - self.menuitem1_menu.insert(button,3) - self.menuitem1_menu.show_all() + def addImportPlugin(self,plugin): + button = gtk.MenuItem(plugin[0]) + button.set_name(plugin[1]) + button.connect("activate", self.parent.runPlugin, plugin[1]) + self.menuitem1_menu.insert(button,3) + self.menuitem1_menu.show_all() - def addExtension(self,extension): - #txtbutton,extensioncode,extensiontype = extension - button = gtk.Button(extension[0]) - button.set_name(extension[1]) - button.connect("button_press_event", self.runExtension, extension) - self.recordbuttons_hbox.pack_start(button,False,False,0) - self.recordbuttons_hbox.show_all() + def addExtension(self,extension): + #txtbutton,extensioncode,extensiontype = extension + button = gtk.Button(extension[0]) + button.set_name(extension[1]) + button.connect("button_press_event", self.runExtension, extension) + self.recordbuttons_hbox.pack_start(button,False,False,0) + self.recordbuttons_hbox.show_all() - def runExtension(self,widget,widget2,extension): - #print extension - txtbutton,extensioncode,extensiontype = extension - id = None - if extensiontype=="record": - selected,iter = self.recordTreeView.get_selection().get_selected() - id = selected.get_value(iter,0) - self.parent.runExtension(extension,id) + def runExtension(self,widget,widget2,extension): + #print extension + txtbutton,extensioncode,extensiontype = extension + id = None + if extensiontype=="record": + selected,iter = self.recordTreeView.get_selection().get_selected() + id = selected.get_value(iter,0) + self.parent.runExtension(extension,id) - def createGraphs(self,RecordGraph,DayGraph,WeekGraph, MonthGraph,YearGraph,HeartRateGraph): - self.drawarearecord = RecordGraph(self.record_graph_vbox, self.window1, self.record_combovalue, self.record_combovalue2, self.btnShowLaps, self.tableConfigY1) - self.drawareaheartrate = HeartRateGraph(self.heartrate_vbox, self.window1, self.heartrate_vbox2, pytrainer_main=self.pytrainer_main) - #self.drawareaday = DayGraph(self.day_vbox, self.day_combovalue) - self.day_vbox.hide() - self.drawareaweek = WeekGraph(self.weekview, self.window1, self.week_combovalue, self.week_combovalue2) - self.drawareamonth = MonthGraph(self.month_vbox, self.window1, self.month_combovalue,self.month_combovalue2) - self.drawareayear = YearGraph(self.year_vbox, self.window1, self.year_combovalue,self.year_combovalue2) + def createGraphs(self,RecordGraph,DayGraph,WeekGraph, MonthGraph,YearGraph,HeartRateGraph): + self.drawarearecord = RecordGraph(self.record_graph_vbox, self.window1, self.record_combovalue, self.record_combovalue2, self.btnShowLaps, self.tableConfigY1) + self.drawareaheartrate = HeartRateGraph(self.heartrate_vbox, self.window1, self.heartrate_vbox2, pytrainer_main=self.pytrainer_main) + #self.drawareaday = DayGraph(self.day_vbox, self.day_combovalue) + self.day_vbox.hide() + self.drawareaweek = WeekGraph(self.weekview, self.window1, self.week_combovalue, self.week_combovalue2) + self.drawareamonth = MonthGraph(self.month_vbox, self.window1, self.month_combovalue,self.month_combovalue2) + self.drawareayear = YearGraph(self.year_vbox, self.window1, self.year_combovalue,self.year_combovalue2) - def createMap(self,MapViewer,waypoint): - self.waypoint = waypoint - self.mapviewer = MapViewer(self.data_path, pytrainer_main=self.parent, box=self.map_vbox) - self.mapviewer_fs = MapViewer(self.data_path, pytrainer_main=self.parent, box=self.map_vbox_old) - #self.googlemaps = Googlemaps(self.data_path, self.map_vbox,waypoint, pytrainer_main=self.parent) - #self.osm = Osm(self.data_path, self.map_vbox,waypoint, pytrainer_main=self.parent) - #self.googlemaps_old = Googlemaps(self.data_path, self.map_vbox_old,waypoint, pytrainer_main=self.parent) + def createMap(self,MapViewer,waypoint): + self.waypoint = waypoint + self.mapviewer = MapViewer(self.data_path, pytrainer_main=self.parent, box=self.map_vbox) + self.mapviewer_fs = MapViewer(self.data_path, pytrainer_main=self.parent, box=self.map_vbox_old) + #self.googlemaps = Googlemaps(self.data_path, self.map_vbox,waypoint, pytrainer_main=self.parent) + #self.osm = Osm(self.data_path, self.map_vbox,waypoint, pytrainer_main=self.parent) + #self.googlemaps_old = Googlemaps(self.data_path, self.map_vbox_old,waypoint, pytrainer_main=self.parent) - def updateSportList(self,listSport): - logging.debug(">>") - liststore = self.sportlist.get_model() - if self.sportlist.get_active() is not 0: - self.sportlist.set_active(0) #Set first item active if it isnt - firstEntry = self.sportlist.get_active_text() - liststore.clear() #Delete all items - #Re-add "All Sports" - liststore.append([firstEntry]) - #Re-add all sports in listSport - for i in listSport: - liststore.append([i[0]]) - self.sportlist.set_active(0) - logging.debug("<<") + def updateSportList(self,listSport): + logging.debug(">>") + liststore = self.sportlist.get_model() + if self.sportlist.get_active() is not 0: + self.sportlist.set_active(0) #Set first item active if it isnt + firstEntry = self.sportlist.get_active_text() + liststore.clear() #Delete all items + #Re-add "All Sports" + liststore.append([firstEntry]) + #Re-add all sports in listSport + for i in listSport: + liststore.append([i[0]]) + self.sportlist.set_active(0) + logging.debug("<<") - def create_treeview(self,treeview,column_names): - i=0 - for column_index, column_name in enumerate(column_names): - column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) - column.set_resizable(True) - if i==0: - column.set_visible(False) - column.set_sort_column_id(i) - treeview.append_column(column) - i+=1 + def create_treeview(self,treeview,column_names): + i=0 + for column_index, column_name in enumerate(column_names): + column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) + column.set_resizable(True) + if i==0: + column.set_visible(False) + column.set_sort_column_id(i) + treeview.append_column(column) + i+=1 - def actualize_recordview(self,activity): - logging.debug(">>") - if activity.id is None: - self.recordview.set_current_page(0) - self.recordview.set_sensitive(0) - logging.debug("<<") - return - #Set the units for the activity results, e.g. km, km/h etc - self.r_distance_unit.set_text(activity.distance_unit) - self.r_speed_unit.set_text(activity.speed_unit) - self.r_maxspeed_unit.set_text(activity.speed_unit) - self.r_pace_unit.set_text(activity.pace_unit) - self.r_maxpace_unit.set_text(activity.pace_unit) - self.r_ascent_unit.set_text(activity.height_unit) - self.r_descent_unit.set_text(activity.height_unit) + def actualize_recordview(self,activity): + logging.debug(">>") + if activity.id is None: + self.recordview.set_current_page(0) + self.recordview.set_sensitive(0) + logging.debug("<<") + return + #Set the units for the activity results, e.g. km, km/h etc + self.r_distance_unit.set_text(activity.distance_unit) + self.r_speed_unit.set_text(activity.speed_unit) + self.r_maxspeed_unit.set_text(activity.speed_unit) + self.r_pace_unit.set_text(activity.pace_unit) + self.r_maxpace_unit.set_text(activity.pace_unit) + self.r_ascent_unit.set_text(activity.height_unit) + self.r_descent_unit.set_text(activity.height_unit) - if activity.has_data: - self.recordview.set_sensitive(1) + if activity.has_data: + self.recordview.set_sensitive(1) - dateTime = activity.date_time - recordDateTime = dateTime.strftime("%Y-%m-%d %H:%M:%S") - recordDate = dateTime.strftime("%x") - recordTime = dateTime.strftime("%X") - recordDateTimeOffset = dateTime.strftime("%z") + dateTime = activity.date_time + recordDateTime = dateTime.strftime("%Y-%m-%d %H:%M:%S") + recordDate = dateTime.strftime("%x") + recordTime = dateTime.strftime("%X") + recordDateTimeOffset = dateTime.strftime("%z") - self.record_distance.set_text("%0.2f" %activity.distance) - self.record_upositive.set_text("%0.2f" %activity.upositive) - self.record_unegative.set_text("%0.2f" %activity.unegative) - self.record_average.set_text("%0.2f" %activity.average) - self.record_maxspeed.set_text("%0.2f" %activity.maxspeed) - self.record_pace.set_text(Record().pace_from_float(activity.pace)) - self.record_maxpace.set_text(Record().pace_from_float(activity.maxpace)) + self.record_distance.set_text("%0.2f" %activity.distance) + self.record_upositive.set_text("%0.2f" %activity.upositive) + self.record_unegative.set_text("%0.2f" %activity.unegative) + self.record_average.set_text("%0.2f" %activity.average) + self.record_maxspeed.set_text("%0.2f" %activity.maxspeed) + self.record_pace.set_text(Record().pace_from_float(activity.pace)) + self.record_maxpace.set_text(Record().pace_from_float(activity.maxpace)) - self.record_sport.set_text(activity.sport_name) - #self.record_date.set_text(str(date)) - self.record_date.set_text(recordDate) - self.record_time.set_text(recordTime) - hour,min,sec=self.parent.date.second2time(int(activity.time)) - self.record_hour.set_text("%d" %hour) - self.record_minute.set_text("%02d" %min) - self.record_second.set_text("%02d" %sec) - self.record_calories.set_text("%0.0f" %activity.calories) - self.record_title.set_text(activity.title) - buffer = self.record_comments.get_buffer() - start,end = buffer.get_bounds() - buffer.set_text(activity.comments) + self.record_sport.set_text(activity.sport_name) + #self.record_date.set_text(str(date)) + self.record_date.set_text(recordDate) + self.record_time.set_text(recordTime) + hour,min,sec=self.parent.date.second2time(int(activity.time)) + self.record_hour.set_text("%d" %hour) + self.record_minute.set_text("%02d" %min) + self.record_second.set_text("%02d" %sec) + self.record_calories.set_text("%0.0f" %activity.calories) + self.record_title.set_text(activity.title) + buffer = self.record_comments.get_buffer() + start,end = buffer.get_bounds() + buffer.set_text(activity.comments) - else: - self.recordview.set_current_page(0) - self.recordview.set_sensitive(0) - logging.debug("<<") + else: + self.recordview.set_current_page(0) + self.recordview.set_sensitive(0) + logging.debug("<<") - def actualize_recordgraph(self,activity): - logging.debug(">>") - self.record_list = activity.tracks - self.laps = activity.laps - if activity.gpx_file is not None: - if True: - logging.debug("Activity has GPX data") - self.record_vbox.set_sensitive(1) - self.drawarearecord.drawgraph(self.record_list,self.laps) + def actualize_recordgraph(self,activity): + 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) + else: + #Remove graph + vboxChildren = self.record_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_vbox.set_sensitive(0) + logging.debug("<<") - else: #Still just test code - #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() - else: - logging.debug("Activity has no GPX data") - #Remove graph - 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_graph_vbox.remove(child) - self.record_vbox.set_sensitive(0) - logging.debug("<<") + def actualize_heartrategraph(self,activity): + logging.debug(">>") + if activity.tracks is not None and len(activity.tracks)>0: + self.heartrate_vbox_.set_sensitive(1) + self.drawareaheartrate.drawgraph(activity.tracks) + else: + self.heartrate_vbox_.set_sensitive(0) + logging.debug("<<") - def actualize_heartrategraph(self,activity): - logging.debug(">>") - if activity.tracks is not None and len(activity.tracks)>0: - self.heartrate_vbox_.set_sensitive(1) - self.drawareaheartrate.drawgraph(activity.tracks) - else: - self.heartrate_vbox_.set_sensitive(0) - logging.debug("<<") + def actualize_hrview(self,activity): + logging.debug(">>") + zones = self.pytrainer_main.profile.getZones() + record_list = activity.tracks + is_karvonen_method = self.pytrainer_main.profile.getValue("pytraining","prf_hrzones_karvonen") + if record_list is not None and len(record_list)>0: + record_list=record_list[0] + self.record_zone1.set_text("%s-%s" %(zones[4][0],zones[4][1])) + self.record_zone2.set_text("%s-%s" %(zones[3][0],zones[3][1])) + self.record_zone3.set_text("%s-%s" %(zones[2][0],zones[2][1])) + self.record_zone4.set_text("%s-%s" %(zones[1][0],zones[1][1])) + self.record_zone5.set_text("%s-%s" %(zones[0][0],zones[0][1])) + beats = activity.beats + maxbeats = activity.maxbeats + self.record_beats.set_text("%0.2f" %beats) + self.record_maxbeats.set_text("%0.2f" %maxbeats) + self.record_calories2.set_text("%0.0f" %activity.calories) + if is_karvonen_method=="True": + self.record_zonesmethod.set_text(_("Karvonen method")) + else: + self.record_zonesmethod.set_text(_("Percentages method")) + #else: + # self.recordview.set_sensitive(0) + logging.debug("<<") - def actualize_hrview(self,activity): - logging.debug(">>") - zones = self.pytrainer_main.profile.getZones() - record_list = activity.tracks - is_karvonen_method = self.pytrainer_main.profile.getValue("pytraining","prf_hrzones_karvonen") - if record_list is not None and len(record_list)>0: - record_list=record_list[0] - self.record_zone1.set_text("%s-%s" %(zones[4][0],zones[4][1])) - self.record_zone2.set_text("%s-%s" %(zones[3][0],zones[3][1])) - self.record_zone3.set_text("%s-%s" %(zones[2][0],zones[2][1])) - self.record_zone4.set_text("%s-%s" %(zones[1][0],zones[1][1])) - self.record_zone5.set_text("%s-%s" %(zones[0][0],zones[0][1])) - beats = activity.beats - maxbeats = activity.maxbeats - self.record_beats.set_text("%0.2f" %beats) - self.record_maxbeats.set_text("%0.2f" %maxbeats) - self.record_calories2.set_text("%0.0f" %activity.calories) - if is_karvonen_method=="True": - self.record_zonesmethod.set_text(_("Karvonen method")) - else: - self.record_zonesmethod.set_text(_("Percentages method")) - #else: - # self.recordview.set_sensitive(0) - logging.debug("<<") + def actualize_dayview(self,record_list): + logging.debug(">>") + if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": + self.d_distance_unit.set_text(_("miles")) + self.d_speed_unit.set_text(_("miles/h")) + self.d_maxspeed_unit.set_text(_("miles/h")) + self.d_pace_unit.set_text(_("min/mile")) + self.d_maxpace_unit.set_text(_("min/mile")) + else: + self.d_distance_unit.set_text(_("km")) + self.d_speed_unit.set_text(_("km/h")) + self.d_maxspeed_unit.set_text(_("km/h")) + self.d_pace_unit.set_text(_("min/km")) + self.d_maxpace_unit.set_text(_("min/km")) - def actualize_dayview(self,record_list): - logging.debug(">>") - if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": - self.d_distance_unit.set_text(_("miles")) - self.d_speed_unit.set_text(_("miles/h")) - self.d_maxspeed_unit.set_text(_("miles/h")) - self.d_pace_unit.set_text(_("min/mile")) - self.d_maxpace_unit.set_text(_("min/mile")) - else: - self.d_distance_unit.set_text(_("km")) - self.d_speed_unit.set_text(_("km/h")) - self.d_maxspeed_unit.set_text(_("km/h")) - self.d_pace_unit.set_text(_("min/km")) - self.d_maxpace_unit.set_text(_("min/km")) + if len(record_list)>0: + tbeats = 0 + distance = 0 + calories = 0 + timeinseconds = 0 + beats = 0 + maxbeats = 0 + maxspeed = 0 + average = 0 + maxpace = "0:00" + pace = "0:00" + for record in record_list: + distance += self.parseFloat(record[2]) + calories += self.parseFloat(record[7]) + timeinseconds += self.parseFloat(record[3]) + beats = self.parseFloat(record[4]) + if float(beats)>0: + tbeats += beats*(self.parseFloat(record[3])/60/60) + if record[9] > maxspeed: + maxspeed = self.parseFloat(record[9]) + if record[10] > maxbeats: + maxbeats = self.parseFloat(record[10]) - if len(record_list)>0: - tbeats = 0 - distance = 0 - calories = 0 - timeinseconds = 0 - beats = 0 - maxbeats = 0 - maxspeed = 0 - average = 0 - maxpace = "0:00" - pace = "0:00" - for record in record_list: - distance += self.parseFloat(record[2]) - calories += self.parseFloat(record[7]) - timeinseconds += self.parseFloat(record[3]) - beats = self.parseFloat(record[4]) - if float(beats)>0: - tbeats += beats*(self.parseFloat(record[3])/60/60) - if record[9] > maxspeed: - maxspeed = self.parseFloat(record[9]) - if record[10] > maxbeats: - maxbeats = self.parseFloat(record[10]) + if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": + distance = km2miles(distance) + maxspeed = km2miles(maxspeed) - if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": - distance = km2miles(distance) - maxspeed = km2miles(maxspeed) + if tbeats > 0: + tbeats = tbeats/(timeinseconds/60/60) + if distance > 0: + average = distance/(timeinseconds/60/60) + if maxspeed > 0: + maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + if average > 0: + pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) - if tbeats > 0: - tbeats = tbeats/(timeinseconds/60/60) - if distance > 0: - average = distance/(timeinseconds/60/60) - if maxspeed > 0: - maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) - if average > 0: - pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) + self.dayview.set_sensitive(1) + self.day_distance.set_text("%0.2f" %distance) + hour,min,sec=self.parent.date.second2time(timeinseconds) + self.day_hour.set_text("%d" %hour) + self.day_minute.set_text("%02d" %min) + self.day_second.set_text("%02d" %sec) + self.day_beats.set_text("%0.2f" %tbeats) + self.day_maxbeats.set_text("%0.2f" %maxbeats) + self.day_average.set_text("%0.2f" %average) + self.day_maxspeed.set_text("%0.2f" %maxspeed) + self.day_pace.set_text("%s" %pace) + self.day_maxpace.set_text("%s" %maxpace) + self.day_calories.set_text("%0.0f" %calories) + self.day_topic.set_text(str(record[1])) - self.dayview.set_sensitive(1) - self.day_distance.set_text("%0.2f" %distance) - hour,min,sec=self.parent.date.second2time(timeinseconds) - self.day_hour.set_text("%d" %hour) - self.day_minute.set_text("%02d" %min) - self.day_second.set_text("%02d" %sec) - self.day_beats.set_text("%0.2f" %tbeats) - self.day_maxbeats.set_text("%0.2f" %maxbeats) - self.day_average.set_text("%0.2f" %average) - self.day_maxspeed.set_text("%0.2f" %maxspeed) - self.day_pace.set_text("%s" %pace) - self.day_maxpace.set_text("%s" %maxpace) - self.day_calories.set_text("%0.0f" %calories) - self.day_topic.set_text(str(record[1])) + else: + self.dayview.set_sensitive(0) + logging.debug("<<") + + def actualize_daygraph(self,record_list): + logging.debug(">>") + if len(record_list)>0: + self.day_vbox.set_sensitive(1) + else: + self.day_vbox.set_sensitive(0) + self.drawareaday.drawgraph(record_list) + logging.debug("<<") - else: - self.dayview.set_sensitive(0) - logging.debug("<<") + def actualize_map(self,activity, full_screen=False): + logging.debug(">>") + #Check which type of map viewer to use + if self.radiobuttonOSM.get_active(): + #Use OSM to draw map + logging.debug("Using OSM to draw map....") + htmlfile = Osm(data_path=self.data_path, waypoint=self.waypoint, pytrainer_main=self.parent).drawMap(activity) + elif self.radiobuttonGMap.get_active(): + #Use Google to draw map + logging.debug("Using Google to draw map") + htmlfile = Googlemaps(data_path=self.data_path, waypoint=self.waypoint, pytrainer_main=self.parent).drawMap(activity) + else: + #Unknown map type... + logging.error("Unknown map viewer requested") + htmlfile = self.mapviewer.createErrorHtml() + logging.debug("Displaying htmlfile: %s" % htmlfile) + if full_screen: + logging.debug("Displaying in full screen mode") + self.mapviewer_fs.display_map(htmlfile=htmlfile) + else: + logging.debug("Displaying in embedded mode") + self.mapviewer.display_map(htmlfile=htmlfile) + logging.debug("<<") - def actualize_daygraph(self,record_list): - logging.debug(">>") - if len(record_list)>0: - self.day_vbox.set_sensitive(1) - else: - self.day_vbox.set_sensitive(0) - self.drawareaday.drawgraph(record_list) - logging.debug("<<") + def actualize_weekview(self, record_list, date_ini, date_end): + logging.debug(">>") + date_s = datetime.datetime.strptime(date_ini, "%Y-%m-%d") + date_e = datetime.datetime.strptime(date_end, "%Y-%m-%d") + self.week_date.set_text("%s - %s (%d)" % (datetime.datetime.strftime(date_s, "%a %d %b"), datetime.datetime.strftime(date_e, "%a %d %b"), int(datetime.datetime.strftime(date_e, "%W"))+1) ) - def actualize_map(self,activity, full_screen=False): - logging.debug(">>") - #Check which type of map viewer to use - if self.radiobuttonOSM.get_active(): - #Use OSM to draw map - logging.debug("Using OSM to draw map....") - htmlfile = Osm(data_path=self.data_path, waypoint=self.waypoint, pytrainer_main=self.parent).drawMap(activity) - elif self.radiobuttonGMap.get_active(): - #Use Google to draw map - logging.debug("Using Google to draw map") - htmlfile = Googlemaps(data_path=self.data_path, waypoint=self.waypoint, pytrainer_main=self.parent).drawMap(activity) - else: - #Unknown map type... - logging.error("Unknown map viewer requested") - htmlfile = self.mapviewer.createErrorHtml() - logging.debug("Displaying htmlfile: %s" % htmlfile) - if full_screen: - logging.debug("Displaying in full screen mode") - self.mapviewer_fs.display_map(htmlfile=htmlfile) - else: - logging.debug("Displaying in embedded mode") - self.mapviewer.display_map(htmlfile=htmlfile) - logging.debug("<<") + km = calories = time = average = beats = 0 + num_records = len(record_list) + logging.info("Number of records selected week: "+str(num_records)) + time_in_min = 0 + tbeats = 0 + maxspeed = 0 + pace = "0:00" + maxpace = "0:00" + maxbeats = 0 - def actualize_weekview(self, record_list, date_ini, date_end): - logging.debug(">>") - date_s = datetime.datetime.strptime(date_ini, "%Y-%m-%d") - date_e = datetime.datetime.strptime(date_end, "%Y-%m-%d") - self.week_date.set_text("%s - %s (%d)" % (datetime.datetime.strftime(date_s, "%a %d %b"), datetime.datetime.strftime(date_e, "%a %d %b"), int(datetime.datetime.strftime(date_e, "%W"))+1) ) + if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": + self.w_distance_unit.set_text(_("miles")) + self.w_speed_unit.set_text(_("miles/h")) + self.w_maxspeed_unit.set_text(_("miles/h")) + self.w_pace_unit.set_text(_("min/mile")) + self.w_maxpace_unit.set_text(_("min/mile")) + else: + self.w_distance_unit.set_text(_("km")) + self.w_speed_unit.set_text(_("km/h")) + self.w_maxspeed_unit.set_text(_("km/h")) + self.w_pace_unit.set_text(_("min/km")) + self.w_maxpace_unit.set_text(_("min/km")) - km = calories = time = average = beats = 0 - num_records = len(record_list) - logging.info("Number of records selected week: "+str(num_records)) - time_in_min = 0 - tbeats = 0 - maxspeed = 0 - pace = "0:00" - maxpace = "0:00" - maxbeats = 0 + if num_records>0: + for record in record_list: + km += self.parseFloat(record[1]) + time += self.parseFloat(record[2]) + average += self.parseFloat(record[5]) + calories += self.parseFloat(record[6]) + beats = self.parseFloat(record[3]) + if float(beats) > 0: + time_in_min += time/60 + tbeats += beats*(time/60) + if record[7] > maxspeed: + maxspeed = self.parseFloat(record[7]) + if record[8] > maxbeats: + maxbeats = self.parseFloat(record[8]) - if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": - self.w_distance_unit.set_text(_("miles")) - self.w_speed_unit.set_text(_("miles/h")) - self.w_maxspeed_unit.set_text(_("miles/h")) - self.w_pace_unit.set_text(_("min/mile")) - self.w_maxpace_unit.set_text(_("min/mile")) - else: - self.w_distance_unit.set_text(_("km")) - self.w_speed_unit.set_text(_("km/h")) - self.w_maxspeed_unit.set_text(_("km/h")) - self.w_pace_unit.set_text(_("min/km")) - self.w_maxpace_unit.set_text(_("min/km")) + if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": + km = km2miles(km) + maxspeed = km2miles(maxspeed) - if num_records>0: - for record in record_list: - km += self.parseFloat(record[1]) - time += self.parseFloat(record[2]) - average += self.parseFloat(record[5]) - calories += self.parseFloat(record[6]) - beats = self.parseFloat(record[3]) - if float(beats) > 0: - time_in_min += time/60 - tbeats += beats*(time/60) - if record[7] > maxspeed: - maxspeed = self.parseFloat(record[7]) - if record[8] > maxbeats: - maxbeats = self.parseFloat(record[8]) + if time_in_min > 0: + tbeats = tbeats/time_in_min + else: + tbeats = 0 + if km > 0: + average = (km/(time/3600)) + else: + average = 0 - if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": - km = km2miles(km) - maxspeed = km2miles(maxspeed) + if maxspeed > 0: + #maxpace = 60/maxspeed + maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + if average > 0: + #pace = 60/average + pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) - if time_in_min > 0: - tbeats = tbeats/time_in_min - else: - tbeats = 0 - if km > 0: - average = (km/(time/3600)) - else: - average = 0 + self.weeka_distance.set_text("%0.2f" %km) + hour,min,sec = self.parent.date.second2time(time) + self.weeka_hour.set_text("%d" %hour) + self.weeka_minute.set_text("%02d" %min) + self.weeka_second.set_text("%02d" %sec) + self.weeka_maxbeats.set_text("%0.2f" %(maxbeats)) + self.weeka_beats.set_text("%0.2f" %(tbeats)) + self.weeka_average.set_text("%0.2f" %average) + self.weeka_maxspeed.set_text("%0.2f" %maxspeed) + self.weeka_pace.set_text(pace) + self.weeka_maxpace.set_text(maxpace) + self.weeka_calories.set_text("%0.0f" %calories) + self.weekview.set_sensitive(1) + else: + self.weekview.set_sensitive(0) + self.drawareaweek.drawgraph(record_list, date_ini, date_end) + logging.debug("<<") - if maxspeed > 0: - #maxpace = 60/maxspeed - maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) - if average > 0: - #pace = 60/average - pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) + def actualize_monthview(self,record_list, nameMonth): + logging.debug(">>") + self.month_date.set_text(nameMonth) + km = calories = time = average = beats = 0 + num_records = len(record_list) + time_in_min = 0 + tbeats = 0 + maxspeed = 0 + pace = "0:00" + maxpace = "0:00" + maxbeats = 0 - self.weeka_distance.set_text("%0.2f" %km) - hour,min,sec = self.parent.date.second2time(time) - self.weeka_hour.set_text("%d" %hour) - self.weeka_minute.set_text("%02d" %min) - self.weeka_second.set_text("%02d" %sec) - self.weeka_maxbeats.set_text("%0.2f" %(maxbeats)) - self.weeka_beats.set_text("%0.2f" %(tbeats)) - self.weeka_average.set_text("%0.2f" %average) - self.weeka_maxspeed.set_text("%0.2f" %maxspeed) - self.weeka_pace.set_text(pace) - self.weeka_maxpace.set_text(maxpace) - self.weeka_calories.set_text("%0.0f" %calories) - self.weekview.set_sensitive(1) - else: - self.weekview.set_sensitive(0) - self.drawareaweek.drawgraph(record_list, date_ini, date_end) - logging.debug("<<") + if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": + self.m_distance_unit.set_text(_("miles")) + self.m_speed_unit.set_text(_("miles/h")) + self.m_maxspeed_unit.set_text(_("miles/h")) + self.m_pace_unit.set_text(_("min/mile")) + self.m_maxpace_unit.set_text(_("min/mile")) + else: + self.m_distance_unit.set_text(_("km")) + self.m_speed_unit.set_text(_("km/h")) + self.m_maxspeed_unit.set_text(_("km/h")) + self.m_pace_unit.set_text(_("min/km")) + self.m_maxpace_unit.set_text(_("min/km")) - def actualize_monthview(self,record_list, nameMonth): - logging.debug(">>") - self.month_date.set_text(nameMonth) - km = calories = time = average = beats = 0 - num_records = len(record_list) - time_in_min = 0 - tbeats = 0 - maxspeed = 0 - pace = "0:00" - maxpace = "0:00" - maxbeats = 0 + if num_records>0: + for record in record_list: + km += self.parseFloat(record[1]) + time += self.parseFloat(record[2]) + average += self.parseFloat(record[5]) + calories += self.parseFloat(record[6]) + beats = self.parseFloat(record[3]) + if float(beats) > 0: + time_in_min += time/60 + tbeats += beats*(time/60) + if record[7] > maxspeed: + maxspeed = self.parseFloat(record[7]) + if record[8] > maxbeats: + maxbeats = self.parseFloat(record[8]) - if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": - self.m_distance_unit.set_text(_("miles")) - self.m_speed_unit.set_text(_("miles/h")) - self.m_maxspeed_unit.set_text(_("miles/h")) - self.m_pace_unit.set_text(_("min/mile")) - self.m_maxpace_unit.set_text(_("min/mile")) - else: - self.m_distance_unit.set_text(_("km")) - self.m_speed_unit.set_text(_("km/h")) - self.m_maxspeed_unit.set_text(_("km/h")) - self.m_pace_unit.set_text(_("min/km")) - self.m_maxpace_unit.set_text(_("min/km")) + if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": + km = km2miles(km) + maxspeed = km2miles(maxspeed) - if num_records>0: - for record in record_list: - km += self.parseFloat(record[1]) - time += self.parseFloat(record[2]) - average += self.parseFloat(record[5]) - calories += self.parseFloat(record[6]) - beats = self.parseFloat(record[3]) - if float(beats) > 0: - time_in_min += time/60 - tbeats += beats*(time/60) - if record[7] > maxspeed: - maxspeed = self.parseFloat(record[7]) - if record[8] > maxbeats: - maxbeats = self.parseFloat(record[8]) + if time_in_min > 0: + tbeats = tbeats/time_in_min + else: + tbeats = 0 + if km > 0: + average = (km/(time/3600)) + else: + average = 0 - if self.pytrainer_main.profile.getValue("pytraining","prf_us_system") == "True": - km = km2miles(km) - maxspeed = km2miles(maxspeed) + if maxspeed > 0: + #maxpace = 60/maxspeed + maxpace = "%d:%02d" %((3600/maxspeed)/60,float(3600/maxspeed)%60) + if average > 0: + #pace = 60/average + pace = "%d:%02d" %((3600/average)/60,float(3600/average)%60) - if time_in_min > 0: - tbeats = tbeats/time_in_min - else: - tbeats = 0 - if km > 0: - average = (km/(time/3600)) - else: - average = 0 + self.montha_distance.set_text("%0.2f" %km) + hour,min,sec = self.parent.date.second2time(time) + self.montha_hour.set_text("%d" %hour) + self.montha_minute.set_text("%02d" %min) + self.montha_second.set_text("%02d" %sec) + self.montha_maxbeats.set_text("%0.2f" %(maxbeats)) + self.montha_beats.set_text("%0.2f" %(tbeats)) + self.montha_average.set_text("%0.2f" %average) + self.montha_maxspeed.set_text("%0.2f" %maxspeed) + self.montha_pace.set_text(pace) + self.montha_maxpace.set_text(maxpace) + self.montha_calories.set_text("%0.0f" %calories) + self.monthview.set_sensitive(1) + else: + self.monthview.set_sensitive(0) + logging.debug("<<") - if maxspeed > 0: - #maxpace = 60/maxspeed - maxpace = "%d:%02d" %((3600/maxspeed)/60,float(3600/maxspeed)%60) - if average > 0: - #pace = 60/average - pace = "%d:%02d" %((3600/average)/60,float(3600/average)%60) + def actualize_monthgraph(self,record_list, daysInMonth): + logging.debug(">>") + self.drawareamonth.drawgraph(record_list, daysInMonth) + logging.debug("<<") - self.montha_distance.set_text("%0.2f" %km) - hour,min,sec = self.parent.date.second2time(time) - self.montha_hour.set_text("%d" %hour) - self.montha_minute.set_text("%02d" %min) - self.montha_second.set_text("%02d" %sec) - self.montha_maxbeats.set_text("%0.2f" %(maxbeats)) - self.montha_beats.set_text("%0.2f" %(tbeats)) - self.montha_average.set_text("%0.2f" %average) - self.montha_maxspeed.set_text("%0.2f" %maxspeed) - self.montha_pace.set_text(pace) - self.montha_maxpace.set_text(maxpace) - self.montha_calories.set_text("%0.0f" %calories) - self.monthview.set_sensitive(1) - else: - self.monthview.set_sensitive(0) - logging.debug("<<") + def actualize_yearview(self,record_list, year): + logging.debug(">>") + self.year_date.set_text("%d" %int(year)) + km = calories = time = average = beats = 0 + num_records = len(record_list) + time_in_min = 0 + tbeats = 0 + maxspeed = 0 + pace = "0:00" + maxpace = "0:00" + maxbeats = 0 + if num_records>0: + for record in record_list: + km += self.parseFloat(record[1]) + time += self.parseFloat(record[2]) + average += self.parseFloat(record[5]) + calories += self.parseFloat(record[6]) + beats = self.parseFloat(record[3]) + if float(beats) > 0: + time_in_min += time/60 + tbeats += beats*(time/60) + if record[7] > maxspeed: + maxspeed = self.parseFloat(record[7]) + if record[8] > maxbeats: + maxbeats = self.parseFloat(record[8]) + if time_in_min > 0: + tbeats = tbeats/time_in_min + else: + tbeats = 0 + if km > 0: + average = (km/(time/3600)) + else: + average = 0 - def actualize_monthgraph(self,record_list, daysInMonth): - logging.debug(">>") - self.drawareamonth.drawgraph(record_list, daysInMonth) - logging.debug("<<") + if maxspeed > 0: + #maxpace = 60/maxspeed + maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) + if average > 0: + #pace = 60/average + pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) - def actualize_yearview(self,record_list, year): - logging.debug(">>") - self.year_date.set_text("%d" %int(year)) - km = calories = time = average = beats = 0 - num_records = len(record_list) - time_in_min = 0 - tbeats = 0 - maxspeed = 0 - pace = "0:00" - maxpace = "0:00" - maxbeats = 0 - if num_records>0: - for record in record_list: - km += self.parseFloat(record[1]) - time += self.parseFloat(record[2]) - average += self.parseFloat(record[5]) - calories += self.parseFloat(record[6]) - beats = self.parseFloat(record[3]) - if float(beats) > 0: - time_in_min += time/60 - tbeats += beats*(time/60) - if record[7] > maxspeed: - maxspeed = self.parseFloat(record[7]) - if record[8] > maxbeats: - maxbeats = self.parseFloat(record[8]) - if time_in_min > 0: - tbeats = tbeats/time_in_min - else: - tbeats = 0 - if km > 0: - average = (km/(time/3600)) - else: - average = 0 + self.yeara_distance.set_text("%0.2f" %km) + hour,min,sec = self.parent.date.second2time(time) + self.yeara_hour.set_text("%d" %hour) + self.yeara_minute.set_text("%02d" %min) + self.yeara_second.set_text("%02d" %sec) + self.yeara_beats.set_text("%0.2f" %tbeats) + self.yeara_maxbeats.set_text("%0.2f" %(maxbeats)) + self.yeara_average.set_text("%0.2f" %average) + self.yeara_maxspeed.set_text("%0.2f" %maxspeed) + self.yeara_pace.set_text(pace) + self.yeara_maxpace.set_text(maxpace) + self.yeara_calories.set_text("%0.0f" %calories) + self.yearview.set_sensitive(1) + else: + self.yearview.set_sensitive(0) + self.drawareayear.drawgraph([]) + logging.debug("<<") - if maxspeed > 0: - #maxpace = 60/maxspeed - maxpace = "%d:%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) - if average > 0: - #pace = 60/average - pace = "%d:%02d" %((3600/average)/60,(3600/average)%60) + def actualize_yeargraph(self,record_list): + logging.debug(">>") + self.drawareayear.drawgraph(record_list) + logging.debug("<<") - self.yeara_distance.set_text("%0.2f" %km) - hour,min,sec = self.parent.date.second2time(time) - self.yeara_hour.set_text("%d" %hour) - self.yeara_minute.set_text("%02d" %min) - self.yeara_second.set_text("%02d" %sec) - self.yeara_beats.set_text("%0.2f" %tbeats) - self.yeara_maxbeats.set_text("%0.2f" %(maxbeats)) - self.yeara_average.set_text("%0.2f" %average) - self.yeara_maxspeed.set_text("%0.2f" %maxspeed) - self.yeara_pace.set_text(pace) - self.yeara_maxpace.set_text(maxpace) - self.yeara_calories.set_text("%0.0f" %calories) - self.yearview.set_sensitive(1) - else: - self.yearview.set_sensitive(0) - self.drawareayear.drawgraph([]) - logging.debug("<<") + def actualize_athleteview(self, athletedata): + logging.debug(">>") + self.labelName.set_text(athletedata["prf_name"]) + self.labelDOB.set_text(athletedata["prf_age"]) + self.labelHeight.set_text(athletedata["prf_height"]+" cm") + #Setup graph + self.grapher = DrawGraph(self, self.pytrainer_main) + from pytrainer.lib.graphdata import GraphData + datalist = GraphData(title="Weight", xlabel="Date", ylabel="kg") + #TODO + #Create history treeview + history_store = gtk.ListStore( + gobject.TYPE_INT, #index + gobject.TYPE_STRING, #date + gobject.TYPE_STRING, #weight + gobject.TYPE_STRING, #body fat % + gobject.TYPE_INT, #resting HR + gobject.TYPE_INT #max HR + ) + for data_index, data in enumerate(athletedata['history']): + weight = float(data['Weight']) + date = dateutil.parser.parse(data['Date']).date() - def actualize_yeargraph(self,record_list): - logging.debug(">>") - self.drawareayear.drawgraph(record_list) - logging.debug("<<") + iter = history_store.append() + history_store.set ( + iter, + 0, data_index, + 1, date, #TODO need to sort date graphing... + 2, "%0.2f" % weight, + 3, "%0.2f" % float(data['BF']), + 4, int(data['RestingHR']), + 5, int(data['MaxHR']), + ) + datalist.addPoints(x=date, y=weight) + self.athleteTreeView.set_model(history_store) + self.grapher.drawPlot(datalist=datalist, box=self.boxAthleteGraph) + logging.debug("<<") - def actualize_athleteview(self, athletedata): - logging.debug(">>") - self.labelName.set_text(athletedata["prf_name"]) - self.labelDOB.set_text(athletedata["prf_age"]) - self.labelHeight.set_text(athletedata["prf_height"]+" cm") - #Setup graph - self.grapher = DrawGraph(self, self.pytrainer_main) - from pytrainer.lib.graphdata import GraphData - datalist = GraphData(title="Weight", xlabel="Date", ylabel="kg") - #TODO - #Create history treeview - history_store = gtk.ListStore( - gobject.TYPE_INT, #index - gobject.TYPE_STRING, #date - gobject.TYPE_STRING, #weight - gobject.TYPE_STRING, #body fat % - gobject.TYPE_INT, #resting HR - gobject.TYPE_INT #max HR - ) - for data_index, data in enumerate(athletedata['history']): - weight = float(data['Weight']) - date = dateutil.parser.parse(data['Date']).date() + def actualize_listview(self,record_list): + logging.debug(">>") + #recod list tiene: + #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")] - iter = history_store.append() - history_store.set ( - iter, - 0, data_index, - 1, date, #TODO need to sort date graphing... - 2, "%0.2f" % weight, - 3, "%0.2f" % float(data['BF']), - 4, int(data['RestingHR']), - 5, int(data['MaxHR']), - ) - datalist.addPoints(x=date, y=weight) - self.athleteTreeView.set_model(history_store) - self.grapher.drawPlot(datalist=datalist, box=self.boxAthleteGraph) - logging.debug("<<") + date = Date() + store = gtk.ListStore( + gobject.TYPE_INT, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_FLOAT, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_INT, + gobject.TYPE_FLOAT, + gobject.TYPE_INT, + object) + for i in record_list: + hour,min,sec = date.second2time(int(i[6])) + time = "%d:%02d:%02d" %(hour,min,sec) + 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 + ) + #self.allRecordTreeView.set_headers_clickable(True) + self.allRecordTreeView.set_model(store) + logging.debug("<<") - def actualize_listview(self,record_list): - logging.debug(">>") - #recod list tiene: - #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")] + def actualize_waypointview(self,record_list,default_waypoint,redrawmap = 1): + logging.debug(">>") + #redrawmap: indica si tenemos que refrescar tb el mapa. 1 si 0 no + #waypoint list tiene: + #id_waypoint,lat,lon,ele,comment,time,name,sym + #Laas columnas son: + #column_names=[_("id"),_("Waypoint")] - date = Date() - store = gtk.ListStore( - gobject.TYPE_INT, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_FLOAT, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - gobject.TYPE_STRING, - object) - for i in record_list: - hour,min,sec = date.second2time(int(i[6])) - time = "%d:%d:%d" %(hour,min,sec) - iter = store.append() - store.set ( - iter, - 0, int(i[5]), - 1, str(i[3]), - 2, str(i[0]), - 3, float(i[1]), - 4, str(i[4]), - 5, time, - 6, str(i[7]), - 7, str(i[2]), - 8, str(i[8]) - ) - #self.allRecordTreeView.set_headers_clickable(True) - self.allRecordTreeView.set_model(store) - logging.debug("<<") + store = gtk.ListStore( + gobject.TYPE_INT, + gobject.TYPE_STRING, + object) + iterOne = False + iterDefault = False + counter = 0 + default_id = 0 + for i in record_list: + iter = store.append() + if not iterOne: + iterOne = iter + if int(i[0])==default_waypoint: + iterDefault = iter + default_id = counter + store.set ( + iter, + 0, int(i[0]), + 1, str(i[6]) + ) + counter+=1 - def actualize_waypointview(self,record_list,default_waypoint,redrawmap = 1): - logging.debug(">>") - #redrawmap: indica si tenemos que refrescar tb el mapa. 1 si 0 no - #waypoint list tiene: - #id_waypoint,lat,lon,ele,comment,time,name,sym - #Laas columnas son: - #column_names=[_("id"),_("Waypoint")] + self.waypointTreeView.set_model(store) + if iterDefault: + self.waypointTreeView.get_selection().select_iter(iterDefault) + elif iterOne: + self.waypointTreeView.get_selection().select_iter(iterOne) + if len(record_list) > 0: + self.waypoint_latitude.set_text(str(record_list[default_id][1])) + self.waypoint_longitude.set_text(str(record_list[default_id][2])) + self.waypoint_name.set_text(str(record_list[default_id][6])) + self.waypoint_description.set_text(str(record_list[default_id][4])) + self.set_waypoint_type(str(record_list[default_id][7])) + if redrawmap == 1: + self.waypointeditor.createHtml(default_waypoint) + self.waypointeditor.drawMap() + logging.debug("<<") - store = gtk.ListStore( - gobject.TYPE_INT, - gobject.TYPE_STRING, - object) - iterOne = False - iterDefault = False - counter = 0 - default_id = 0 - for i in record_list: - iter = store.append() - if not iterOne: - iterOne = iter - if int(i[0])==default_waypoint: - iterDefault = iter - default_id = counter - store.set ( - iter, - 0, int(i[0]), - 1, str(i[6]) - ) - counter+=1 + ... [truncated message content] |
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-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-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 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-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-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 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-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 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-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-05 09:04:50
|
Revision: 645 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=645&view=rev Author: jblance Date: 2010-10-05 09:04:44 +0000 (Tue, 05 Oct 2010) Log Message: ----------- Fix pace by lap to check max pace setting Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-10-05 04:00:20 UTC (rev 644) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-10-05 09:04:44 UTC (rev 645) @@ -237,6 +237,9 @@ 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 + 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 logging.debug("Time: %f, Dist: %f, Pace: %f" % (time, dist, pace) ) self.lap_time.addBars(x=time, y=10) if self.us_system: Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-05 04:00:20 UTC (rev 644) +++ pytrainer/trunk/pytrainer/main.py 2010-10-05 09:04:44 UTC (rev 645) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#644" + self.version ="1.7.2_svn#645" 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-05 10:32:06
|
Revision: 646 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=646&view=rev Author: jblance Date: 2010-10-05 10:31:59 +0000 (Tue, 05 Oct 2010) Log Message: ----------- Start of implementation of user selectable graph axis limits for newgraph - currently only displaying the limits Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-05 09:04:44 UTC (rev 645) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-05 10:31:59 UTC (rev 646) @@ -34,18 +34,18 @@ self.ax1 = None self.ax2 = None logging.debug('<<') - + 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 + title = + y2 = + + return = figure ''' logging.debug('>>') if box is None: @@ -62,19 +62,19 @@ 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 - + if y2 and self.ax2 is None: self.ax2 = plt.twinx() - - + + #Create canvas canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea canvas.show() - + #Display title etc if datalist.xlabel is not None: plt.xlabel(datalist.xlabel) @@ -117,10 +117,10 @@ 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) - + #Display plot box.pack_start(canvas, True, True) - + logging.debug("<<") return figure @@ -144,7 +144,7 @@ #Debug info - to remove print("drawPlot....") #print datalist - + #Set up drawing area figure = plt.figure() canvas = FigureCanvasGTK(figure) # a gtk.DrawingArea @@ -219,7 +219,7 @@ 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 @@ -230,7 +230,7 @@ return if activity is None: logging.error("Must supply data to graph graph") - return + return #TODO Check that datalist is of type dict (and contains has correct items) figure = None datalist = [] @@ -242,7 +242,7 @@ _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 for item in activity.distance_data: if activity.distance_data[item].show_on_y1: @@ -271,7 +271,7 @@ #Display lap divisions if required if activity.show_laps: figure = self.draw(activity.lap_time, box=box, figure=figure) - + #Sort out graph errors... if y1count == 0 and y2count == 0: logging.debug("No items to graph.. Removing graph") @@ -279,4 +279,16 @@ elif y1count == 0: logging.debug("No items on y1 axis... ") #TODO Sort + #Get axis limits.. + if self.ax1 is not None: + activity.x_limits = self.ax1.get_xlim() + activity.y1_limits = self.ax1.get_ylim() + else: + activity.y1_limits = (None, None) + if self.ax2 is not None: + activity.x_limits = self.ax2.get_xlim() + activity.y2_limits = self.ax2.get_ylim() + else: + activity.y2_limits = (None, None) + return activity logging.debug('<<') Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-05 09:04:44 UTC (rev 645) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-05 10:31:59 UTC (rev 646) @@ -68,10 +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 @@ -300,19 +300,15 @@ for child in self.graph_data_hbox.get_children(): if isinstance(child, gtk.Frame): 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") y2Frame = gtk.Frame(label="Show on Y2 Axis") + limitsFrame = gtk.Frame(label="Axis Limits") xvbox = gtk.VBox() y1box = gtk.Table() y2box = gtk.Table() + limitsbox = gtk.Table() #Populate X axis data #Create x axis items xdistancebutton = gtk.RadioButton(label=_("Distance")) @@ -329,11 +325,39 @@ xtimebutton.connect("toggled", self.on_xaxischange, "time", activity) xlapsbutton.connect("toggled", self.on_xlapschange, activity) #Add buttons to frame - xvbox.add(xdistancebutton) - xvbox.add(xtimebutton) - xvbox.add(xlapsbutton) + xvbox.pack_start(xdistancebutton, expand=False) + xvbox.pack_start(xtimebutton, expand=False) + xvbox.pack_start(xlapsbutton, expand=False) xFrame.add(xvbox) - + + #Populate axis limits frame + #TODO Need to change these to editable objects and redraw graphs if changed.... + minlabel = gtk.Label("<small>Min</small>") + minlabel.set_use_markup(True) + maxlabel = gtk.Label("<small>Max</small>") + maxlabel.set_use_markup(True) + xlimlabel = gtk.Label("X") + xminlabel = gtk.Label() + xmaxlabel = gtk.Label() + y1limlabel = gtk.Label("Y1") + y1minlabel = gtk.Label() + y1maxlabel = gtk.Label() + y2limlabel = gtk.Label("Y2") + y2minlabel = gtk.Label() + y2maxlabel = gtk.Label() + limitsbox.attach(minlabel, 1, 2, 0, 1, yoptions=gtk.SHRINK) + limitsbox.attach(maxlabel, 2, 3, 0, 1, yoptions=gtk.SHRINK) + limitsbox.attach(xlimlabel, 0, 1, 1, 2, yoptions=gtk.SHRINK) + limitsbox.attach(xminlabel, 1, 2, 1, 2, yoptions=gtk.SHRINK, xpadding=5) + limitsbox.attach(xmaxlabel, 2, 3, 1, 2, yoptions=gtk.SHRINK, xpadding=5) + limitsbox.attach(y1limlabel, 0, 1, 2, 3, yoptions=gtk.SHRINK) + limitsbox.attach(y1minlabel, 1, 2, 2, 3, yoptions=gtk.SHRINK, xpadding=5) + limitsbox.attach(y1maxlabel, 2, 3, 2, 3, yoptions=gtk.SHRINK, xpadding=5) + limitsbox.attach(y2limlabel, 0, 1, 3, 4, yoptions=gtk.SHRINK) + limitsbox.attach(y2minlabel, 1, 2, 3, 4, yoptions=gtk.SHRINK, xpadding=5) + limitsbox.attach(y2maxlabel, 2, 3, 3, 4, yoptions=gtk.SHRINK, xpadding=5) + limitsFrame.add(limitsbox) + row = 0 if activity.x_axis == "distance": data = activity.distance_data @@ -361,7 +385,7 @@ 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.set_active(data[graphdata].show_on_y2) @@ -374,18 +398,29 @@ #Attach to container y2box.attach(y2color, 1, 2, row, row+1) row += 1 - + y1Frame.add(y1box) 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.pack_start(xFrame, expand=False, fill=False, padding=5) + self.graph_data_hbox.pack_start(y1Frame, expand=False, fill=False, padding=5) + self.graph_data_hbox.pack_start(y2Frame, expand=False, fill=False, padding=5) + self.graph_data_hbox.pack_start(limitsFrame, expand=False, fill=True, padding=5) self.graph_data_hbox.show_all() self.buttonGraphShowOptions.hide() - self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) - + act = self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + xmin, xmax = act.x_limits + y1min, y1max = act.y1_limits + y2min, y2max = act.y2_limits + #print y1min, y1max, y2min, y2max + if xmin is not None and xmax is not None: + xminlabel.set_text(str(xmin)) + xmaxlabel.set_text(str(xmax)) + if y1min is not None and y1min is not None: + y1minlabel.set_text(str(y1min)) + y1maxlabel.set_text(str(y1max)) + if y2min is not None and y2min is not None: + y2minlabel.set_text(str(y2min)) + y2maxlabel.set_text(str(y2max)) else: logging.debug("Activity has no GPX data") #Show drop down boxes @@ -507,7 +542,7 @@ else: self.dayview.set_sensitive(0) logging.debug("<<") - + def actualize_daygraph(self,record_list): logging.debug(">>") if len(record_list)>0: @@ -795,7 +830,7 @@ iter = history_store.append() history_store.set ( iter, - 0, data_index, + 0, data_index, 1, date, #TODO need to sort date graphing... 2, "%0.2f" % weight, 3, "%0.2f" % float(data['BF']), @@ -846,7 +881,7 @@ logging.debug("Unable to parse beats for %s" % str(i[7]) ) logging.debug(str(e)) _beats = 0.0 - + iter = store.append() store.set ( iter, @@ -1023,7 +1058,7 @@ logging.debug("Reseting graph Y axis with ylimits: %s" % str(y1limits) ) self.drawarearecord.drawgraph(self.record_list,self.laps, y1limits=y1limits, y1color=y1color, y1_linewidth=y1_linewidth) logging.debug("<<") - + def update_athlete_item(self, idx, date, weight, bf, restingHR, maxHR): logging.debug(">>") #Prepare vars @@ -1045,45 +1080,47 @@ ###################### ## Lista de eventos ## ###################### - - def on_xaxischange(self, widget, data=None, activity=None): - '''Handler for record graph axis selection changes''' - if widget.get_active(): + + def on_xaxischange(self, widget, data=None, activity=None): + '''Handler for record graph axis selection changes''' + if widget.get_active(): activity.x_axis = data self.actualize_recordgraph(activity) - - def on_xlapschange(self, widget, activity=None): - if widget.get_active(): + + 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''' + + 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_y2colorchange(self, widget, box, graphdata, activity): - '''Hander for changes to y2 color selection''' + #self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + self.actualize_recordgraph(activity) + + 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''' + #self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + self.actualize_recordgraph(activity) + + def on_y1change(self, widget, box, graphdata, activity): + '''Hander for changes to y1 selection''' logging.debug("Y1 selection toggled: %s" % graphdata) #Loop through all options at set data correctly - for child in box.get_children(): + 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(): @@ -1095,13 +1132,14 @@ 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) - + #self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + self.actualize_recordgraph(activity) + def on_y2change(self, widget, box, graphdata, activity): - '''Hander for changes to y2 selection''' + '''Hander for changes to y2 selection''' logging.debug("Y2 selection toggled: %s" % graphdata) #Loop through all options at set data correctly - for child in box.get_children(): + 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(): @@ -1113,8 +1151,9 @@ 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) - + #self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) + self.actualize_recordgraph(activity) + def on_athleteTreeView_button_press_event(self, treeview, event): x = int(event.x) y = int(event.y) @@ -1151,7 +1190,7 @@ self.buttonShowOptions.set_tooltip_text(_('Show graph display options') ) #logging.debug('Position: %d' % self.hpaned1.get_position() ) logging.debug('Position set: %s' % self.hpaned1.get_property('position-set') ) - + def on_buttonGraphHideOptions_clicked(self, widget): logging.debug('on_buttonGraphHideOptions_clicked') self.buttonGraphHideOptions.hide() @@ -1159,8 +1198,8 @@ if isinstance(child, gtk.Frame): child.hide() self.buttonGraphShowOptions.show() - - + + def on_buttonGraphShowOptions_clicked(self, widget): logging.debug('on_buttonGraphShowOptions_clicked') self.buttonGraphShowOptions.hide() @@ -1365,9 +1404,9 @@ #hasta aqui revisado def on_allRecordTreeView_button_press(self, treeview, event): - ''' - Handler for clicks on recordview list (list of activities for the day) - + ''' + 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(">>") Modified: pytrainer/trunk/pytrainer/lib/activity.py =================================================================== --- pytrainer/trunk/pytrainer/lib/activity.py 2010-10-05 09:04:44 UTC (rev 645) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-10-05 10:31:59 UTC (rev 646) @@ -111,6 +111,9 @@ self._init_graph_data() self._generate_per_lap_graphs() self.x_axis = "distance" + self.x_limits = (None, None) + self.y1_limits = (None, None) + self.y2_limits = (None, None) self.show_laps = False logging.debug("<<") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-05 09:04:44 UTC (rev 645) +++ pytrainer/trunk/pytrainer/main.py 2010-10-05 10:31:59 UTC (rev 646) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#645" + self.version ="1.7.2_svn#646" 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-07 03:53:30
|
Revision: 648 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=648&view=rev Author: jblance Date: 2010-10-07 03:53:23 +0000 (Thu, 07 Oct 2010) Log Message: ----------- Allow axis limits to be set and reset (for newgraph only) Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/activity.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-06 22:48:47 UTC (rev 647) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-07 03:53:23 UTC (rev 648) @@ -290,5 +290,21 @@ activity.y2_limits = self.ax2.get_ylim() else: activity.y2_limits = (None, None) + #Set axis limits if requested + #X Axis + if activity.x_limits_u[0] is not None: + if self.ax1 is not None: + self.ax1.set_xlim(activity.x_limits_u) + elif self.ax2 is not None: + self.ax2.set_xlim(activity.x_limits_u) + #Y1 Axis + if activity.y1_limits_u[0] is not None: + if self.ax1 is not None: + self.ax1.set_ylim(activity.y1_limits_u) + #Y2 Axis + if activity.y2_limits_u[0] is not None: + if self.ax2 is not None: + self.ax2.set_ylim(activity.y2_limits_u) + return activity logging.debug('<<') Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-06 22:48:47 UTC (rev 647) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-07 03:53:23 UTC (rev 648) @@ -115,6 +115,16 @@ self.radiobuttonOSM.set_active(1) else: self.radiobuttonGMap.set_active(1) + + def _float_or(self, value, default): + '''Function to parse and return a float, or the default if the parsing fails''' + try: + result = float(value) + except Exception as e: + #print type(e) + #print e + result = default + return result def setup(self): self.createGraphs(RecordGraph,DayGraph,WeekGraph, MonthGraph,YearGraph,HeartRateGraph) @@ -332,19 +342,44 @@ #Populate axis limits frame #TODO Need to change these to editable objects and redraw graphs if changed.... + #Create labels etc minlabel = gtk.Label("<small>Min</small>") minlabel.set_use_markup(True) maxlabel = gtk.Label("<small>Max</small>") maxlabel.set_use_markup(True) xlimlabel = gtk.Label("X") - xminlabel = gtk.Label() - xmaxlabel = gtk.Label() + limits = {} + xminlabel = gtk.Entry(max=10) + xmaxlabel = gtk.Entry(max=10) + limits['xminlabel'] = xminlabel + limits['xmaxlabel'] = xmaxlabel + xminlabel.set_width_chars(5) + xminlabel.set_alignment(1.0) + xmaxlabel.set_width_chars(5) + xmaxlabel.set_alignment(1.0) y1limlabel = gtk.Label("Y1") - y1minlabel = gtk.Label() - y1maxlabel = gtk.Label() + y1minlabel = gtk.Entry(max=10) + y1maxlabel = gtk.Entry(max=10) + limits['y1minlabel'] = y1minlabel + limits['y1maxlabel'] = y1maxlabel + y1minlabel.set_width_chars(5) + y1minlabel.set_alignment(1.0) + y1maxlabel.set_width_chars(5) + y1maxlabel.set_alignment(1.0) y2limlabel = gtk.Label("Y2") - y2minlabel = gtk.Label() - y2maxlabel = gtk.Label() + y2minlabel = gtk.Entry(max=10) + y2maxlabel = gtk.Entry(max=10) + limits['y2minlabel'] = y2minlabel + limits['y2maxlabel'] = y2maxlabel + y2minlabel.set_width_chars(5) + y2minlabel.set_alignment(1.0) + y2maxlabel.set_width_chars(5) + y2maxlabel.set_alignment(1.0) + resetbutton = gtk.Button(_('Reset Limits')) + resetbutton.connect("clicked", self.on_setlimits, activity, True, None) + setbutton = gtk.Button(_('Set Limits')) + setbutton.connect("clicked", self.on_setlimits, activity, False, limits) + #Add labels etc to table limitsbox.attach(minlabel, 1, 2, 0, 1, yoptions=gtk.SHRINK) limitsbox.attach(maxlabel, 2, 3, 0, 1, yoptions=gtk.SHRINK) limitsbox.attach(xlimlabel, 0, 1, 1, 2, yoptions=gtk.SHRINK) @@ -356,6 +391,8 @@ limitsbox.attach(y2limlabel, 0, 1, 3, 4, yoptions=gtk.SHRINK) limitsbox.attach(y2minlabel, 1, 2, 3, 4, yoptions=gtk.SHRINK, xpadding=5) limitsbox.attach(y2maxlabel, 2, 3, 3, 4, yoptions=gtk.SHRINK, xpadding=5) + limitsbox.attach(setbutton, 0, 3, 4, 5, yoptions=gtk.SHRINK) + limitsbox.attach(resetbutton, 0, 3, 5, 6, yoptions=gtk.SHRINK) limitsFrame.add(limitsbox) row = 0 @@ -408,17 +445,26 @@ self.graph_data_hbox.show_all() self.buttonGraphShowOptions.hide() act = self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) - xmin, xmax = act.x_limits - y1min, y1max = act.y1_limits - y2min, y2max = act.y2_limits + if act.x_limits_u[0] is not None: + xmin, xmax = act.x_limits_u + else: + xmin, xmax = act.x_limits + if act.y1_limits_u[0] is not None: + y1min, y1max = act.y1_limits_u + else: + y1min, y1max = act.y1_limits + if act.y2_limits_u[0] is not None: + y2min, y2max = act.y2_limits_u + else: + y2min, y2max = act.y2_limits #print y1min, y1max, y2min, y2max if xmin is not None and xmax is not None: xminlabel.set_text(str(xmin)) xmaxlabel.set_text(str(xmax)) - if y1min is not None and y1min is not None: + if y1min is not None and y1max is not None: y1minlabel.set_text(str(y1min)) y1maxlabel.set_text(str(y1max)) - if y2min is not None and y2min is not None: + if y2min is not None and y2max is not None: y2minlabel.set_text(str(y2min)) y2maxlabel.set_text(str(y2max)) else: @@ -1153,6 +1199,32 @@ #Replot the activity #self.grapher.drawMultiPlot(activity=activity, box=self.record_graph_vbox) self.actualize_recordgraph(activity) + + def on_setlimits(self, widget, activity, reset, data): + '''Handler for setting graph limits buttons''' + if data is None: + logging.debug("Resetting graph limits...") + activity.x_limits_u = (None, None) + activity.y1_limits_u = (None, None) + activity.y2_limits_u = (None, None) + #Replot the activity + self.actualize_recordgraph(activity) + else: + #Setting to limits in boxes + logging.debug("Setting graph limits...") + #Determine contents of boxes... + xmin = self._float_or(data['xminlabel'].get_text(), activity.x_limits[0]) + xmax = self._float_or(data['xmaxlabel'].get_text(), activity.x_limits[1]) + y1min = self._float_or(data['y1minlabel'].get_text(), activity.y1_limits[0]) + y1max = self._float_or(data['y1maxlabel'].get_text(), activity.y1_limits[1]) + y2min = self._float_or(data['y2minlabel'].get_text(), activity.y2_limits[0]) + y2max = self._float_or(data['y2maxlabel'].get_text(), activity.y2_limits[1]) + logging.debug("Setting graph limits x: (%s,%s), y1: (%s,%s), y2: (%s,%s)" % (str(xmin), str(xmax), str(y1min), str(y1max), str(y2min), str(y2max)) ) + activity.x_limits_u = (xmin, xmax) + activity.y1_limits_u = (y1min, y1max) + activity.y2_limits_u = (y2min, y2max) + #Replot the activity + self.actualize_recordgraph(activity) 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-06 22:48:47 UTC (rev 647) +++ pytrainer/trunk/pytrainer/lib/activity.py 2010-10-07 03:53:23 UTC (rev 648) @@ -68,6 +68,12 @@ 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 + x_limits - (tuple of float) start, end limits of x axis (as determined by matplotlib) + y1_limits - (tuple of float) start, end limits of y1 axis (as determined by matplotlib) + y2_limits - (tuple of float) start, end limits of y2 axis (as determined by matplotlib) + x_limits_u - (tuple of float) start, end limits of x axis (as requested by user) + y1_limits_u - (tuple of float) start, end limits of y1 axis (as requested by user) + y2_limits_u - (tuple of float) start, end limits of y2 axis (as requested by user) show_laps - (bool) display laps on graphs lap_distance - (graphdata) lap_time - (graphdata) @@ -114,6 +120,9 @@ self.x_limits = (None, None) self.y1_limits = (None, None) self.y2_limits = (None, None) + self.x_limits_u = (None, None) + self.y1_limits_u = (None, None) + self.y2_limits_u = (None, None) self.show_laps = False logging.debug("<<") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-06 22:48:47 UTC (rev 647) +++ pytrainer/trunk/pytrainer/main.py 2010-10-07 03:53:23 UTC (rev 648) @@ -49,7 +49,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#647" + self.version ="1.7.2_svn#648" 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-08 04:08:29
|
Revision: 649 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=649&view=rev Author: jblance Date: 2010-10-08 04:08:23 +0000 (Fri, 08 Oct 2010) Log Message: ----------- Add athlete stats DB table Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/ddbb.py pytrainer/trunk/pytrainer/main.py Added Paths: ----------- pytrainer/trunk/pytrainer/athlete.py Added: pytrainer/trunk/pytrainer/athlete.py =================================================================== --- pytrainer/trunk/pytrainer/athlete.py (rev 0) +++ pytrainer/trunk/pytrainer/athlete.py 2010-10-08 04:08:23 UTC (rev 649) @@ -0,0 +1,42 @@ +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... +#Modified by dgranda + +#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 logging + +from lib.ddbb import DDBB + +class Athlete: + def __init__(self, data_path = None, parent = None): + logging.debug('>>') + self.parent = parent + self.pytrainer_main = parent + self.data_path = data_path + logging.debug('<<') + + def get_athlete_stats(self): + print('>>') + stats = [] + results = self.pytrainer_main.ddbb.select("athletestats", "id_athletestat, date, weight, bodyfat, restinghr, maxhr") + print('Found %d athlete stats results' % len(results)) + for row in results: + stats.append({'id_athletestat': row[0], 'Date': row[1], 'Weight':row[2], 'BF': row[3], 'RestingHR':row[4], 'MaxHR':row[5]}) + return stats + print('<<') + + Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-07 03:53:23 UTC (rev 648) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-08 04:08:23 UTC (rev 649) @@ -862,7 +862,7 @@ #TODO #Create history treeview history_store = gtk.ListStore( - gobject.TYPE_INT, #index + gobject.TYPE_INT, #id gobject.TYPE_STRING, #date gobject.TYPE_STRING, #weight gobject.TYPE_STRING, #body fat % @@ -876,7 +876,7 @@ iter = history_store.append() history_store.set ( iter, - 0, data_index, + 0, int(data['id_athletestat']), 1, date, #TODO need to sort date graphing... 2, "%0.2f" % weight, 3, "%0.2f" % float(data['BF']), Modified: pytrainer/trunk/pytrainer/lib/ddbb.py =================================================================== --- pytrainer/trunk/pytrainer/lib/ddbb.py 2010-10-07 03:53:23 UTC (rev 648) +++ pytrainer/trunk/pytrainer/lib/ddbb.py 2010-10-08 04:08:23 UTC (rev 649) @@ -162,6 +162,14 @@ "end_lon": "float", "calories": "int", }, + "athletestats": { + "id_athletestat": "integer primary key autoincrement", + "date": "date", + "weight": "float", + "bodyfat": "float", + "restinghr": "integer", + "maxhr": "integer", + }, } try: tablesDBT = self.ddbbObject.select("sqlite_master","name", "type IN ('table','view') AND name NOT LIKE 'sqlite_%' ORDER BY name") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-07 03:53:23 UTC (rev 648) +++ pytrainer/trunk/pytrainer/main.py 2010-10-08 04:08:23 UTC (rev 649) @@ -38,6 +38,7 @@ from importdata import Importdata from plugins import Plugins from profile import Profile +from athlete import Athlete from gui.windowimportdata import WindowImportdata from gui.windowmain import Main @@ -49,8 +50,8 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#648" - self.DB_version = 4 + self.version ="1.7.2_svn#649" + self.DB_version = 5 #Process command line options self.startup_options = self.get_options() #Setup logging @@ -80,6 +81,7 @@ else: logging.info('No sanity check requested') self.record = Record(data_path,self) + self.athlete = Athlete(data_path,self) pool_size = self.profile.getIntValue("pytraining","activitypool_size", default=1) self.activitypool = ActivityPool(self, size=pool_size) #preparamos la ventana principal @@ -311,14 +313,7 @@ athletedata['prf_name'] = self.profile.getValue("pytraining","prf_name") athletedata['prf_age'] = self.profile.getValue("pytraining","prf_age") athletedata['prf_height'] = self.profile.getValue("pytraining","prf_height") - athletedata['history'] = ( - {'Date':'2010-01-01', 'Weight':88.8, 'BF':15.0, 'RestingHR':67, 'MaxHR':220}, - {'Date':'2010-02-01', 'Weight':89.8, 'BF':16.0, 'RestingHR':68, 'MaxHR':221}, - {'Date':'2010-03-01', 'Weight':99.1, 'BF':13.0, 'RestingHR':65, 'MaxHR':212}, - {'Date':'2010-04-01', 'Weight':79.5, 'BF':11.0, 'RestingHR':61, 'MaxHR':210}, - {'Date':'2010-05-01', 'Weight':67.2, 'BF':13.0, 'RestingHR':60, 'MaxHR':205}, - {'Date':'2010-06-01', 'Weight':83.8, 'BF':16.0, 'RestingHR':56, 'MaxHR':200}, - ) + athletedata['history'] = self.athlete.get_athlete_stats() self.windowmain.actualize_athleteview(athletedata) logging.debug('<<') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-10-12 02:50:04
|
Revision: 653 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=653&view=rev Author: jblance Date: 2010-10-12 02:49:58 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Athlete view - delete record, improved DB access (uses dicts and checks data type) Modified Paths: -------------- pytrainer/trunk/pytrainer/athlete.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/lib/ddbb.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/athlete.py =================================================================== --- pytrainer/trunk/pytrainer/athlete.py 2010-10-11 21:18:37 UTC (rev 652) +++ pytrainer/trunk/pytrainer/athlete.py 2010-10-12 02:49:58 UTC (rev 653) @@ -56,14 +56,15 @@ def get_athlete_stats(self): logging.debug('>>') - stats = [] - results = self.pytrainer_main.ddbb.select("athletestats", "id_athletestat, date, weight, bodyfat, restinghr, maxhr", mod="order by date") + results = self.pytrainer_main.ddbb.select_dict("athletestats", ('id_athletestat', 'date', 'weight', 'bodyfat', 'restinghr', 'maxhr'), mod="order by date") + #Remove None values + for i, row in enumerate(results): + for cell in results[i]: + if results[i][cell] == None: + results[i][cell] = "" logging.debug('Found %d athlete stats results' % len(results)) - for row in results: - date = dateutil.parser.parse(row[1]).date() - stats.append({'id_athletestat': row[0], 'Date': row[1], 'Weight':row[2], 'BF': row[3], 'RestingHR':row[4], 'MaxHR':row[5]}) logging.debug('<<') - return stats + return results def get_athlete_data(self): logging.debug('>>') @@ -71,8 +72,8 @@ graphdata['weight'] = GraphData(title="Weight", xlabel="Date", ylabel="Weight (%s)" % (self.weight_unit)) graphdata['weight'].set_color('#3300FF', '#3300FF') #graphdata['weight'].graphType = 'fill' - graphdata['bf'] = GraphData(title="Body Fat", xlabel="Date", ylabel="Body Fat (%s)" % (self.weight_unit)) - graphdata['bf'].set_color('#FF6600', '#FF6600') + graphdata['bodyfat'] = GraphData(title="Body Fat", xlabel="Date", ylabel="Body Fat (%s)" % (self.weight_unit)) + graphdata['bodyfat'].set_color('#FF6600', '#FF6600') #graphdata['bf'].graphType = 'fill' graphdata['restinghr'] = GraphData(title="Resting Heartrate", xlabel="Date", ylabel="Resting Heartrate (bpm)") graphdata['restinghr'].set_color('#660000', '#660000') @@ -81,32 +82,36 @@ graphdata['maxhr'].set_color('#33CC99', '#33CC99') graphdata['maxhr'].show_on_y2 = True for row in self.data: - date = dateutil.parser.parse(row['Date']).date() - if row['Weight']: - weight = float(row['Weight']) + if not 'date' in row or not row['date']: + continue + if 'weight' in row and row['weight']: + weight = float(row['weight']) else: - weight = None - if row['BF']: - bf = float(row['BF']) / 100 * weight + weight = "" + if 'bodyfat' in row and row['bodyfat'] and weight: + bf = float(row['bodyfat']) / 100 * weight else: - bf = None - graphdata['weight'].addPoints(x=date, y=weight) - graphdata['bf'].addPoints(x=date, y=bf) - graphdata['restinghr'].addPoints(x=date, y=row['RestingHR']) - graphdata['maxhr'].addPoints(x=date, y=row['MaxHR']) + bf = "" + graphdata['weight'].addPoints(x=row['date'], y=weight) + graphdata['bodyfat'].addPoints(x=row['date'], y=bf) + graphdata['restinghr'].addPoints(x=row['date'], y=row['restinghr']) + graphdata['maxhr'].addPoints(x=row['date'], y=row['maxhr']) return graphdata def update_athlete_stats(self, id_athletestat, date, weight, bodyfat, restinghr, maxhr): logging.debug('>>') try: - date = dateutil.parser.parse(date).date() + dateutil.parser.parse(date).date() + logging.debug("update_athlete_stats called with invalid date") + logging.debug('!<<') except ValueError: return - cells = "date, weight, bodyfat, restinghr, maxhr" - values = (date, weight, bodyfat, restinghr, maxhr) - #Update database - self.pytrainer_main.ddbb.update("athletestats",cells,values," id_athletestat=%d" %int(id_athletestat)) + #Update DB + data = {'date': date, 'weight': weight, 'bodyfat': bodyfat, 'restinghr': restinghr, 'maxhr': maxhr} + condition = "id_athletestat=%d" % int(id_athletestat) + self.pytrainer_main.ddbb.update_dict("athletestats",data, condition) + #self.pytrainer_main.ddbb.update("athletestats",cells,values," id_athletestat=%d" %int(id_athletestat)) logging.debug('<<') def insert_athlete_stats(self, date, weight, bodyfat, restinghr, maxhr): @@ -117,11 +122,17 @@ logging.debug('!<<') return try: - date = dateutil.parser.parse(date).date() + dateutil.parser.parse(date).date() except ValueError: + logging.debug("insert_athlete_stats called with invalid date") + logging.debug('!<<') return - cells = "date, weight, bodyfat, restinghr, maxhr" - values = (date, weight, bodyfat, restinghr, maxhr) #Update DB - self.pytrainer_main.ddbb.insert("athletestats",cells,values) + data = {'date': date, 'weight': weight, 'bodyfat': bodyfat, 'restinghr': restinghr, 'maxhr': maxhr} + self.pytrainer_main.ddbb.insert_dict("athletestats",data) logging.debug('<<') + + def delete_record(self, data): + logging.debug('>>') + self.pytrainer_main.ddbb.delete("athletestats","id_athletestat=%d" % int(data)) + logging.debug('<<') Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-11 21:18:37 UTC (rev 652) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-12 02:49:58 UTC (rev 653) @@ -880,8 +880,8 @@ gobject.TYPE_STRING #max HR ) for data in athlete.data: - weight = (data['Weight']) - date = dateutil.parser.parse(data['Date']).date() + weight = data['weight'] + date = data['date'] iter = history_store.append() history_store.set ( @@ -889,9 +889,9 @@ 0, (data['id_athletestat']), 1, date, #TODO need to sort date graphing... 2, weight, - 3, (data['BF']), - 4, (data['RestingHR']), - 5, (data['MaxHR']), + 3, (data['bodyfat']), + 4, (data['restinghr']), + 5, (data['maxhr']), ) self.athleteTreeView.set_model(history_store) self.grapher.drawAthleteGraph(athlete=athlete, box=self.boxAthleteGraph) @@ -1608,14 +1608,45 @@ treeview.grab_focus() treeview.set_cursor(path, col, 0) selected,iter = treeview.get_selection().get_selected() - idx = selected.get_value(iter,0) - date = selected.get_value(iter,1) - weight = selected.get_value(iter,2) - bf = selected.get_value(iter,3) - restingHR = selected.get_value(iter,4) - maxHR = selected.get_value(iter,5) - self.update_athlete_item(idx, date, weight, bf, restingHR, maxHR) - #print path, col, cellx, celly + if event.button == 3: + #Right mouse button... + idx = selected.get_value(iter,0) + date = selected.get_value(iter,1) + #print "show popup etc (clicked on idx %s, date %s)" % (idx, date) + #Show popup menu... + popup = gtk.Menu() + menuitem = gtk.MenuItem(label=_("Delete Entry")) + menuitem.connect("activate", self.on_athleteTreeView_delete, idx) + popup.attach(menuitem, 0, 1, 0, 1) + popup.show_all() + popup.popup( None, None, None, event.button, time) + #self.popup.show(selected.get_value(iter,0), event.button, time) + #self.popup.popup( None, None, None, event_button, time) + else: + #Left mouse - so display this row + idx = selected.get_value(iter,0) + date = selected.get_value(iter,1) + weight = selected.get_value(iter,2) + bf = selected.get_value(iter,3) + restingHR = selected.get_value(iter,4) + maxHR = selected.get_value(iter,5) + self.update_athlete_item(idx, date, weight, bf, restingHR, maxHR) + + def on_athleteTreeView_delete(self, widget, data): + '''User has opted to delete entry''' + logging.debug(">>") + msg = _("Delete this database entry?") + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, msg) + md.set_title(_("Are you sure?")) + response = md.run() + md.destroy() + if response == gtk.RESPONSE_OK: + logging.debug("User confirmed deletion of athlete entry with id: %s" % data) + self.pytrainer_main.athlete.delete_record(data) + self.parent.refreshAthleteView() + else: + logging.debug("User canceled athlete record deletion for id %s" % data) + logging.debug("<<") def on_buttonAthleteNew_clicked(self, widget): #Reset Fields Modified: pytrainer/trunk/pytrainer/lib/ddbb.py =================================================================== --- pytrainer/trunk/pytrainer/lib/ddbb.py 2010-10-11 21:18:37 UTC (rev 652) +++ pytrainer/trunk/pytrainer/lib/ddbb.py 2010-10-12 02:49:58 UTC (rev 653) @@ -22,6 +22,7 @@ import logging import traceback import commands, os +import dateutil from pytrainer.lib.date import Date #Define the tables and their columns that should be in the database @@ -124,37 +125,134 @@ def select(self,table,cells,condition=None, mod=None): return self.ddbbObject.select(table,cells,condition,mod) - def select_dict(self,table,cells,condition=None): + def select_dict(self,table,cells,condition=None, mod=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 + ---- mod - string of select clause modifier, eg "order by date" -- returns ---- list of dicts with cells as keys ''' + logging.debug(">>") + global tablesList 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) + if table in tablesList: + cellString = ','.join(cells) #create cell list string + results = self.ddbbObject.select(table,cellString,condition,mod) + for result in results: + dict = {} + #Loop through cells and create dict of results + for i, cell in enumerate(cells): + #check result is correct type + if cell not in tablesList[table]: + logging.error('select includes invalid cell (%s) for table %s' % (cell, table)) + else: + cell_type = tablesList[table][cell] + dict[cell] = self.parseByCellType(result[i], cell_type) + return_value.append(dict) + else: + logging.error('select on invalid table name') + logging.debug("<<") return return_value + + def parseByCellType(self, value, cell_type): + ''' + Function to validate that value is of type cell_type + ''' + #TODO need to check if multivalue cell type specified + # eg integer primary key autoincrement + #print "Checking if %s is of type %s" % (value, cell_type) + if not value: + return None + elif cell_type.startswith('float'): + try: + result = float(value) + return result + except Exception as e: + print "%s not float" % value + return None + elif cell_type.startswith('int'): + try: + result = int(value) + return result + except Exception as e: + print "%s not int" % value + return None + elif cell_type.startswith('text'): + #Text so is OK?? + #TODO anytests required here?? + return value + elif cell_type.startswith('varchar'): + #Text so is OK?? + #TODO check length against spec? + return value + elif cell_type.startswith('date'): + try: + result = dateutil.parser.parse(value).date() + return result + except Exception as e: + print type(e) + print e + print "%s not date" % value + return None + print "Unknown datatype: (%s) for data (%s)" % (cell_type, value) + return None def insert(self,table,cells,values): self.ddbbObject.insert(table,cells,values) + + def insert_dict(self, table, data): + logging.debug(">>") + global tablesList + if not table or not data or table not in tablesList: + print "insert_dict called with invalid table or no data" + logging.debug("!<<") + return False + cells = [] + values = [] + for cell in data: + cell_type = tablesList[table][cell] + cell_value = self.parseByCellType(data[cell], cell_type) + if cell_value is not None: + cells.append(cell) + values.append(cell_value) + #Create string of cell names for sql... + #TODO fix sql objects so dont need to join... + cells_string = ",".join(cells) + self.ddbbObject.insert(table,cells_string,values) + logging.debug("<<") 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_dict(self, table, data, condition): + logging.debug(">>") + global tablesList + if not table or not data or table not in tablesList: + print "update_dict called with invalid table or no data" + logging.debug("!<<") + return False + cells = [] + values = [] + for cell in data: + cell_type = tablesList[table][cell] + cell_value = self.parseByCellType(data[cell], cell_type) + if cell_value is not None: + cells.append(cell) + values.append(cell_value) + #Create string of cell names for sql... + #TODO fix sql objects so dont need to join... + cells_string = ",".join(cells) + self.ddbbObject.update(table,cells_string,values,condition) + logging.debug("<<") def lastRecord(self,table): id = "id_" + table[:-1] #prune 's' of table name and pre-pend 'id_' to get id column Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-11 21:18:37 UTC (rev 652) +++ pytrainer/trunk/pytrainer/main.py 2010-10-12 02:49:58 UTC (rev 653) @@ -50,7 +50,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#652" + self.version ="1.7.2_svn#653" self.DB_version = 5 #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-12 04:53:08
|
Revision: 654 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=654&view=rev Author: jblance Date: 2010-10-12 04:53:01 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Updated date to _hopefully_ deal with different week start days Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/date.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/lib/date.py =================================================================== --- pytrainer/trunk/pytrainer/lib/date.py 2010-10-12 02:49:58 UTC (rev 653) +++ pytrainer/trunk/pytrainer/lib/date.py 2010-10-12 04:53:01 UTC (rev 654) @@ -24,126 +24,167 @@ import datetime import dateutil.parser from dateutil.tz import * # for tzutc() +from subprocess import Popen, PIPE class Date: - def __init__(self, calendar=None): - self.calendar = calendar - - def second2time(self,seconds): - if not seconds: - return 0,0,0 - time_in_hour = seconds/3600.0 - hour = int(time_in_hour) - min = int((time_in_hour-hour)*60) - sec = (((time_in_hour-hour)*60)-min)*60 - sec = seconds-(hour*3600)-(min*60) - return hour,min,sec + def __init__(self, calendar=None): + self.calendar = calendar + + def second2time(self,seconds): + if not seconds: + return 0,0,0 + time_in_hour = seconds/3600.0 + hour = int(time_in_hour) + min = int((time_in_hour-hour)*60) + sec = (((time_in_hour-hour)*60)-min)*60 + sec = seconds-(hour*3600)-(min*60) + return hour,min,sec - def time2second(self,time): - hour,min,sec = time - return int(sec)+(int(min)*60)+(int(hour)*3600) + def time2second(self,time): + hour,min,sec = time + return int(sec)+(int(min)*60)+(int(hour)*3600) - def getLocalTZ(self): - ''' Returns string representation of local timezone''' - return datetime.datetime.now(tzlocal()).tzname() + def getLocalTZ(self): + ''' Returns string representation of local timezone''' + return datetime.datetime.now(tzlocal()).tzname() - def getDate(self): - #hack for the gtk calendar widget - if self.calendar is not None: - year,month,day = self.calendar.get_date() - return "%0.4d-%0.2d-%0.2d" %(year,month+1,day) - else: - return datetime.date.today().strftime("%Y-%m-%d") + def getDate(self): + #hack for the gtk calendar widget + if self.calendar is not None: + year,month,day = self.calendar.get_date() + return "%0.4d-%0.2d-%0.2d" %(year,month+1,day) + else: + return datetime.date.today().strftime("%Y-%m-%d") - def setDate(self,newdate): - year,month,day = newdate.split("-") - self.calendar.select_month(int(month)-1,int(year)) - self.calendar.select_day(int(day)) - - def time2string(self,date): - return "%0.4d-%0.2d-%0.2d" %(int(date[0]),int(date[1]),int(date[2])) + def setDate(self,newdate): + year,month,day = newdate.split("-") + self.calendar.select_month(int(month)-1,int(year)) + self.calendar.select_day(int(day)) + + def time2string(self,date): + return "%0.4d-%0.2d-%0.2d" %(int(date[0]),int(date[1]),int(date[2])) + + def getFirstDayOfWeek(self): + ''' + Function to determine the first day of the week from the locale + from http://blogs.gnome.org/patrys/2008/09/29/how-to-determine-the-first-day-of-week/ + + $ locale first_weekday week-1stday + 2 + 19971130 + ''' + + CMD=('locale', 'first_weekday', 'week-1stday') + p=Popen(CMD, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + #print "STDOUT\n"+stdout + #print "STDERR\n"+stderr + #print "RETURNCODE: "+str(p.returncode) + if p.returncode != 0: + #Error in command execution + return None + results = stdout.split('\n') + if len(results) < 2: + #print "len error", len(results), results + return None + try: + day_delta = datetime.timedelta(days=int(results[0]) - 1) + base_date = dateutil.parser.parse(results[1]) + first_day = base_date + day_delta + print "First day of week based on locale is:", first_day.strftime("%A") + return first_day + except Exception as e: + print type(e) + print e + return None + + - def getWeekInterval(self,date, prf_us_system): - ''' Function to provide beginning and ending of the week that a certain day is in - Problems as python date functions do not respect locale (i.e. Sunday is always start of week????) - Note: %w gives weekday as a decimal number [0(Sunday),6(Saturday)]. - ''' - if prf_us_system: - #Sunday is first day of week - weekDate = datetime.datetime.strptime(date, "%Y-%m-%d") - dayOfWeek = int(weekDate.strftime("%w")) - else: - #Monday is first day of week - weekDate = datetime.datetime.strptime(date, "%Y-%m-%d") - dayOfWeek = int(weekDate.strftime("%w")) - if dayOfWeek == 0: #Sunday, need to adjust - dayOfWeek = 7 - dayOfWeek -= 1 - date_ini = weekDate + datetime.timedelta(days=0-dayOfWeek) - date_end = weekDate + datetime.timedelta(days=6-dayOfWeek) - return date_ini.strftime("%Y-%m-%d"), date_end.strftime("%Y-%m-%d") - - def getMonthInterval(self,date): - year,month,day = date.split("-") - date_ini = "%0.4d-%0.2d-00" %(int(year),int(month)) - if (int(month)<12): - month = int(month)+1 - else: - year = int(year)+1 - month = 1 - date_end = "%0.4d-%0.2d-01" %(int(year),int(month)) - return date_ini, date_end + def getWeekInterval(self,date, prf_us_system): + ''' Function to provide beginning and ending of the week that a certain day is in + Problems as python date functions do not respect locale (i.e. Sunday is always start of week????) + Note: %w gives weekday as a decimal number [0(Sunday),6(Saturday)]. + ''' + weekDate = datetime.datetime.strptime(date, "%Y-%m-%d") + dayOfWeek = int(weekDate.strftime("%w")) + #print "Today is %s day of the week:" % dayOfWeek + first_day = self.getFirstDayOfWeek().strftime("%w") #0 = Sun is first, 1 = Mon is first, 6 = Sat is first + #first_day = 6 + if first_day is not None: + #got response from locale query... + #print "first day of week is:", first_day + #Adjust dayOfweek... + dayOfWeek -= int(first_day) + if dayOfWeek < 0: + dayOfWeek += 7 + #print "Adjusted today is %s day of the week:" % dayOfWeek + date_ini = weekDate + datetime.timedelta(days=0-dayOfWeek) + date_end = weekDate + datetime.timedelta(days=6-dayOfWeek) + #print "weekrange", date_ini.strftime("%A"), date_end.strftime("%A") + #print "dates", date_ini.strftime("%Y-%m-%d"), date_end.strftime("%Y-%m-%d") + return date_ini.strftime("%Y-%m-%d"), date_end.strftime("%Y-%m-%d") + + def getMonthInterval(self,date): + year,month,day = date.split("-") + date_ini = "%0.4d-%0.2d-00" %(int(year),int(month)) + if (int(month)<12): + month = int(month)+1 + else: + year = int(year)+1 + month = 1 + date_end = "%0.4d-%0.2d-01" %(int(year),int(month)) + return date_ini, date_end - def getYearInterval(self,date): - year,month,day = date.split("-") - date_ini = "%0.4d-0.1-01" %int(year) - year = int(year)+1 - date_end = "%0.4d-01-01" %int(year) - return date_ini, date_end - - def getNameMonth(self, date): - #month_name = { - # "01":_("January"), - # "02":_("Febrary"), - # "03":_("March"), - # "04":_("April"), - # "05":_("May"), - # "06":_("June"), - # "07":_("July"), - # "08":_("August"), - # "09":_("September"), - # "10":_("October"), - # "11":_("November"), - # "12":_("December") - # } - year,month,day = date.split("-") - day, daysInMonth = calendar.monthrange(int(year), int(month)) - monthName = calendar.month_name[int(month)] - return monthName, daysInMonth + def getYearInterval(self,date): + year,month,day = date.split("-") + date_ini = "%0.4d-0.1-01" %int(year) + year = int(year)+1 + date_end = "%0.4d-01-01" %int(year) + return date_ini, date_end + + def getNameMonth(self, date): + #month_name = { + # "01":_("January"), + # "02":_("Febrary"), + # "03":_("March"), + # "04":_("April"), + # "05":_("May"), + # "06":_("June"), + # "07":_("July"), + # "08":_("August"), + # "09":_("September"), + # "10":_("October"), + # "11":_("November"), + # "12":_("December") + # } + year,month,day = date.split("-") + day, daysInMonth = calendar.monthrange(int(year), int(month)) + monthName = calendar.month_name[int(month)] + return monthName, daysInMonth - def getYear(self,date): - year,month,day = date.split("-") - return year + def getYear(self,date): + year,month,day = date.split("-") + return year - def unixtime2date(self,unixtime): - print unixtime - tm = time.gmtime(unixtime) - year = tm[0] - month = tm[1] - day = tm[2] - return "%0.4d-%0.2d-%0.2d" %(year,month,day) + def unixtime2date(self,unixtime): + print unixtime + tm = time.gmtime(unixtime) + year = tm[0] + month = tm[1] + day = tm[2] + return "%0.4d-%0.2d-%0.2d" %(year,month,day) - def getDateTime(self, time_): - # Time can be in multiple formats - # - zulu 2009-12-15T09:00Z - # - local ISO8601 2009-12-15T10:00+01:00 - dateTime = dateutil.parser.parse(time_) - timezone = dateTime.tzname() - if timezone == 'UTC': #got a zulu time - local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) - else: - local_dateTime = dateTime #use datetime as supplied - utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset - #print utc_dateTime, local_dateTime - return (utc_dateTime,local_dateTime) + def getDateTime(self, time_): + # Time can be in multiple formats + # - zulu 2009-12-15T09:00Z + # - local ISO8601 2009-12-15T10:00+01:00 + dateTime = dateutil.parser.parse(time_) + timezone = dateTime.tzname() + if timezone == 'UTC': #got a zulu time + local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) + else: + local_dateTime = dateTime #use datetime as supplied + utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset + #print utc_dateTime, local_dateTime + return (utc_dateTime,local_dateTime) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-12 02:49:58 UTC (rev 653) +++ pytrainer/trunk/pytrainer/main.py 2010-10-12 04:53:01 UTC (rev 654) @@ -50,7 +50,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#653" + self.version ="1.7.2_svn#654" self.DB_version = 5 #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-12 08:47:28
|
Revision: 655 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=655&view=rev Author: jblance Date: 2010-10-12 08:47:22 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Fix Record graphs broken by 654 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-10-12 04:53:01 UTC (rev 654) +++ pytrainer/trunk/pytrainer/lib/ddbb.py 2010-10-12 08:47:22 UTC (rev 655) @@ -141,13 +141,26 @@ return_value = [] #Only query db if table and cells are supplied if table is not None and cells is not None: - if table in tablesList: + if table.find(',') != -1: + #multiple tables in select + #TODO fix so works.... + print 'TODO fix select_dict to work with multiple tables' cellString = ','.join(cells) #create cell list string results = self.ddbbObject.select(table,cellString,condition,mod) for result in results: dict = {} #Loop through cells and create dict of results for i, cell in enumerate(cells): + #cell_type = tablesList[table][cell] + dict[cell] = result[i] + return_value.append(dict) + elif table in tablesList: + cellString = ','.join(cells) #create cell list string + results = self.ddbbObject.select(table,cellString,condition,mod) + for result in results: + dict = {} + #Loop through cells and create dict of results + for i, cell in enumerate(cells): #check result is correct type if cell not in tablesList[table]: logging.error('select includes invalid cell (%s) for table %s' % (cell, table)) @@ -159,7 +172,7 @@ logging.error('select on invalid table name') logging.debug("<<") return return_value - + def parseByCellType(self, value, cell_type): ''' Function to validate that value is of type cell_type @@ -205,7 +218,7 @@ def insert(self,table,cells,values): self.ddbbObject.insert(table,cells,values) - + def insert_dict(self, table, data): logging.debug(">>") global tablesList @@ -221,7 +234,7 @@ if cell_value is not None: cells.append(cell) values.append(cell_value) - #Create string of cell names for sql... + #Create string of cell names for sql... #TODO fix sql objects so dont need to join... cells_string = ",".join(cells) self.ddbbObject.insert(table,cells_string,values) @@ -232,7 +245,7 @@ def update(self,table,cells,value,condition): self.ddbbObject.update(table,cells,value,condition) - + def update_dict(self, table, data, condition): logging.debug(">>") global tablesList @@ -248,7 +261,7 @@ if cell_value is not None: cells.append(cell) values.append(cell_value) - #Create string of cell names for sql... + #Create string of cell names for sql... #TODO fix sql objects so dont need to join... cells_string = ",".join(cells) self.ddbbObject.update(table,cells_string,values,condition) @@ -313,15 +326,15 @@ else: logging.info('Database backup successfully created') logging.debug('<<') - + def checkDBDataValues(self): ''' Check all data in DB and report values that do not match the type ''' global tablesList - + for table in tablesList.keys(): pass - + 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 Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-12 04:53:01 UTC (rev 654) +++ pytrainer/trunk/pytrainer/main.py 2010-10-12 08:47:22 UTC (rev 655) @@ -50,7 +50,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#654" + self.version ="1.7.2_svn#655" self.DB_version = 5 #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-12 09:14:11
|
Revision: 656 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=656&view=rev Author: jblance Date: 2010-10-12 09:14:05 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Fixes to athlete view to account for missing data Modified Paths: -------------- pytrainer/trunk/pytrainer/athlete.py pytrainer/trunk/pytrainer/gui/drawGraph.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/athlete.py =================================================================== --- pytrainer/trunk/pytrainer/athlete.py 2010-10-12 08:47:22 UTC (rev 655) +++ pytrainer/trunk/pytrainer/athlete.py 2010-10-12 09:14:05 UTC (rev 656) @@ -33,12 +33,12 @@ self.data = self.get_athlete_stats() self.graphdata = self.get_athlete_data() logging.debug('<<') - + def refresh(self): self.init_from_conf() self.data = self.get_athlete_stats() self.graphdata = self.get_athlete_data() - + def init_from_conf(self): logging.debug('>>') self.name = self.pytrainer_main.profile.getValue("pytraining","prf_name") @@ -53,7 +53,7 @@ else: self.weight_unit = _("kg") logging.debug('<<') - + def get_athlete_stats(self): logging.debug('>>') results = self.pytrainer_main.ddbb.select_dict("athletestats", ('id_athletestat', 'date', 'weight', 'bodyfat', 'restinghr', 'maxhr'), mod="order by date") @@ -65,16 +65,16 @@ logging.debug('Found %d athlete stats results' % len(results)) logging.debug('<<') return results - + def get_athlete_data(self): logging.debug('>>') graphdata = {} graphdata['weight'] = GraphData(title="Weight", xlabel="Date", ylabel="Weight (%s)" % (self.weight_unit)) graphdata['weight'].set_color('#3300FF', '#3300FF') - #graphdata['weight'].graphType = 'fill' + #graphdata['weight'].graphType = 'date' graphdata['bodyfat'] = GraphData(title="Body Fat", xlabel="Date", ylabel="Body Fat (%s)" % (self.weight_unit)) graphdata['bodyfat'].set_color('#FF6600', '#FF6600') - #graphdata['bf'].graphType = 'fill' + #graphdata['bf'].graphType = 'date' graphdata['restinghr'] = GraphData(title="Resting Heartrate", xlabel="Date", ylabel="Resting Heartrate (bpm)") graphdata['restinghr'].set_color('#660000', '#660000') graphdata['restinghr'].show_on_y2 = True @@ -84,6 +84,8 @@ for row in self.data: if not 'date' in row or not row['date']: continue + else: + date = row['date'] if 'weight' in row and row['weight']: weight = float(row['weight']) else: @@ -92,13 +94,18 @@ bf = float(row['bodyfat']) / 100 * weight else: bf = "" - graphdata['weight'].addPoints(x=row['date'], y=weight) - graphdata['bodyfat'].addPoints(x=row['date'], y=bf) - graphdata['restinghr'].addPoints(x=row['date'], y=row['restinghr']) - graphdata['maxhr'].addPoints(x=row['date'], y=row['maxhr']) + graphdata['weight'].addPoints(x=date, y=weight) + graphdata['bodyfat'].addPoints(x=date, y=bf) + graphdata['restinghr'].addPoints(x=date, y=row['restinghr']) + graphdata['maxhr'].addPoints(x=date, y=row['maxhr']) + #Remove empty data + for item in graphdata.keys(): + if len(graphdata[item]) == 0: + logging.debug( "No values for %s. Removing...." % item ) + del graphdata[item] return graphdata - - + + def update_athlete_stats(self, id_athletestat, date, weight, bodyfat, restinghr, maxhr): logging.debug('>>') try: @@ -113,7 +120,7 @@ self.pytrainer_main.ddbb.update_dict("athletestats",data, condition) #self.pytrainer_main.ddbb.update("athletestats",cells,values," id_athletestat=%d" %int(id_athletestat)) logging.debug('<<') - + def insert_athlete_stats(self, date, weight, bodyfat, restinghr, maxhr): logging.debug('>>') if not date and not weight and not bodyfat and not restinghr and not maxhr: @@ -131,7 +138,7 @@ data = {'date': date, 'weight': weight, 'bodyfat': bodyfat, 'restinghr': restinghr, 'maxhr': maxhr} self.pytrainer_main.ddbb.insert_dict("athletestats",data) logging.debug('<<') - + def delete_record(self, data): logging.debug('>>') self.pytrainer_main.ddbb.delete("athletestats","id_athletestat=%d" % int(data)) Modified: pytrainer/trunk/pytrainer/gui/drawGraph.py =================================================================== --- pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-12 08:47:22 UTC (rev 655) +++ pytrainer/trunk/pytrainer/gui/drawGraph.py 2010-10-12 09:14:05 UTC (rev 656) @@ -65,7 +65,7 @@ if datalist is None: logging.debug("drawPlot called with no data") - return + return figure if y2 and self.ax2 is None: self.ax2 = plt.twinx() @@ -111,11 +111,11 @@ else: self.ax2.axvspan(datalist.x_values[i], datalist.x_values[i]+datalist.bar_widths[i], alpha=0.15, facecolor=datalist.y2linecolor) i += 1 - elif datalist.graphType == "fill": + elif datalist.graphType == "date": if not y2: - self.ax1.fill_between(datalist.x_values, datalist.y_values, color=datalist.linecolor, label=datalist.ylabel, alpha=0.5) + self.ax1.plot_date(datalist.x_values, datalist.y_values, color=datalist.linecolor, label=datalist.ylabel, alpha=0.5) else: - self.ax2.fill_between(datalist.x_values, datalist.y_values, color=datalist.y2linecolor, label=datalist.ylabel, alpha=0.5) + self.ax2.plot_date(datalist.x_values, datalist.y_values, color=datalist.y2linecolor, label=datalist.ylabel, alpha=0.5) else: print "Unknown/unimplemented graph type: %s" % datalist.graphType return figure @@ -151,6 +151,7 @@ #print("drawPlot....") for item in athlete.graphdata: #print "drawing", item + #print athlete.graphdata[item] figure = self.draw(athlete.graphdata[item], box=box, figure=figure, title=_("Athlete Data"), y2=athlete.graphdata[item].show_on_y2) def drawActivityGraph(self, activity = None, box = None): @@ -217,12 +218,12 @@ activity.x_limits = self.ax1.get_xlim() activity.y1_limits = self.ax1.get_ylim() else: - activity.y1_limits = (None, None) + activity.y1_limits = (None, None) if self.ax2 is not None: activity.x_limits = self.ax2.get_xlim() activity.y2_limits = self.ax2.get_ylim() else: - activity.y2_limits = (None, None) + activity.y2_limits = (None, None) #Set axis limits if requested #X Axis if activity.x_limits_u[0] is not None: @@ -238,6 +239,6 @@ if activity.y2_limits_u[0] is not None: if self.ax2 is not None: self.ax2.set_ylim(activity.y2_limits_u) - + return activity logging.debug('<<') Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-12 08:47:22 UTC (rev 655) +++ pytrainer/trunk/pytrainer/main.py 2010-10-12 09:14:05 UTC (rev 656) @@ -50,7 +50,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#655" + self.version ="1.7.2_svn#656" self.DB_version = 5 #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-12 09:24:11
|
Revision: 657 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=657&view=rev Author: jblance Date: 2010-10-12 09:24:04 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Update week numbering to use ISO as per Arnd suggestion 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-10-12 09:14:05 UTC (rev 656) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-10-12 09:24:04 UTC (rev 657) @@ -62,7 +62,7 @@ glade_path="glade/pytrainer.glade" root = "window1" domain = None - + SimpleGladeApp.__init__(self, self.data_path+glade_path, root, domain) self.popup = PopupMenu(data_path,self) @@ -80,7 +80,7 @@ self.y1_linewidth = 1 # setup Search ListView self.listsearch = ListSearch(self, self.pytrainer_main) - + def new(self): self.testimport = self.pytrainer_main.startup_options.testimport self.menublocking = 0 @@ -123,8 +123,8 @@ else: self.radiobuttonGMap.set_active(1) - - + + def _float_or(self, value, default): '''Function to parse and return a float, or the default if the parsing fails''' try: @@ -639,8 +639,8 @@ logging.debug(">>") date_s = datetime.datetime.strptime(date_ini, "%Y-%m-%d") date_e = datetime.datetime.strptime(date_end, "%Y-%m-%d") - self.week_date.set_text("%s - %s (%d)" % (datetime.datetime.strftime(date_s, "%a %d %b"), datetime.datetime.strftime(date_e, "%a %d %b"), int(datetime.datetime.strftime(date_e, "%W"))+1) ) - + #self.week_date.set_text("%s - %s (%d)" % (datetime.datetime.strftime(date_s, "%a %d %b"), datetime.datetime.strftime(date_e, "%a %d %b"), int(datetime.datetime.strftime(date_e, "%W"))+1) ) + self.week_date.set_text("%s - %s (%d)" % (datetime.datetime.strftime(date_s, "%a %d %b"), datetime.datetime.strftime(date_e, "%a %d %b"), int(datetime.datetime.strftime(date_e, "%V"))) ) km = calories = time = average = beats = 0 num_records = len(record_list) logging.info("Number of records selected week: "+str(num_records)) @@ -922,7 +922,7 @@ if hour >0: _hh = "%2d:%02d:%02d" %(hour, min, sec) else: - _hh = "___%2d:%02d" %(min, sec) + _hh = "___%2d:%02d" %(min, sec) #_time =_hh try: _id = int(i[5]) @@ -1053,7 +1053,7 @@ self.listsearch.sport = self.lsa_sport.get_active() self.listsearch.past = self.lsa_past.get_active() self.listsearch.duration = self.lsa_duration.get_active() - self.listsearch.distance = self.lsa_distance.get_active() + self.listsearch.distance = self.lsa_distance.get_active() self.parent.searchListView(self.listsearch.condition) def create_menulist(self,column_names): @@ -1214,7 +1214,7 @@ activity.time_data[item].show_on_y2 = child.get_active() #Replot the activity self.actualize_recordgraph(activity) - + def on_setlimits(self, widget, activity, reset, data): '''Handler for setting graph limits buttons''' if data is None: @@ -1566,6 +1566,8 @@ self.calendar.clear_marks() for i in record_list: self.calendar.mark_day(int(i)) + #display_options = self.calendar.get_display_options() + #self.calendar.set_display_options(display_options|gtk.CALENDAR_SHOW_WEEK_NUMBERS) logging.debug("<<") def on_about_activate(self,widget): @@ -1596,7 +1598,7 @@ def on_recordTree_clicked(self,widget,num,num2): selected,iter = self.recordTreeView.get_selection().get_selected() self.parent.editRecord(selected.get_value(iter,0)) - + ### athleteview events ### def on_athleteTreeView_button_press_event(self, treeview, event): x = int(event.x) @@ -1633,7 +1635,7 @@ self.update_athlete_item(idx, date, weight, bf, restingHR, maxHR) def on_athleteTreeView_delete(self, widget, data): - '''User has opted to delete entry''' + '''User has opted to delete entry''' logging.debug(">>") msg = _("Delete this database entry?") md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, msg) @@ -1647,7 +1649,7 @@ else: logging.debug("User canceled athlete record deletion for id %s" % data) logging.debug("<<") - + def on_buttonAthleteNew_clicked(self, widget): #Reset Fields self.labelAthleteIdx.set_text("") @@ -1656,7 +1658,7 @@ self.entryAthleteBF.set_text("") self.entryAthleteRestingHR.set_text("") self.entryAthleteMaxHR.set_text("") - + def on_buttonAlthleteSave_clicked(self, widget): #Get data in fields id_athletestat = self.labelAthleteIdx.get_text() @@ -1674,7 +1676,7 @@ restinghr = self.entryAthleteRestingHR.get_text() maxhr = self.entryAthleteMaxHR.get_text() #TODO - are any other fields required? - + #Check if an entry has been edited or is a new one if id_athletestat is None or id_athletestat == "": #New entry @@ -1685,11 +1687,11 @@ logging.debug('Updating id_athletestat:%s with values: date %s, weight %s, bodyfat %s, restinghr %s, maxhr %s' % (id_athletestat, date, weight, bodyfat, restinghr, maxhr) ) self.parent.athlete.update_athlete_stats(id_athletestat, date, weight, bodyfat, restinghr, maxhr) self.parent.refreshAthleteView() - + def on_athletecalendar_clicked(self,widget): calendardialog = WindowCalendar(self.data_path,self) calendardialog.run() - + def setDate(self,date): self.entryAthleteDate.set_text(date) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-12 09:14:05 UTC (rev 656) +++ pytrainer/trunk/pytrainer/main.py 2010-10-12 09:24:04 UTC (rev 657) @@ -50,7 +50,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#656" + self.version ="1.7.2_svn#657" self.DB_version = 5 #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-12 09:26:40
|
Revision: 658 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=658&view=rev Author: jblance Date: 2010-10-12 09:26:33 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Arnd added distance options to list view filters Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/listview.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/pytrainer/lib/listview.py =================================================================== --- pytrainer/trunk/pytrainer/lib/listview.py 2010-10-12 09:24:04 UTC (rev 657) +++ pytrainer/trunk/pytrainer/lib/listview.py 2010-10-12 09:26:33 UTC (rev 658) @@ -1,8 +1,8 @@ import datetime import math -LISTPAST = [['All Time', -99999], ['Last 4 Weeks', -31], - ['Last 6 Months', -183], ['Last 12 Months', -366]] +#LISTPAST = [['All Time', -99999], ['Last 4 Weeks', -31], +# ['Last 6 Months', -183], ['Last 12 Months', -366]] class ListSearch(object): """ Builds SQLite condition out of search parameters""" @@ -19,8 +19,15 @@ self.listDuration = [['All Durations', [0,999999]], ['<1 Hour', [0,3600]], ['1-2 Hours', [3600,7200]], - ['>2 Hours', [7200,999999]]] - self.listDistance = self.get_listDistance() + ['>2 Hours', [7200,999999]]] + + self.listDistance = [['All Distances', [0.0,999999.9]], + ['<1 km', [0.0, 1.0]], + ['1-5 km', [1.0, 5.0]], + ['5-20 km', [5.0, 20.0]], + ['20-50 km', [20.0, 50.0]], + ['50-100 km', [50.0, 100.0]], + ['>100 km', [100.0, 999999.9]]] #print self.listDistance self.setup_lsa_sport() self.setup_lsa_past() @@ -60,9 +67,9 @@ else: _search = _here _add_and = True - if self.listDistance[self.sport][self.distance][1]: - _dis_min = int(self.listDistance[self.sport][self.distance][1][0]) - _dis_max = int(self.listDistance[self.sport][self.distance][1][1]) + if self.listDistance[self.distance][1]: + _dis_min = int(self.listDistance[self.distance][1][0]) + _dis_max = int(self.listDistance[self.distance][1][1]) _here = "(distance between %s and %s)" % (_dis_min, _dis_max) if _add_and: _search += " and " + _here @@ -132,7 +139,7 @@ self.parent.lsa_distance.set_active(0) firstEntry = self.parent.lsa_distance.get_active_text() liststore_lsa.clear() #Delete all items - for i in self.listDistance[self.sport]: + for i in self.listDistance: liststore_lsa.append([i[0]]) self.parent.lsa_distance.set_active(0) #Add handler manually, so above changes do not trigger recursive loop Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-12 09:24:04 UTC (rev 657) +++ pytrainer/trunk/pytrainer/main.py 2010-10-12 09:26:33 UTC (rev 658) @@ -50,7 +50,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#657" + self.version ="1.7.2_svn#658" self.DB_version = 5 #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-12 10:30:58
|
Revision: 660 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=660&view=rev Author: jblance Date: 2010-10-12 10:30:51 +0000 (Tue, 12 Oct 2010) Log Message: ----------- Fix for GPX files with no lap info Modified Paths: -------------- pytrainer/trunk/pytrainer/lib/gpx.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Modified: pytrainer/trunk/pytrainer/lib/gpx.py =================================================================== --- pytrainer/trunk/pytrainer/lib/gpx.py 2010-10-12 09:56:48 UTC (rev 659) +++ pytrainer/trunk/pytrainer/lib/gpx.py 2010-10-12 10:30:51 UTC (rev 660) @@ -49,373 +49,382 @@ distanceTag = gpxdataNS.substitute(tag="distance") class Gpx: - def __init__(self, data_path = None, filename = None, trkname = None): - logging.debug(">>") - #print("GPX init-ing") - global mainNS, timeTag, trackTag, trackPointTag, trackPointTagLast, trackSegTag, elevationTag, nameTag - self.data_path = data_path - self.filename = filename - self.trkname = trkname - logging.debug(str(data_path)+"|"+str(filename)+"|"+str(trkname)) - self.trkpoints = [] - self.vel_array = [] - self.total_dist = 0 - self.total_time = 0 - self.upositive = 0 - self.unegative = 0 - self.maxvel = 0 - self.maxhr = 0 - self.hr_average = 0 - self.date = "" - #self.Date = Date() - self.calories= 0 - self.tree = None - if filename != None: - if not os.path.isfile(self.filename): - return None - logging.debug("parsing content from "+self.filename) - self.tree = etree.ElementTree(file=filename).getroot() - if self.tree.get("version") == "1.0": - #Got an old GPX file - logging.debug("Old gpx version") - mainNS = string.Template(".//{http://www.topografix.com/GPX/1/0}$tag") - timeTag = mainNS.substitute(tag="time") - trackTag = mainNS.substitute(tag="trk") - trackPointTag = mainNS.substitute(tag="trkpt") - trackPointTagLast = mainNS.substitute(tag="trkpt[last()]") - trackSegTag = mainNS.substitute(tag="trkseg") - elevationTag = mainNS.substitute(tag="ele") - nameTag = mainNS.substitute(tag="name") - else: - logging.debug("Importing version %s gpx file" % self.tree.get("version")) - mainNS = string.Template(".//{http://www.topografix.com/GPX/1/1}$tag") - timeTag = mainNS.substitute(tag="time") - trackTag = mainNS.substitute(tag="trk") - trackPointTag = mainNS.substitute(tag="trkpt") - trackPointTagLast = mainNS.substitute(tag="trkpt[last()]") - trackSegTag = mainNS.substitute(tag="trkseg") - elevationTag = mainNS.substitute(tag="ele") - nameTag = mainNS.substitute(tag="name") + def __init__(self, data_path = None, filename = None, trkname = None): + logging.debug(">>") + #print("GPX init-ing") + global mainNS, timeTag, trackTag, trackPointTag, trackPointTagLast, trackSegTag, elevationTag, nameTag + self.data_path = data_path + self.filename = filename + self.trkname = trkname + logging.debug(str(data_path)+"|"+str(filename)+"|"+str(trkname)) + self.trkpoints = [] + self.vel_array = [] + self.total_dist = 0 + self.total_time = 0 + self.upositive = 0 + self.unegative = 0 + self.maxvel = 0 + self.maxhr = 0 + self.hr_average = 0 + self.date = "" + #self.Date = Date() + self.calories= 0 + self.tree = None + if filename != None: + if not os.path.isfile(self.filename): + return None + logging.debug("parsing content from "+self.filename) + self.tree = etree.ElementTree(file=filename).getroot() + if self.tree.get("version") == "1.0": + #Got an old GPX file + logging.debug("Old gpx version") + mainNS = string.Template(".//{http://www.topografix.com/GPX/1/0}$tag") + timeTag = mainNS.substitute(tag="time") + trackTag = mainNS.substitute(tag="trk") + trackPointTag = mainNS.substitute(tag="trkpt") + trackPointTagLast = mainNS.substitute(tag="trkpt[last()]") + trackSegTag = mainNS.substitute(tag="trkseg") + elevationTag = mainNS.substitute(tag="ele") + nameTag = mainNS.substitute(tag="name") + else: + logging.debug("Importing version %s gpx file" % self.tree.get("version")) + mainNS = string.Template(".//{http://www.topografix.com/GPX/1/1}$tag") + timeTag = mainNS.substitute(tag="time") + trackTag = mainNS.substitute(tag="trk") + trackPointTag = mainNS.substitute(tag="trkpt") + trackPointTagLast = mainNS.substitute(tag="trkpt[last()]") + trackSegTag = mainNS.substitute(tag="trkseg") + elevationTag = mainNS.substitute(tag="ele") + nameTag = mainNS.substitute(tag="name") - logging.debug("getting values...") - self.Values = self._getValues() - logging.debug("<<") + logging.debug("getting values...") + self.Values = self._getValues() + logging.debug("<<") - def getMaxValues(self): - return self.total_dist, self.total_time, self.maxvel, self.maxhr + def getMaxValues(self): + return self.total_dist, self.total_time, self.maxvel, self.maxhr - def getDate(self): - return self.date + def getDate(self): + return self.date - def getTrackRoutes(self): - trks = self.tree.findall(trackTag) - tracks = [] - retorno = [] - for trk in trks: - nameResult = trk.find(nameTag) - if nameResult is not None: - name = nameResult.text - else: - name = _("No Name") - timeResult = trk.find(timeTag) - if timeResult is not None: - time_ = timeResult.text # check timezone - mk_time = self.getDateTime(time_)[0] - time_ = mk_time.strftime("%Y-%m-%d") - else: - time_ = _("No Data") - logging.debug("name: "+name+" | time: "+time_) - tracks.append((name,time_)) - return tracks + def getTrackRoutes(self): + trks = self.tree.findall(trackTag) + tracks = [] + retorno = [] + for trk in trks: + nameResult = trk.find(nameTag) + if nameResult is not None: + name = nameResult.text + else: + name = _("No Name") + timeResult = trk.find(timeTag) + if timeResult is not None: + time_ = timeResult.text # check timezone + mk_time = self.getDateTime(time_)[0] + time_ = mk_time.strftime("%Y-%m-%d") + else: + time_ = _("No Data") + logging.debug("name: "+name+" | time: "+time_) + tracks.append((name,time_)) + return tracks - def getDateTime(self, time_): - return Date().getDateTime(time_) + def getDateTime(self, time_): + return Date().getDateTime(time_) - def getUnevenness(self): - return self.upositive,self.unegative + def getUnevenness(self): + return self.upositive,self.unegative - def getTrackList(self): - return self.Values + def getTrackList(self): + return self.Values - def getHeartRateAverage(self): - return self.hr_average + def getHeartRateAverage(self): + return self.hr_average - def getCalories(self): - return self.calories + def getCalories(self): + return self.calories - def getLaps(self): - logging.debug(">>") - lapInfo = [] - if self.tree is None: - return lapInfo - tree = self.tree - laps = tree.findall(lapTag) - logging.debug("Found %d laps" % len(laps)) - for lap in laps: - endPoint = lap.find(endPointTag) - lat = endPoint.get("lat") - lon = endPoint.get("lon") - startPoint = lap.find(startPointTag) - if startPoint is not None: - stLat = startPoint.get("lat") - stLon = startPoint.get("lon") - else: - stLat, stLon = "","" - elapsedTime = lap.findtext(elapsedTimeTag) - if elapsedTime.count(":") == 2: # got a 0:41:42.14 type elasped time - hours, mins, secs = elapsedTime.split(":") - elapsedTime = (int(hours) *3600) + (int(mins) * 60) + float(secs) - #print elapsedTime - calories = lap.findtext(calorieTag) - distance = lap.findtext(distanceTag) - logging.debug("Found time: %s, lat: %s lon: %s cal: %s dist: %s " % (elapsedTime, lat, lon, calories, distance)) - lapInfo.append((elapsedTime, lat, lon, calories, distance, stLat, stLon)) - logging.debug("<<") - return lapInfo + def getLaps(self): + logging.debug(">>") + lapInfo = [] + if self.tree is None: + return lapInfo + tree = self.tree + laps = tree.findall(lapTag) + logging.debug("Found %d laps" % len(laps)) + if len(laps) == 0: + #Found no laps, so add single lap with totals + stLat = self.trkpoints[0]['lat'] + stLon = self.trkpoints[0]['lon'] + lat = self.trkpoints[-1]['lat'] + lon = self.trkpoints[-1]['lon'] + #print ((self.total_time, lat, lon, self.calories, self.total_dist, stLat, stLon)) + lapInfo.append((self.total_time, lat, lon, self.calories, self.total_dist*1000, stLat, stLon)) + else: + for lap in laps: + endPoint = lap.find(endPointTag) + lat = endPoint.get("lat") + lon = endPoint.get("lon") + startPoint = lap.find(startPointTag) + if startPoint is not None: + stLat = startPoint.get("lat") + stLon = startPoint.get("lon") + else: + stLat, stLon = "","" + elapsedTime = lap.findtext(elapsedTimeTag) + if elapsedTime.count(":") == 2: # got a 0:41:42.14 type elasped time + hours, mins, secs = elapsedTime.split(":") + elapsedTime = (int(hours) *3600) + (int(mins) * 60) + float(secs) + #print elapsedTime + calories = lap.findtext(calorieTag) + distance = lap.findtext(distanceTag) + logging.debug("Found time: %s, lat: %s lon: %s cal: %s dist: %s " % (elapsedTime, lat, lon, calories, distance)) + lapInfo.append((elapsedTime, lat, lon, calories, distance, stLat, stLon)) + logging.debug("<<") + return lapInfo - def _getValues(self): - ''' - Migrated to eTree XML processing 26 Nov 2009 - jblance - ''' - logging.debug(">>") - tree = self.tree - # Calories data comes within laps. Maybe more than one, adding them together - dgranda 20100114 - laps = tree.findall(lapTag) - if laps is not None and laps != "": - for lap in laps: - lapCalories = lap.findtext(calorieTag) - logging.debug("Lap calories: "+str(lapCalories)) - self.calories += int(lapCalories) - logging.debug("Calories: "+str(self.calories)) - else: - laps = [] + def _getValues(self): + ''' + Migrated to eTree XML processing 26 Nov 2009 - jblance + ''' + logging.debug(">>") + tree = self.tree + # Calories data comes within laps. Maybe more than one, adding them together - dgranda 20100114 + laps = tree.findall(lapTag) + if laps is not None and laps != "": + for lap in laps: + lapCalories = lap.findtext(calorieTag) + logging.debug("Lap calories: "+str(lapCalories)) + self.calories += int(lapCalories) + logging.debug("Calories: "+str(self.calories)) + else: + laps = [] - retorno = [] - his_vel = [] - last_lat = None - last_lon = None - last_time = None - total_dist = 0 - dist_elapsed = 0 # distance since the last time found - total_hr = 0 - tmp_alt = 0 - len_validhrpoints = 0 - trkpoints = tree.findall(trackPointTag) - if trkpoints is None or len(trkpoints) == 0: - logging.debug( "No trkpoints found in file") - return retorno - logging.debug("%d trkpoints in file" % len(trkpoints)) + retorno = [] + his_vel = [] + last_lat = None + last_lon = None + last_time = None + total_dist = 0 + dist_elapsed = 0 # distance since the last time found + total_hr = 0 + tmp_alt = 0 + len_validhrpoints = 0 + trkpoints = tree.findall(trackPointTag) + if trkpoints is None or len(trkpoints) == 0: + logging.debug( "No trkpoints found in file") + return retorno + logging.debug("%d trkpoints in file" % len(trkpoints)) - date_ = tree.find(timeTag).text - #mk_time = self.getDateTime(date_)[0] #UTC Date - mk_time = self.getDateTime(date_)[1] #Local Date - self.date = mk_time.strftime("%Y-%m-%d") - waiting_points = [] + date_ = tree.find(timeTag).text + #mk_time = self.getDateTime(date_)[0] #UTC Date + mk_time = self.getDateTime(date_)[1] #Local Date + self.date = mk_time.strftime("%Y-%m-%d") + waiting_points = [] - for i, trkpoint in enumerate(trkpoints): - #Get data from trkpoint - try: - lat = float(trkpoint.get("lat")) - lon = float(trkpoint.get("lon")) - except Exception as e: - logging.debug(str(e)) - lat = lon = None - if lat is None or lat == "" or lat == 0 or lon is None or lon == "" or lon == 0: - logging.debug("lat or lon is blank or zero") - continue - #get the heart rate value from the gpx extended format file - hrResult = trkpoint.find(hrTag) - if hrResult is not None: - hr = int(hrResult.text) - len_validhrpoints += 1 - total_hr += hr #TODO fix - if hr>self.maxhr: - self.maxhr = hr - else: - hr = None - #get the cadence (if present) - cadResult = trkpoint.find(cadTag) - if cadResult is not None: - cadence = int(cadResult.text) - else: - cadence = None - #get the time - timeResult = trkpoint.find(timeTag) - if timeResult is not None: - date_ = timeResult.text - mk_time = self.getDateTime(date_)[0] - time_ = time.mktime(mk_time.timetuple()) #Convert date to seconds - if i == 0: - time_elapsed = 0 - else: - time_elapsed = time_ - self.trkpoints[i-1]['time'] if self.trkpoints[i-1]['time'] is not None else 0 - self.total_time += time_elapsed - else: - time_ = None - time_elapsed = None - #get the elevation - eleResult = trkpoint.find(elevationTag) - rel_alt = 0 - if eleResult is not None: - try: - ele = float(eleResult.text) - #Calculate elevation change - if i != 0: - rel_alt = ele - self.trkpoints[i-1]['ele'] if self.trkpoints[i-1]['ele'] is not None else 0 - except Exception as e: - logging.debug(str(e)) - ele = None - else: - ele = None + for i, trkpoint in enumerate(trkpoints): + #Get data from trkpoint + try: + lat = float(trkpoint.get("lat")) + lon = float(trkpoint.get("lon")) + except Exception as e: + logging.debug(str(e)) + lat = lon = None + if lat is None or lat == "" or lat == 0 or lon is None or lon == "" or lon == 0: + logging.debug("lat or lon is blank or zero") + continue + #get the heart rate value from the gpx extended format file + hrResult = trkpoint.find(hrTag) + if hrResult is not None: + hr = int(hrResult.text) + len_validhrpoints += 1 + total_hr += hr #TODO fix + if hr>self.maxhr: + self.maxhr = hr + else: + hr = None + #get the cadence (if present) + cadResult = trkpoint.find(cadTag) + if cadResult is not None: + cadence = int(cadResult.text) + else: + cadence = None + #get the time + timeResult = trkpoint.find(timeTag) + if timeResult is not None: + date_ = timeResult.text + mk_time = self.getDateTime(date_)[0] + time_ = time.mktime(mk_time.timetuple()) #Convert date to seconds + if i == 0: + time_elapsed = 0 + else: + time_elapsed = time_ - self.trkpoints[i-1]['time'] if self.trkpoints[i-1]['time'] is not None else 0 + self.total_time += time_elapsed + else: + time_ = None + time_elapsed = None + #get the elevation + eleResult = trkpoint.find(elevationTag) + rel_alt = 0 + if eleResult is not None: + try: + ele = float(eleResult.text) + #Calculate elevation change + if i != 0: + rel_alt = ele - self.trkpoints[i-1]['ele'] if self.trkpoints[i-1]['ele'] is not None else 0 + except Exception as e: + logging.debug(str(e)) + ele = None + else: + ele = None - #Calculate climb or decent amount - #Allow for some 'jitter' in height here - JITTER_VALUE = 0 #Elevation changes less than this value are not counted in +- - if abs(rel_alt) < JITTER_VALUE: - rel_alt = 0 - if rel_alt > 0: - self.upositive += rel_alt - elif rel_alt < 0: - self.unegative -= rel_alt + #Calculate climb or decent amount + #Allow for some 'jitter' in height here + JITTER_VALUE = 0 #Elevation changes less than this value are not counted in +- + if abs(rel_alt) < JITTER_VALUE: + rel_alt = 0 + if rel_alt > 0: + self.upositive += rel_alt + elif rel_alt < 0: + self.unegative -= rel_alt - #Calculate distance between two points - if i == 0: #First point - dist = None - else: - dist = self._distance_between_points(lat1=self.trkpoints[i-1]['lat'], lon1=self.trkpoints[i-1]['lon'], lat2=lat, lon2=lon) + #Calculate distance between two points + if i == 0: #First point + dist = None + else: + dist = self._distance_between_points(lat1=self.trkpoints[i-1]['lat'], lon1=self.trkpoints[i-1]['lon'], lat2=lat, lon2=lon) - #Accumulate distances - if dist is not None: - dist_elapsed += dist #TODO fix - total_dist += dist + #Accumulate distances + if dist is not None: + dist_elapsed += dist #TODO fix + total_dist += dist - #Calculate speed... - vel = self._calculate_speed(dist, time_elapsed, smoothing_factor=3) - if vel>self.maxvel: - self.maxvel=vel + #Calculate speed... + vel = self._calculate_speed(dist, time_elapsed, smoothing_factor=3) + if vel>self.maxvel: + self.maxvel=vel - #The waiting point stuff.... - #This 'fills in' the data for situations where some times are missing from the GPX file - if time_ is not None: - if len(waiting_points) > 0: - for ((w_total_dist, w_dist, w_alt, w_total_time, w_lat, w_lon, w_hr, w_cadence)) in waiting_points: - w_time = (w_dist/dist_elapsed) * time_elapsed - w_vel = w_dist/((w_time)/3600.0) - w_total_time += w_time - retorno.append((w_total_dist, w_alt, w_total_time, w_vel, w_lat, w_lon, w_hr, w_cadence)) - waiting_points = [] - dist_elapsed = 0 - else: - retorno.append((total_dist,ele, self.total_time,vel,lat,lon,hr,cadence)) - dist_elapsed = 0 - else: # time_ is None - waiting_points.append((total_dist, dist_elapsed, ele, self.total_time, lat, lon, hr, cadence)) + #The waiting point stuff.... + #This 'fills in' the data for situations where some times are missing from the GPX file + if time_ is not None: + if len(waiting_points) > 0: + for ((w_total_dist, w_dist, w_alt, w_total_time, w_lat, w_lon, w_hr, w_cadence)) in waiting_points: + w_time = (w_dist/dist_elapsed) * time_elapsed + w_vel = w_dist/((w_time)/3600.0) + w_total_time += w_time + retorno.append((w_total_dist, w_alt, w_total_time, w_vel, w_lat, w_lon, w_hr, w_cadence)) + waiting_points = [] + dist_elapsed = 0 + else: + retorno.append((total_dist,ele, self.total_time,vel,lat,lon,hr,cadence)) + dist_elapsed = 0 + else: # time_ is None + waiting_points.append((total_dist, dist_elapsed, ele, self.total_time, lat, lon, hr, cadence)) - #Add to dict of values to trkpoint list - self.trkpoints.append({ 'id': i, - 'lat':lat, - 'lon':lon, - 'hr':hr, - 'cadence':cadence, - 'time':time_, - 'time_since_previous': time_elapsed, - 'time_elapsed': self.total_time, - 'ele':ele, - 'ele_change': rel_alt, - 'distance_from_previous': dist, - 'elapsed_distance': total_dist, - 'velocity':vel, + #Add to dict of values to trkpoint list + self.trkpoints.append({ 'id': i, + 'lat':lat, + 'lon':lon, + 'hr':hr, + 'cadence':cadence, + 'time':time_, + 'time_since_previous': time_elapsed, + 'time_elapsed': self.total_time, + 'ele':ele, + 'ele_change': rel_alt, + 'distance_from_previous': dist, + 'elapsed_distance': total_dist, + 'velocity':vel, - }) + }) - #end of for trkpoint in trkpoints loop + #end of for trkpoint in trkpoints loop - #Calculate averages etc - self.hr_average = 0 - if len_validhrpoints > 0: - self.hr_average = total_hr/len_validhrpoints - self.total_dist = total_dist - logging.debug("<<") - return retorno + #Calculate averages etc + self.hr_average = 0 + if len_validhrpoints > 0: + self.hr_average = total_hr/len_validhrpoints + self.total_dist = total_dist + logging.debug("<<") + return retorno - def _distance_between_points(self, lat1, lon1, lat2, lon2): - ''' - Function to calculate the distance between two lat, lon points on the earths surface + def _distance_between_points(self, lat1, lon1, lat2, lon2): + ''' + Function to calculate the distance between two lat, lon points on the earths surface - History of this function is unknown.... - -- David "no me mates que esto lo escribi hace anhos" - -- http://faculty.washington.edu/blewis/ocn499/EXER04.htm equation for the distance between 2 points on a spherical earth - -- 0.01745329252 = number of radians in a degree - -- 57.29577951 = 1/0.01745329252 or degrees per radian - requires - - start lat and lon as floats - - finish lat and lon as floats + History of this function is unknown.... + -- David "no me mates que esto lo escribi hace anhos" + -- http://faculty.washington.edu/blewis/ocn499/EXER04.htm equation for the distance between 2 points on a spherical earth + -- 0.01745329252 = number of radians in a degree + -- 57.29577951 = 1/0.01745329252 or degrees per radian + requires + - start lat and lon as floats + - finish lat and lon as floats - returns - - distance between points in kilometers if successful - - None if any error situation occurs - ''' - RADIANS_PER_DEGREE = 0.01745329252 - DEGREES_PER_RADIAN = 57.29577951 - #Check for invalid variables - for var in (lat1, lon1, lat2, lon2): - if var is None or var == 0 or var == "": #TODO Need this?? if (float(lat) < -0.000001) or (float(lat) > 0.0000001): - return None - if type(var) is not type(float()): - return None - #Convert lat and lon from degrees to radians - last_lat = lat1*RADIANS_PER_DEGREE - last_lon = lon1*RADIANS_PER_DEGREE - tmp_lat = lat2*RADIANS_PER_DEGREE - tmp_lon = lon2*RADIANS_PER_DEGREE - #Pasamos la distancia de radianes a metros.. creo / We convert the distance from radians to meters - try: - dist=math.acos((math.sin(last_lat)*math.sin(tmp_lat))+(math.cos(last_lat)*math.cos(tmp_lat)*math.cos(tmp_lon-last_lon)))*111.302*DEGREES_PER_RADIAN - except Exception as e: - logging.debug(str(e)) - dist=None - return dist + returns + - distance between points in kilometers if successful + - None if any error situation occurs + ''' + RADIANS_PER_DEGREE = 0.01745329252 + DEGREES_PER_RADIAN = 57.29577951 + #Check for invalid variables + for var in (lat1, lon1, lat2, lon2): + if var is None or var == 0 or var == "": #TODO Need this?? if (float(lat) < -0.000001) or (float(lat) > 0.0000001): + return None + if type(var) is not type(float()): + return None + #Convert lat and lon from degrees to radians + last_lat = lat1*RADIANS_PER_DEGREE + last_lon = lon1*RADIANS_PER_DEGREE + tmp_lat = lat2*RADIANS_PER_DEGREE + tmp_lon = lon2*RADIANS_PER_DEGREE + #Pasamos la distancia de radianes a metros.. creo / We convert the distance from radians to meters + try: + dist=math.acos((math.sin(last_lat)*math.sin(tmp_lat))+(math.cos(last_lat)*math.cos(tmp_lat)*math.cos(tmp_lon-last_lon)))*111.302*DEGREES_PER_RADIAN + except Exception as e: + logging.debug(str(e)) + dist=None + return dist - def _calculate_speed(self, dist_elapsed, time_elapsed, smoothing_factor=3): - '''Function to calculate moving average for speed''' + def _calculate_speed(self, dist_elapsed, time_elapsed, smoothing_factor=3): + '''Function to calculate moving average for speed''' - if dist_elapsed is None or dist_elapsed == 0 or time_elapsed is None or time_elapsed == 0: - velocity = 0 - else: - velocity = (dist_elapsed/time_elapsed) * 3600 # 3600 to convert km/sec to km/hour - self.vel_array.append(velocity) - if len(self.vel_array)>smoothing_factor: - self.vel_array.pop(0) - if len(self.vel_array)<smoothing_factor: - #Got too few numbers to average - #Pad with duplicates - for x in range(len(self.vel_array), smoothing_factor): - self.vel_array.append(velocity) - vel = 0 - for v in self.vel_array: - vel+= v - vel /= smoothing_factor - return vel + if dist_elapsed is None or dist_elapsed == 0 or time_elapsed is None or time_elapsed == 0: + velocity = 0 + else: + velocity = (dist_elapsed/time_elapsed) * 3600 # 3600 to convert km/sec to km/hour + self.vel_array.append(velocity) + if len(self.vel_array)>smoothing_factor: + self.vel_array.pop(0) + if len(self.vel_array)<smoothing_factor: + #Got too few numbers to average + #Pad with duplicates + for x in range(len(self.vel_array), smoothing_factor): + self.vel_array.append(velocity) + vel = 0 + for v in self.vel_array: + vel+= v + vel /= smoothing_factor + return vel - def getStartTimeFromGPX(self, gpxFile): - '''03.05.2008 - dgranda - Retrieves start time from a given gpx file - args: - - gpxFile: path to xml file (gpx format) - returns: tuple (string with start time as UTC timezone - 2008-03-22T12:17:43Z, datetime of time in local timezone) - ''' - logging.debug(">>") - date_time = self.tree.find(timeTag) #returns first instance found - if date_time is None: - print "Problems when retrieving start time from "+gpxFile+". Please check data integrity" - return 0 - dateTime = self.getDateTime(date_time.text) - zuluDateTime = dateTime[0].strftime("%Y-%m-%dT%H:%M:%SZ") - localDateTime = dateTime[1] - logging.debug(gpxFile+" | "+ date_time.text +" | " + zuluDateTime + " | " + str(localDateTime)) - #print localDateTime - #return date_time.text - logging.debug("<<") - return (zuluDateTime, localDateTime) + def getStartTimeFromGPX(self, gpxFile): + '''03.05.2008 - dgranda + Retrieves start time from a given gpx file + args: + - gpxFile: path to xml file (gpx format) + returns: tuple (string with start time as UTC timezone - 2008-03-22T12:17:43Z, datetime of time in local timezone) + ''' + logging.debug(">>") + date_time = self.tree.find(timeTag) #returns first instance found + if date_time is None: + print "Problems when retrieving start time from "+gpxFile+". Please check data integrity" + return 0 + dateTime = self.getDateTime(date_time.text) + zuluDateTime = dateTime[0].strftime("%Y-%m-%dT%H:%M:%SZ") + localDateTime = dateTime[1] + logging.debug(gpxFile+" | "+ date_time.text +" | " + zuluDateTime + " | " + str(localDateTime)) + #print localDateTime + #return date_time.text + logging.debug("<<") + return (zuluDateTime, localDateTime) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-10-12 09:56:48 UTC (rev 659) +++ pytrainer/trunk/pytrainer/main.py 2010-10-12 10:30:51 UTC (rev 660) @@ -50,7 +50,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.2_svn#658" + self.version ="1.7.2_svn#660" self.DB_version = 5 #Process command line options self.startup_options = self.get_options() Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-10-12 09:56:48 UTC (rev 659) +++ pytrainer/trunk/pytrainer/record.py 2010-10-12 10:30:51 UTC (rev 660) @@ -117,7 +117,7 @@ ) logging.debug('<<') return cells,values - + def pace_to_float(self, value): '''Take a mm:ss or mm.ss and return float''' value = value.replace(':', '.') @@ -126,7 +126,7 @@ except ValueError: value = None return value - + def pace_from_float(self, value): '''Helper to generate mm:ss from float representation mm.ss (or mm,ss?)''' #Check that value supplied is a float @@ -336,6 +336,7 @@ "record=\"%s\"" % id_record) if laps is None or laps == []: #No laps stored - update DB logging.debug("No laps in DB for record %d" % id_record) + #print ("No laps in DB for record %d" % id_record) gpx_dest = self.pytrainer_main.profile.gpxdir gpxfile = gpx_dest+"/%d.gpx"%id_record gpx = Gpx(self.data_path,gpxfile) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |